Merge "Drop product config include tags" into main
diff --git a/core/Makefile b/core/Makefile
index 02deadd..9845437 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4369,7 +4369,7 @@
 INSTALLED_PVMFW_EMBEDDED_AVBKEY_TARGET := $(PRODUCT_OUT)/pvmfw_embedded.avbpubkey
 INSTALLED_PVMFW_BINARY_TARGET := $(call module-target-built-files,pvmfw_bin)
 INTERNAL_PVMFWIMAGE_FILES := $(call module-target-built-files,pvmfw_img)
-INTERNAL_PVMFW_EMBEDDED_AVBKEY := $(call module-target-built-files,pvmfw_embedded_key)
+INTERNAL_PVMFW_EMBEDDED_AVBKEY := $(call module-target-built-files,pvmfw_embedded_key_pub_bin)
 INTERNAL_PVMFW_SYMBOL := $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/pvmfw
 
 $(call declare-1p-container,$(INSTALLED_PVMFWIMAGE_TARGET),)
@@ -4919,7 +4919,7 @@
   $(if $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST),\
     $(hide) $(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
         $(AVBTOOL) extract_public_key --key $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH) \
-            --output $(1)/$(partition).avbpubkey;)) \
+            --output $(1)/$(partition).avbpubkey;))
   $(if $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),\
     $(hide) $(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS), \
         $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_KEY_PATH) \
@@ -7605,6 +7605,7 @@
 sdk_dep_file := $(sdk_dir)/sdk_deps.mk
 
 ATREE_FILES :=
+include development/build/tools/sdk-preprocess-files.mk
 -include $(sdk_dep_file)
 
 # if we don't have a real list, then use "everything"
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index c43081e..274a7de 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -77,6 +77,12 @@
 $(call add_soong_config_var_value,ANDROID,avf_enabled,$(PRODUCT_AVF_ENABLED))
 endif
 
+# Enable AVF remote attestation according to the flag value if PRODUCT_AVF_REMOTE_ATTESTATION_DISABLED is not
+# set to true explicitly.
+ifneq (true,$(PRODUCT_AVF_REMOTE_ATTESTATION_DISABLED))
+  $(call add_soong_config_var_value,ANDROID,avf_remote_attestation_enabled,$(RELEASE_AVF_ENABLE_REMOTE_ATTESTATION))
+endif
+
 ifdef PRODUCT_AVF_MICRODROID_GUEST_GKI_VERSION
 $(call add_soong_config_var_value,ANDROID,avf_microdroid_guest_gki_version,$(PRODUCT_AVF_MICRODROID_GUEST_GKI_VERSION))
 endif
@@ -95,6 +101,8 @@
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_llpvm_changes,$(RELEASE_AVF_ENABLE_LLPVM_CHANGES))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_multi_tenant_microdroid_vm,$(RELEASE_AVF_ENABLE_MULTI_TENANT_MICRODROID_VM))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_network,$(RELEASE_AVF_ENABLE_NETWORK))
+# TODO(b/341292601): This flag is needed until the V release. We with clean it up after V together
+# with most of the release_avf_ flags here.
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_remote_attestation,$(RELEASE_AVF_ENABLE_REMOTE_ATTESTATION))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_vendor_modules,$(RELEASE_AVF_ENABLE_VENDOR_MODULES))
 $(call add_soong_config_var_value,ANDROID,release_avf_enable_virt_cpufreq,$(RELEASE_AVF_ENABLE_VIRT_CPUFREQ))
@@ -103,11 +111,15 @@
 
 $(call add_soong_config_var_value,ANDROID,release_binder_death_recipient_weak_from_jni,$(RELEASE_BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI))
 
+$(call add_soong_config_var_value,ANDROID,release_libpower_no_lock_binder_txn,$(RELEASE_LIBPOWER_NO_LOCK_BINDER_TXN))
+
 $(call add_soong_config_var_value,ANDROID,release_package_libandroid_runtime_punch_holes,$(RELEASE_PACKAGE_LIBANDROID_RUNTIME_PUNCH_HOLES))
 
 $(call add_soong_config_var_value,ANDROID,release_selinux_data_data_ignore,$(RELEASE_SELINUX_DATA_DATA_IGNORE))
-
-$(call add_soong_config_var_value,ANDROID,release_write_appcompat_override_system_properties,$(RELEASE_WRITE_APPCOMPAT_OVERRIDE_SYSTEM_PROPERTIES))
+ifneq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)))
+    # write appcompat system properties on userdebug and eng builds
+    $(call add_soong_config_var_value,ANDROID,release_write_appcompat_override_system_properties,true)
+endif
 
 # Enable system_server optimizations by default unless explicitly set or if
 # there may be dependent runtime jars.
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 9c7e906..86028a9 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -768,6 +768,10 @@
       $(LOCAL_BUILT_MODULE):$(dir)/$(my_installed_module_stem)))) \
   $(eval my_compat_dist_config_$(suite) := ))
 
+ifneq (,$(LOCAL_SOONG_CLASSES_JAR))
+    $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+      $(eval my_compat_api_map_$(suite) += $(LOCAL_SOONG_CLASSES_JAR)))
+endif
 
 # Auto-generate build config.
 ifeq (,$(test_config))
@@ -821,6 +825,12 @@
       $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
         $(s):$(dir)/$(n)))))
 
+  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+     $(eval my_compat_api_map_$(suite) += $(foreach f, $(LOCAL_COMPATIBILITY_SUPPORT_FILES), \
+       $(eval p := $(subst :,$(space),$(f))) \
+       $(eval s := $(word 1,$(p))) \
+       $(if $(filter %.apk,$(s)) $(filter %.jar,$(s)),$(s),))))
+
   ifneq (,$(test_config))
     $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
       $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
@@ -863,7 +873,9 @@
       $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data)))) \
     $(eval my_compat_dist_test_data_$(suite) += \
       $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
-        $(filter $(my_installed_test_data),$(call append-path,$(dir),$(file)))))))
+        $(filter $(my_installed_test_data),$(call append-path,$(dir),$(file))))) \
+    $(eval my_compat_api_map_$(suite) += \
+      $(if $(filter %.apk,$(src_path)) $(filter %.jar,$(src_path)),$(src_path),))))
 endif
 else
 ifneq ($(my_test_data_file_pairs),)
@@ -873,7 +885,9 @@
   $(eval file := $(word 2,$(parts))) \
   $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
     $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
-      $(src_path):$(call append-path,$(dir),$(file))))))
+      $(src_path):$(call append-path,$(dir),$(file)))) \
+    $(eval my_compat_api_map_$(suite) += \
+      $(if $(filter %.apk,$(src_path)) $(filter %.jar,$(src_path)),$(src_path),))))
 endif
 endif
 
@@ -885,7 +899,8 @@
 $(call create-suite-dependencies)
 $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
   $(eval my_compat_dist_config_$(suite) := ) \
-  $(eval my_compat_dist_test_data_$(suite) := ))
+  $(eval my_compat_dist_test_data_$(suite) := ) \
+  $(eval my_compat_api_map_$(suite) := ))
 
 endif  # LOCAL_UNINSTALLABLE_MODULE
 
@@ -1108,6 +1123,7 @@
     $(LOCAL_JNI_SHARED_LIBRARIES)
 
 endif
+ALL_MODULES.$(my_register_name).TEST_MODULE_CONFIG_BASE := $(LOCAL_TEST_MODULE_CONFIG_BASE)
 
 ##########################################################################
 ## When compiling against API imported module, use API import stub
diff --git a/core/check_elf_file.mk b/core/check_elf_file.mk
index b5be81f..ec3c4b0 100644
--- a/core/check_elf_file.mk
+++ b/core/check_elf_file.mk
@@ -7,9 +7,12 @@
 #
 # Inputs:
 # - LOCAL_ALLOW_UNDEFINED_SYMBOLS
+# - LOCAL_IGNORE_MAX_PAGE_SIZE
 # - LOCAL_BUILT_MODULE
 # - LOCAL_IS_HOST_MODULE
 # - LOCAL_MODULE_CLASS
+# - TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE
+# - TARGET_MAX_PAGE_SIZE_SUPPORTED
 # - intermediates
 # - my_installed_module_stem
 # - my_prebuilt_src_file
@@ -26,6 +29,21 @@
 # In addition to $(my_check_elf_file_shared_lib_files), some file paths are
 # added by `resolve-shared-libs-for-elf-file-check` from `core/main.mk`.
 $(check_elf_files_stamp): PRIVATE_SHARED_LIBRARY_FILES := $(my_check_elf_file_shared_lib_files)
+
+# For different page sizes to work, we must support a larger max page size
+# as well as properly reflect page size at runtime. Limit this check, since many
+# devices set the max page size (for future proof) than actually use the
+# larger page size.
+ifeq ($(strip $(TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE)),true)
+ifeq ($(strip $(LOCAL_IGNORE_MAX_PAGE_SIZE)),true)
+$(check_elf_files_stamp): PRIVATE_MAX_PAGE_SIZE :=
+else
+$(check_elf_files_stamp): PRIVATE_MAX_PAGE_SIZE := $(TARGET_MAX_PAGE_SIZE_SUPPORTED)
+endif
+else
+$(check_elf_files_stamp): PRIVATE_MAX_PAGE_SIZE :=
+endif
+
 $(check_elf_files_stamp): $(my_prebuilt_src_file) $(my_check_elf_file_shared_lib_files) $(CHECK_ELF_FILE) $(LLVM_READOBJ)
 	@echo Check prebuilt ELF binary: $<
 	$(hide) mkdir -p $(dir $@)
@@ -33,6 +51,7 @@
 	$(hide) $(CHECK_ELF_FILE) \
 	    --skip-bad-elf-magic \
 	    --skip-unknown-elf-machine \
+	    $(if $(PRIVATE_MAX_PAGE_SIZE),--max-page-size=$(PRIVATE_MAX_PAGE_SIZE)) \
 	    $(if $(PRIVATE_SONAME),--soname $(PRIVATE_SONAME)) \
 	    $(foreach l,$(PRIVATE_SHARED_LIBRARY_FILES),--shared-lib $(l)) \
 	    $(foreach l,$(PRIVATE_SYSTEM_SHARED_LIBRARIES),--system-shared-lib $(l)) \
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index fb42878..6192690 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -106,6 +106,7 @@
 LOCAL_HEADER_LIBRARIES:=
 LOCAL_HOST_PREFIX:=
 LOCAL_HOST_REQUIRED_MODULES:=
+LOCAL_IGNORE_MAX_PAGE_SIZE:=
 LOCAL_INIT_RC:=
 LOCAL_INJECT_BSSL_HASH:=
 LOCAL_INSTALLED_MODULE:=
@@ -259,6 +260,7 @@
 LOCAL_SOONG_HEADER_JAR :=
 LOCAL_SOONG_INSTALL_PAIRS :=
 LOCAL_SOONG_INSTALL_SYMLINKS :=
+LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES:=
 LOCAL_SOONG_INSTALLED_MODULE :=
 LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=
 LOCAL_SOONG_LICENSE_METADATA :=
@@ -297,6 +299,7 @@
 LOCAL_TEST_DATA_BINS:=
 LOCAL_TEST_MAINLINE_MODULES:=
 LOCAL_TEST_MODULE_TO_PROGUARD_WITH:=
+LOCAL_TEST_MODULE_CONFIG_BASE:=
 LOCAL_TIDY:=
 LOCAL_TIDY_CHECKS:=
 LOCAL_TIDY_FLAGS:=
diff --git a/core/config.mk b/core/config.mk
index ce11b1d..43304d5 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -419,6 +419,13 @@
 endif
 .KATI_READONLY := TARGET_MAX_PAGE_SIZE_SUPPORTED
 
+ifdef PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE
+  TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE := $(PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE)
+else
+  TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE := false
+endif
+.KATI_READONLY := TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE
+
 # Boolean variable determining if AOSP relies on bionic's PAGE_SIZE macro.
 ifdef PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO
   TARGET_NO_BIONIC_PAGE_SIZE_MACRO := $(PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO)
@@ -1248,14 +1255,12 @@
 
 include $(BUILD_SYSTEM)/dumpvar.mk
 
-ifneq ($(KEEP_VNDK),true)
 ifdef BOARD_VNDK_VERSION
 BOARD_VNDK_VERSION=
 endif
 ifdef PLATFORM_VNDK_VERSION
 PLATFORM_VNDK_VERSION=
 endif
-endif
 
 ifeq (true,$(FULL_SYSTEM_OPTIMIZE_JAVA))
 ifeq (false,$(SYSTEM_OPTIMIZE_JAVA))
diff --git a/core/definitions.mk b/core/definitions.mk
index 40b7980..dde0aa9 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -3589,11 +3589,14 @@
   $(if $(filter $(suite),$(ALL_COMPATIBILITY_SUITES)),,\
     $(eval ALL_COMPATIBILITY_SUITES += $(suite)) \
     $(eval COMPATIBILITY.$(suite).FILES :=) \
-    $(eval COMPATIBILITY.$(suite).MODULES :=)) \
+    $(eval COMPATIBILITY.$(suite).MODULES :=) \
+    $(eval COMPATIBILITY.$(suite).API_MAP_FILES :=)) \
   $(eval COMPATIBILITY.$(suite).FILES += \
     $$(foreach f,$$(my_compat_dist_$(suite)),$$(call word-colon,2,$$(f))) \
     $$(foreach f,$$(my_compat_dist_config_$(suite)),$$(call word-colon,2,$$(f))) \
     $$(my_compat_dist_test_data_$(suite))) \
+  $(eval COMPATIBILITY.$(suite).API_MAP_FILES += $$(my_compat_api_map_$(suite))) \
+  $(eval COMPATIBILITY.$(suite).SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES += $(LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) \
   $(eval ALL_COMPATIBILITY_DIST_FILES += $$(my_compat_dist_$(suite))) \
   $(eval COMPATIBILITY.$(suite).MODULES += $$(my_register_name))) \
 $(eval $(my_all_targets) : \
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 151591e..08e2da3 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -202,6 +202,12 @@
 endif
 ifneq (,$(LOCAL_COMPATIBILITY_SUITE))
   LOCAL_ENFORCE_USES_LIBRARIES := false
+
+  # Enable the check for WTS
+  ifneq ($(filter wts,$(LOCAL_COMPATIBILITY_SUITE)),)
+    LOCAL_ENFORCE_USES_LIBRARIES := true
+  endif
+
 endif
 
 # Disable the check if the app contains no java code.
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 3271079..c063f60 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -50,13 +50,6 @@
 # Release config
 include $(BUILD_SYSTEM)/release_config.mk
 
-# Set default value of KEEP_VNDK.
-ifeq ($(RELEASE_DEPRECATE_VNDK),true)
-  KEEP_VNDK ?= false
-else
-  KEEP_VNDK ?= true
-endif
-
 # ---------------------------------------------------------------
 # Set up version information
 include $(BUILD_SYSTEM)/version_util.mk
@@ -82,7 +75,7 @@
 # ---------------------------------------------------------------
 # The product defaults to generic on hardware
 ifeq ($(TARGET_PRODUCT),)
-TARGET_PRODUCT := aosp_arm
+TARGET_PRODUCT := aosp_arm64
 endif
 
 
diff --git a/core/product.mk b/core/product.mk
index d9e70db..17e117d 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -32,6 +32,7 @@
 # PRODUCT_MAX_PAGE_SIZE_SUPPORTED=65536, the possible values for PAGE_SIZE could be
 # 4096, 16384 and 65536.
 _product_single_value_vars += PRODUCT_MAX_PAGE_SIZE_SUPPORTED
+_product_single_value_vars += PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE
 
 # Boolean variable determining if AOSP relies on bionic's PAGE_SIZE macro.
 _product_single_value_vars += PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO
@@ -423,6 +424,9 @@
 # If true, installs a full version of com.android.virt APEX.
 _product_single_value_vars += PRODUCT_AVF_ENABLED
 
+# If false, disable the AVF remote attestaton feature.
+_product_single_value_vars += PRODUCT_AVF_REMOTE_ATTESTATION_DISABLED
+
 # If true, kernel with modules will be used for Microdroid VMs.
 _product_single_value_vars += PRODUCT_AVF_KERNEL_MODULES_ENABLED
 
diff --git a/core/release_config.mk b/core/release_config.mk
index e3ec3a0..2898868 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -49,9 +49,6 @@
 
 # If this is a google source tree, restrict it to only the one file
 # which has OWNERS control.  If it isn't let others define their own.
-# TODO: Remove wildcard for build/release one when all branch manifests
-# have updated.
-_must_protobuf :=
 config_map_files := $(wildcard build/release/release_config_map.mk) \
     $(wildcard vendor/google_shared/build/release/release_config_map.mk) \
     $(if $(wildcard vendor/google/release/release_config_map.mk), \
@@ -64,7 +61,7 @@
         ) \
     )
 
-protobuf_map_files := $(wildcard build/release/release_config_map.textproto) \
+protobuf_map_files := build/release/release_config_map.textproto \
     $(wildcard vendor/google_shared/build/release/release_config_map.textproto) \
     $(if $(wildcard vendor/google/release/release_config_map.textproto), \
         vendor/google/release/release_config_map.textproto, \
@@ -76,6 +73,9 @@
         ) \
     )
 
+# Remove support for the legacy approach.
+_must_protobuf := true
+
 # PRODUCT_RELEASE_CONFIG_MAPS is set by Soong using an initial run of product
 # config to capture only the list of config maps needed by the build.
 # Keep them in the order provided, but remove duplicates.
@@ -130,7 +130,9 @@
         # Disable the build flag in release-config.
         _args += --guard=false
     endif
-    _flags_file:=$(OUT_DIR)/soong/release-config/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).vars
+    _args += --allow-missing=true
+    _flags_dir:=$(OUT_DIR)/soong/release-config
+    _flags_file:=$(_flags_dir)/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).vars
     # release-config generates $(_flags_varmk)
     _flags_varmk:=$(_flags_file:.vars=.varmk)
     $(shell $(OUT_DIR)/release-config $(_args) >$(OUT_DIR)/release-config.out && touch -t 200001010000 $(_flags_varmk))
@@ -138,7 +140,7 @@
     ifneq (,$(_final_product_config_pass))
         # Save the final version of the config.
         $(shell if ! cmp --quiet $(_flags_varmk) $(_flags_file); then cp $(_flags_varmk) $(_flags_file); fi)
-        # This will also set _all_release_configs and _used_files for us.
+        # This will also set ALL_RELEASE_CONFIGS_FOR_PRODUCT and _used_files for us.
         $(eval include $(_flags_file))
         $(KATI_extra_file_deps $(OUT_DIR)/release-config $(protobuf_map_files) $(_flags_file))
     else
@@ -148,7 +150,24 @@
     _used_files :=
     ifeq (,$(_must_protobuf)$(RELEASE_BUILD_FLAGS_IN_PROTOBUF))
         _use_protobuf :=
+    else
+        _base_all_release := all_release_configs-$(TARGET_PRODUCT)
+        $(call dist-for-goals,droid,\
+            $(_flags_dir)/$(_base_all_release).pb:build_flags/all_release_configs.pb \
+            $(_flags_dir)/$(_base_all_release).textproto:build_flags/all_release_configs.textproto \
+            $(_flags_dir)/$(_base_all_release).json:build_flags/all_release_configs.json \
+            $(_flags_dir)/inheritance_graph-$(TARGET_PRODUCT).dot:build_flags/inheritance_graph-$(TARGET_PRODUCT).dot \
+        )
+# These are always created, add an empty rule for them to keep ninja happy.
+$(_flags_dir)/inheritance_graph-$(TARGET_PRODUCT).dot:
+	: created by $(OUT_DIR)/release-config
+$(_flags_dir)/$(_base_all_release).pb $(_flags_dir)/$(_base_all_release).textproto $(_flags_dir)/$(_base_all_release).json:
+	: created by $(OUT_DIR)/release-config
+        _base_all_release :=
     endif
+    _flags_dir:=
+    _flags_file:=
+    _flags_varmk:=
 endif
 ifeq (,$(_use_protobuf))
     # The .mk files are the canonical source of truth.
@@ -199,9 +218,9 @@
         $(error declare-release-config: config $(strip $(1)) must have release config files, override another release config, or both) \
     )
     $(if $(strip $(4)),$(eval _all_release_configs.$(strip $(1)).ALIAS := true))
-    $(eval _all_release_configs := $(sort $(_all_release_configs) $(strip $(1))))
+    $(eval ALL_RELEASE_CONFIGS_FOR_PRODUCT := $(sort $(ALL_RELEASE_CONFIGS_FOR_PRODUCT) $(strip $(1))))
     $(if $(strip $(3)), \
-      $(if $(filter $(_all_release_configs), $(strip $(3))),
+      $(if $(filter $(ALL_RELEASE_CONFIGS_FOR_PRODUCT), $(strip $(3))),
         $(if $(filter $(_all_release_configs.$(strip $(1)).OVERRIDES),$(strip $(3))),,
           $(eval _all_release_configs.$(strip $(1)).OVERRIDES := $(_all_release_configs.$(strip $(1)).OVERRIDES) $(strip $(3)))), \
         $(error No release config $(strip $(3))) \
@@ -227,13 +246,13 @@
 FLAG_DECLARATION_FILES :=
 
 # Verify that all inherited/overridden release configs are declared.
-$(foreach config,$(_all_release_configs),\
+$(foreach config,$(ALL_RELEASE_CONFIGS_FOR_PRODUCT),\
   $(foreach r,$(all_release_configs.$(r).OVERRIDES),\
     $(if $(strip $(_all_release_configs.$(r).FILES)$(_all_release_configs.$(r).OVERRIDES)),,\
     $(error Release config $(config) [declared in: $(_all_release_configs.$(r).DECLARED_IN)] inherits from non-existent $(r).)\
 )))
 # Verify that alias configs do not have config files.
-$(foreach r,$(_all_release_configs),\
+$(foreach r,$(ALL_RELEASE_CONFIGS_FOR_PRODUCT),\
   $(if $(_all_release_configs.$(r).ALIAS),$(if $(_all_release_configs.$(r).FILES),\
     $(error Alias release config "$(r)" may not specify release config files $(_all_release_configs.$(r).FILES))\
 )))
@@ -248,7 +267,7 @@
     # if the variable was completely unset.
     TARGET_RELEASE ?= was_unset
     ifeq ($(TARGET_RELEASE),was_unset)
-        $(error No release config set for target; please set TARGET_RELEASE, or if building on the command line use 'lunch <target>-<release>-<build_type>', where release is one of: $(_all_release_configs))
+        $(error No release config set for target; please set TARGET_RELEASE, or if building on the command line use 'lunch <target>-<release>-<build_type>', where release is one of: $(ALL_RELEASE_CONFIGS_FOR_PRODUCT))
     endif
     # Instead of leaving this string empty, we want to default to a valid
     # setting.  Full builds coming through this path is a bug, but in case
@@ -259,8 +278,8 @@
 # During pass 1 of product config, using a non-existent release config is not an error.
 # We can safely assume that we are doing pass 1 if DUMP_MANY_VARS=="PRODUCT_RELEASE_CONFIG_MAPS".
 ifneq (,$(_final_product_config_pass))
-    ifeq ($(filter $(_all_release_configs), $(TARGET_RELEASE)),)
-        $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(_all_release_configs))
+    ifeq ($(filter $(ALL_RELEASE_CONFIGS_FOR_PRODUCT), $(TARGET_RELEASE)),)
+        $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(ALL_RELEASE_CONFIGS_FOR_PRODUCT))
     endif
 endif
 
@@ -309,14 +328,13 @@
 .KATI_READONLY := TARGET_RELEASE
 
 ifeq (,$(_use_protobuf))
-$(foreach config, $(_all_release_configs), \
+$(foreach config, $(ALL_RELEASE_CONFIGS_FOR_PRODUCT), \
     $(eval _all_release_configs.$(config).DECLARED_IN:= ) \
     $(eval _all_release_configs.$(config).FILES:= ) \
 )
 applied_releases:=
 # use makefiles
 endif
-_all_release_configs:=
 config_map_files:=
 protobuf_map_files:=
 
@@ -363,3 +381,4 @@
 _can_protobuf :=
 _must_protobuf :=
 _use_protobuf :=
+
diff --git a/core/soong_config.mk b/core/soong_config.mk
index da0ece1..dd7e4e6 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -144,8 +144,6 @@
 $(call add_json_list, NativeCoveragePaths,               $(NATIVE_COVERAGE_PATHS))
 $(call add_json_list, NativeCoverageExcludePaths,        $(NATIVE_COVERAGE_EXCLUDE_PATHS))
 
-$(call add_json_bool, SamplingPGO,                       $(filter true,$(SAMPLING_PGO)))
-
 $(call add_json_bool, ArtUseReadBarrier,                 $(call invert_bool,$(filter false,$(PRODUCT_ART_USE_READ_BARRIER))))
 $(call add_json_str,  BtConfigIncludeDir,                $(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR))
 $(call add_json_list, DeviceKernelHeaders,               $(TARGET_DEVICE_KERNEL_HEADERS) $(TARGET_BOARD_KERNEL_HEADERS) $(TARGET_PRODUCT_KERNEL_HEADERS))
@@ -167,7 +165,6 @@
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
 $(call add_json_list, ApexBootJars,                      $(filter-out $(APEX_BOOT_JARS_EXCLUDED), $(PRODUCT_APEX_BOOT_JARS)))
 
-$(call add_json_bool, VndkUseCoreVariant,                $(TARGET_VNDK_USE_CORE_VARIANT))
 $(call add_json_bool, VndkSnapshotBuildArtifacts,        $(VNDK_SNAPSHOT_BUILD_ARTIFACTS))
 
 $(call add_json_map,  BuildFlags)
@@ -205,9 +202,6 @@
 $(call add_json_bool, Uml,                               $(filter true,$(TARGET_USER_MODE_LINUX)))
 $(call add_json_str,  VendorPath,                        $(TARGET_COPY_OUT_VENDOR))
 $(call add_json_str,  OdmPath,                           $(TARGET_COPY_OUT_ODM))
-$(call add_json_str,  VendorDlkmPath,                    $(TARGET_COPY_OUT_VENDOR_DLKM))
-$(call add_json_str,  OdmDlkmPath,                       $(TARGET_COPY_OUT_ODM_DLKM))
-$(call add_json_str,  SystemDlkmPath,                    $(TARGET_COPY_OUT_SYSTEM_DLKM))
 $(call add_json_str,  ProductPath,                       $(TARGET_COPY_OUT_PRODUCT))
 $(call add_json_str,  SystemExtPath,                     $(TARGET_COPY_OUT_SYSTEM_EXT))
 $(call add_json_bool, MinimizeJavaDebugInfo,             $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
@@ -288,7 +282,7 @@
 $(call add_json_bool, BoardMoveRecoveryResourcesToVendorBoot, $(filter true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT)))
 $(call add_json_str,  PrebuiltHiddenApiDir, $(BOARD_PREBUILT_HIDDENAPI_DIR))
 
-$(call add_json_str,  ShippingApiLevel, $(PRODUCT_SHIPPING_API_LEVEL))
+$(call add_json_str,  Shipping_api_level, $(PRODUCT_SHIPPING_API_LEVEL))
 
 $(call add_json_list, BuildBrokenPluginValidation,         $(BUILD_BROKEN_PLUGIN_VALIDATION))
 $(call add_json_bool, BuildBrokenClangProperty,            $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
@@ -332,73 +326,10 @@
 
 $(call add_json_bool, ReleaseDefaultModuleBuildFromSource,   $(RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE))
 
-$(call add_json_bool, KeepVndk, $(filter true,$(KEEP_VNDK)))
-
 $(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
 
 $(call add_json_bool, BuildIgnoreApexContributionContents, $(PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS))
 
-$(call add_json_map, PartitionVarsForBazelMigrationOnlyDoNotUse)
-  $(call add_json_str,  ProductDirectory,    $(dir $(INTERNAL_PRODUCT)))
-
-  $(call add_json_map,PartitionQualifiedVariables)
-  $(foreach image_type,SYSTEM VENDOR CACHE USERDATA PRODUCT SYSTEM_EXT OEM ODM VENDOR_DLKM ODM_DLKM SYSTEM_DLKM, \
-    $(call add_json_map,$(call to-lower,$(image_type))) \
-    $(call add_json_bool, BuildingImage, $(filter true,$(BUILDING_$(image_type)_IMAGE))) \
-    $(call add_json_str, BoardErofsCompressor, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESSOR)) \
-    $(call add_json_str, BoardErofsCompressHints, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESS_HINTS)) \
-    $(call add_json_str, BoardErofsPclusterSize, $(BOARD_$(image_type)IMAGE_EROFS_PCLUSTER_SIZE)) \
-    $(call add_json_str, BoardExtfsInodeCount, $(BOARD_$(image_type)IMAGE_EXTFS_INODE_COUNT)) \
-    $(call add_json_str, BoardExtfsRsvPct, $(BOARD_$(image_type)IMAGE_EXTFS_RSV_PCT)) \
-    $(call add_json_str, BoardF2fsSloadCompressFlags, $(BOARD_$(image_type)IMAGE_F2FS_SLOAD_COMPRESS_FLAGS)) \
-    $(call add_json_str, BoardFileSystemCompress, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_COMPRESS)) \
-    $(call add_json_str, BoardFileSystemType, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_TYPE)) \
-    $(call add_json_str, BoardJournalSize, $(BOARD_$(image_type)IMAGE_JOURNAL_SIZE)) \
-    $(call add_json_str, BoardPartitionReservedSize, $(BOARD_$(image_type)IMAGE_PARTITION_RESERVED_SIZE)) \
-    $(call add_json_str, BoardPartitionSize, $(BOARD_$(image_type)IMAGE_PARTITION_SIZE)) \
-    $(call add_json_str, BoardSquashfsBlockSize, $(BOARD_$(image_type)IMAGE_SQUASHFS_BLOCK_SIZE)) \
-    $(call add_json_str, BoardSquashfsCompressor, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR)) \
-    $(call add_json_str, BoardSquashfsCompressorOpt, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR_OPT)) \
-    $(call add_json_str, BoardSquashfsDisable4kAlign, $(BOARD_$(image_type)IMAGE_SQUASHFS_DISABLE_4K_ALIGN)) \
-    $(call add_json_str, ProductBaseFsPath, $(PRODUCT_$(image_type)_BASE_FS_PATH)) \
-    $(call add_json_str, ProductHeadroom, $(PRODUCT_$(image_type)_HEADROOM)) \
-    $(call add_json_str, ProductVerityPartition, $(PRODUCT_$(image_type)_VERITY_PARTITION)) \
-    $(call add_json_str, BoardAvbAddHashtreeFooterArgs, $(BOARD_AVB_$(image_type)_ADD_HASHTREE_FOOTER_ARGS)) \
-    $(call add_json_str, BoardAvbKeyPath, $(BOARD_AVB_$(image_type)_KEY_PATH)) \
-    $(call add_json_str, BoardAvbAlgorithm, $(BOARD_AVB_$(image_type)_ALGORITHM)) \
-    $(call add_json_str, BoardAvbRollbackIndex, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX)) \
-    $(call add_json_str, BoardAvbRollbackIndexLocation, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX_LOCATION)) \
-    $(call end_json_map) \
-  )
-  $(call end_json_map)
-
-  $(call add_json_bool, TargetUserimagesUseExt2, $(filter true,$(TARGET_USERIMAGES_USE_EXT2)))
-  $(call add_json_bool, TargetUserimagesUseExt3, $(filter true,$(TARGET_USERIMAGES_USE_EXT3)))
-  $(call add_json_bool, TargetUserimagesUseExt4, $(filter true,$(TARGET_USERIMAGES_USE_EXT4)))
-
-  $(call add_json_bool, TargetUserimagesSparseExtDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)))
-  $(call add_json_bool, TargetUserimagesSparseErofsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EROFS_DISABLED)))
-  $(call add_json_bool, TargetUserimagesSparseSquashfsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED)))
-  $(call add_json_bool, TargetUserimagesSparseF2fsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_F2FS_DISABLED)))
-
-  $(call add_json_str, BoardErofsCompressor, $(BOARD_EROFS_COMPRESSOR))
-  $(call add_json_str, BoardErofsCompressorHints, $(BOARD_EROFS_COMPRESS_HINTS))
-  $(call add_json_str, BoardErofsPclusterSize, $(BOARD_EROFS_PCLUSTER_SIZE))
-  $(call add_json_str, BoardErofsShareDupBlocks, $(BOARD_EROFS_SHARE_DUP_BLOCKS))
-  $(call add_json_str, BoardErofsUseLegacyCompression, $(BOARD_EROFS_USE_LEGACY_COMPRESSION))
-  $(call add_json_str, BoardExt4ShareDupBlocks, $(BOARD_EXT4_SHARE_DUP_BLOCKS))
-  $(call add_json_str, BoardFlashLogicalBlockSize, $(BOARD_FLASH_LOGICAL_BLOCK_SIZE))
-  $(call add_json_str, BoardFlashEraseBlockSize, $(BOARD_FLASH_ERASE_BLOCK_SIZE))
-
-  $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
-  $(call add_json_bool, ProductUseDynamicPartitionSize, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)))
-  $(call add_json_bool, CopyImagesForTargetFilesZip, $(filter true,$(COPY_IMAGES_FOR_TARGET_FILES_ZIP)))
-
-  $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
-
-  $(call add_json_list, ProductPackages, $(sort $(PRODUCT_PACKAGES)))
-$(call end_json_map)
-
 $(call add_json_bool, BuildFromSourceStub, $(findstring true,$(PRODUCT_BUILD_FROM_SOURCE_STUB) $(BUILD_FROM_SOURCE_STUB)))
 
 $(call add_json_bool, HiddenapiExportableStubs, $(filter true,$(PRODUCT_HIDDEN_API_EXPORTABLE_STUBS)))
diff --git a/core/tasks/device-platinum-tests.mk b/core/tasks/device-platinum-tests.mk
index 270248c..75f4c4c 100644
--- a/core/tasks/device-platinum-tests.mk
+++ b/core/tasks/device-platinum-tests.mk
@@ -15,20 +15,23 @@
 
 .PHONY: device-platinum-tests
 
-device-platinum-tests-zip := $(PRODUCT_OUT)/device-platinum-tests.zip
+device_platinum_tests_zip := $(PRODUCT_OUT)/device-platinum-tests.zip
 # Create an artifact to include a list of test config files in device-platinum-tests.
-device-platinum-tests-list-zip := $(PRODUCT_OUT)/device-platinum-tests_list.zip
+device_platinum_tests_list_zip := $(PRODUCT_OUT)/device-platinum-tests_list.zip
 # Create an artifact to include all test config files in device-platinum-tests.
-device-platinum-tests-configs-zip := $(PRODUCT_OUT)/device-platinum-tests_configs.zip
+device_platinum_tests_configs_zip := $(PRODUCT_OUT)/device-platinum-tests_configs.zip
 my_host_shared_lib_for_device_platinum_tests := $(call copy-many-files,$(COMPATIBILITY.device-platinum-tests.HOST_SHARED_LIBRARY.FILES))
 device_platinum_tests_host_shared_libs_zip := $(PRODUCT_OUT)/device-platinum-tests_host-shared-libs.zip
 
-$(device-platinum-tests-zip) : .KATI_IMPLICIT_OUTPUTS := $(device-platinum-tests-list-zip) $(device-platinum-tests-configs-zip) $(device_platinum_tests_host_shared_libs_zip)
-$(device-platinum-tests-zip) : PRIVATE_device_platinum_tests_list := $(PRODUCT_OUT)/device-platinum-tests_list
-$(device-platinum-tests-zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_device_platinum_tests)
-$(device-platinum-tests-zip) : PRIVATE_device_host_shared_libs_zip := $(device_platinum_tests_host_shared_libs_zip)
-$(device-platinum-tests-zip) : $(COMPATIBILITY.device-platinum-tests.FILES) $(my_host_shared_lib_for_device_platinum_tests) $(SOONG_ZIP)
+$(device_platinum_tests_zip) : .KATI_IMPLICIT_OUTPUTS := $(device_platinum_tests_list_zip) $(device_platinum_tests_configs_zip) $(device_platinum_tests_host_shared_libs_zip)
+$(device_platinum_tests_zip) : PRIVATE_device_platinum_tests_list_zip := $(device_platinum_tests_list_zip)
+$(device_platinum_tests_zip) : PRIVATE_device_platinum_tests_configs_zip := $(device_platinum_tests_configs_zip)
+$(device_platinum_tests_zip) : PRIVATE_device_platinum_tests_list := $(PRODUCT_OUT)/device-platinum-tests_list
+$(device_platinum_tests_zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_device_platinum_tests)
+$(device_platinum_tests_zip) : PRIVATE_device_host_shared_libs_zip := $(device_platinum_tests_host_shared_libs_zip)
+$(device_platinum_tests_zip) : $(COMPATIBILITY.device-platinum-tests.FILES) $(my_host_shared_lib_for_device_platinum_tests) $(SOONG_ZIP)
 	rm -f $@-shared-libs.list
+	rm -f $(PRIVATE_device_platinum_tests_list_zip)
 	echo $(sort $(COMPATIBILITY.device-platinum-tests.FILES)) | tr " " "\n" > $@.list
 	grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
 	grep -e .*\\.config$$ $@-host.list > $@-host-test-configs.list || true
@@ -40,7 +43,7 @@
 	grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
 	grep -e .*\\.config$$ $@-target.list > $@-target-test-configs.list || true
 	$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list -P target -C $(PRODUCT_OUT) -l $@-target.list -sha256
-	$(hide) $(SOONG_ZIP) -d -o $(device-platinum-tests-configs-zip) \
+	$(hide) $(SOONG_ZIP) -d -o $(PRIVATE_device_platinum_tests_configs_zip) \
 	  -P host -C $(HOST_OUT) -l $@-host-test-configs.list \
 	  -P target -C $(PRODUCT_OUT) -l $@-target-test-configs.list
 	$(SOONG_ZIP) -d -o $(PRIVATE_device_host_shared_libs_zip) \
@@ -48,21 +51,21 @@
 	rm -f $(PRIVATE_device_platinum_tests_list)
 	$(hide) grep -e .*\\.config$$ $@-host.list | sed s%$(HOST_OUT)%host%g > $(PRIVATE_device_platinum_tests_list)
 	$(hide) grep -e .*\\.config$$ $@-target.list | sed s%$(PRODUCT_OUT)%target%g >> $(PRIVATE_device_platinum_tests_list)
-	$(hide) $(SOONG_ZIP) -d -o $(device-platinum-tests-list-zip) -C $(dir $@) -f $(PRIVATE_device_platinum_tests_list)
+	$(hide) $(SOONG_ZIP) -d -o $(PRIVATE_device_platinum_tests_list_zip) -C $(dir $@) -f $(PRIVATE_device_platinum_tests_list)
 	rm -f $@.list $@-host.list $@-target.list $@-host-test-configs.list $@-target-test-configs.list \
 	  $@-shared-libs.list $@-host-shared-libs.list $(PRIVATE_device_platinum_tests_list)
 
-device-platinum-tests: $(device-platinum-tests-zip)
-$(call dist-for-goals, device-platinum-tests, $(device-platinum-tests-zip) $(device-platinum-tests-list-zip) $(device-platinum-tests-configs-zip) $(device_platinum_tests_host_shared_libs_zip))
+device-platinum-tests: $(device_platinum_tests_zip)
+$(call dist-for-goals, device-platinum-tests, $(device_platinum_tests_zip) $(device_platinum_tests_list_zip) $(device_platinum_tests_configs_zip) $(device_platinum_tests_host_shared_libs_zip))
 
-$(call declare-1p-container,$(device-platinum-tests-zip),)
-$(call declare-container-license-deps,$(device-platinum-tests-zip),$(COMPATIBILITY.device-platinum-tests.FILES) $(my_host_shared_lib_for_device_platinum_tests),$(PRODUCT_OUT)/:/)
+$(call declare-1p-container,$(device_platinum_tests_zip),)
+$(call declare-container-license-deps,$(device_platinum_tests_zip),$(COMPATIBILITY.device-platinum-tests.FILES) $(my_host_shared_lib_for_device_platinum_tests),$(PRODUCT_OUT)/:/)
 
 tests: device-platinum-tests
 
 # Reset temp vars
-device-platinum-tests-zip :=
-device-platinum-tests-list-zip :=
-device-platinum-tests-configs-zip :=
+device_platinum_tests_zip :=
+device_platinum_tests_list_zip :=
+device_platinum_tests_configs_zip :=
 my_host_shared_lib_for_device_platinum_tests :=
-device_platinum_tests_host_shared_libs_zip :=
\ No newline at end of file
+device_platinum_tests_host_shared_libs_zip :=
diff --git a/core/tasks/device-tests.mk b/core/tasks/device-tests.mk
index 4167a7e..5850c4e 100644
--- a/core/tasks/device-tests.mk
+++ b/core/tasks/device-tests.mk
@@ -27,9 +27,9 @@
 $(device-tests-zip) : PRIVATE_device_tests_list := $(PRODUCT_OUT)/device-tests_list
 $(device-tests-zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_device_tests)
 $(device-tests-zip) : PRIVATE_device_host_shared_libs_zip := $(device_tests_host_shared_libs_zip)
-$(device-tests-zip) : $(COMPATIBILITY.device-tests.FILES) $(my_host_shared_lib_for_device_tests) $(SOONG_ZIP)
+$(device-tests-zip) : $(COMPATIBILITY.device-tests.FILES) $(COMPATIBILITY.device-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES) $(my_host_shared_lib_for_device_tests) $(SOONG_ZIP)
 	rm -f $@-shared-libs.list
-	echo $(sort $(COMPATIBILITY.device-tests.FILES)) | tr " " "\n" > $@.list
+	echo $(sort $(COMPATIBILITY.device-tests.FILES) $(COMPATIBILITY.device-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) | tr " " "\n" > $@.list
 	grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
 	grep -e .*\\.config$$ $@-host.list > $@-host-test-configs.list || true
 	$(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index cae71e4..d6fc072 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -47,11 +47,11 @@
 $(general_tests_zip) : PRIVATE_TOOLS := $(general_tests_tools)
 $(general_tests_zip) : PRIVATE_INTERMEDIATES_DIR := $(intermediates_dir)
 $(general_tests_zip) : PRIVATE_general_tests_configs_zip := $(general_tests_configs_zip)
-$(general_tests_zip) : $(COMPATIBILITY.general-tests.FILES) $(general_tests_tools) $(SOONG_ZIP)
+$(general_tests_zip) : $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES) $(general_tests_tools) $(SOONG_ZIP)
 	rm -rf $(PRIVATE_INTERMEDIATES_DIR)
 	rm -f $@ $(PRIVATE_general_tests_list_zip)
 	mkdir -p $(PRIVATE_INTERMEDIATES_DIR) $(PRIVATE_INTERMEDIATES_DIR)/tools
-	echo $(sort $(COMPATIBILITY.general-tests.FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
+	echo $(sort $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
 	find $(PRIVATE_KERNEL_LTP_HOST_OUT) >> $(PRIVATE_INTERMEDIATES_DIR)/list
 	grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/host.list || true
 	grep $(TARGET_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/target.list || true
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index daa7089..7593668 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -49,6 +49,7 @@
 			$(call write-optional-json-list, "supported_variants", $(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS))) \
 			$(call write-optional-json-list, "host_dependencies", $(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET))) \
 			$(call write-optional-json-list, "target_dependencies", $(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST))) \
+			$(call write-optional-json-bool, "test_module_config_base", $(ALL_MODULES.$(m).TEST_MODULE_CONFIG_BASE)) \
 		'}')'\n}\n' >> $@.tmp
 	$(PRIVATE_MERGE_JSON_OBJECTS) -o $@ $(PRIVATE_SOONG_MODULE_INFO) $@.tmp
 	rm $@.tmp
diff --git a/core/tasks/performance-tests.mk b/core/tasks/performance-tests.mk
index 32c156d..8702756 100644
--- a/core/tasks/performance-tests.mk
+++ b/core/tasks/performance-tests.mk
@@ -15,40 +15,42 @@
 
 .PHONY: performance-tests
 
-performance-tests-zip := $(PRODUCT_OUT)/performance-tests.zip
+performance_tests_zip := $(PRODUCT_OUT)/performance-tests.zip
 # Create an artifact to include a list of test config files in performance-tests.
-performance-tests-list-zip := $(PRODUCT_OUT)/performance-tests_list.zip
+performance_tests_list_zip := $(PRODUCT_OUT)/performance-tests_list.zip
 # Create an artifact to include all test config files in performance-tests.
-performance-tests-configs-zip := $(PRODUCT_OUT)/performance-tests_configs.zip
+performance_tests_configs_zip := $(PRODUCT_OUT)/performance-tests_configs.zip
 
-$(performance-tests-zip) : .KATI_IMPLICIT_OUTPUTS := $(performance-tests-list-zip) $(performance-tests-configs-zip)
-$(performance-tests-zip) : PRIVATE_performance_tests_list := $(PRODUCT_OUT)/performance-tests_list
-$(performance-tests-zip) : $(COMPATIBILITY.performance-tests.FILES) $(SOONG_ZIP)
+$(performance_tests_zip) : .KATI_IMPLICIT_OUTPUTS := $(performance_tests_list_zip) $(performance_tests_configs_zip)
+$(performance_tests_zip) : PRIVATE_performance_tests_list_zip := $(performance_tests_list_zip)
+$(performance_tests_zip) : PRIVATE_performance_tests_configs_zip := $(performance_tests_configs_zip)
+$(performance_tests_zip) : PRIVATE_performance_tests_list := $(PRODUCT_OUT)/performance-tests_list
+$(performance_tests_zip) : $(COMPATIBILITY.performance-tests.FILES) $(SOONG_ZIP)
 	echo $(sort $(COMPATIBILITY.performance-tests.FILES)) | tr " " "\n" > $@.list
 	grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
 	grep -e .*\\.config$$ $@-host.list > $@-host-test-configs.list || true
 	grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
 	grep -e .*\\.config$$ $@-target.list > $@-target-test-configs.list || true
 	$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list -P target -C $(PRODUCT_OUT) -l $@-target.list -sha256
-	$(hide) $(SOONG_ZIP) -d -o $(performance-tests-configs-zip) \
+	$(hide) $(SOONG_ZIP) -d -o $(PRIVATE_performance_tests_configs_zip) \
 	  -P host -C $(HOST_OUT) -l $@-host-test-configs.list \
 	  -P target -C $(PRODUCT_OUT) -l $@-target-test-configs.list
 	rm -f $(PRIVATE_performance_tests_list)
 	$(hide) grep -e .*\\.config$$ $@-host.list | sed s%$(HOST_OUT)%host%g > $(PRIVATE_performance_tests_list)
 	$(hide) grep -e .*\\.config$$ $@-target.list | sed s%$(PRODUCT_OUT)%target%g >> $(PRIVATE_performance_tests_list)
-	$(hide) $(SOONG_ZIP) -d -o $(performance-tests-list-zip) -C $(dir $@) -f $(PRIVATE_performance_tests_list)
+	$(hide) $(SOONG_ZIP) -d -o $(PRIVATE_performance_tests_list_zip) -C $(dir $@) -f $(PRIVATE_performance_tests_list)
 	rm -f $@.list $@-host.list $@-target.list $@-host-test-configs.list $@-target-test-configs.list \
 	  $(PRIVATE_performance_tests_list)
 
-performance-tests: $(performance-tests-zip)
-$(call dist-for-goals, performance-tests, $(performance-tests-zip) $(performance-tests-list-zip) $(performance-tests-configs-zip))
+performance-tests: $(performance_tests_zip)
+$(call dist-for-goals, performance-tests, $(performance_tests_zip) $(performance_tests_list_zip) $(performance_tests_configs_zip))
 
-$(call declare-1p-container,$(performance-tests-zip),)
-$(call declare-container-license-deps,$(performance-tests-zip),$(COMPATIBILITY.performance-tests.FILES),$(PRODUCT_OUT)/:/)
+$(call declare-1p-container,$(performance_tests_zip),)
+$(call declare-container-license-deps,$(performance_tests_zip),$(COMPATIBILITY.performance-tests.FILES),$(PRODUCT_OUT)/:/)
 
 tests: performance-tests
 
 # Reset temp vars
-performance-tests-zip :=
-performance-tests-list-zip :=
-performance-tests-configs-zip :=
+performance_tests_zip :=
+performance_tests_list_zip :=
+performance_tests_configs_zip :=
diff --git a/envsetup.sh b/envsetup.sh
index 640ed14..352d664 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -48,80 +48,13 @@
 fi
 IMPORTING_ENVSETUP=true source $T/build/make/shell_utils.sh
 
-
-# Help
-function hmm() {
-cat <<EOF
-
-Run "m help" for help with the build system itself.
-
-Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
-- lunch:      lunch <product_name>-<release_type>-<build_variant>
-              Selects <product_name> as the product to build, and <build_variant> as the variant to
-              build, and stores those selections in the environment to be read by subsequent
-              invocations of 'm' etc.
-- tapas:      tapas [<App1> <App2> ...] [arm|x86|arm64|x86_64] [eng|userdebug|user]
-              Sets up the build environment for building unbundled apps (APKs).
-- banchan:    banchan <module1> [<module2> ...] \\
-                      [arm|x86|arm64|riscv64|x86_64|arm64_only|x86_64only] [eng|userdebug|user]
-              Sets up the build environment for building unbundled modules (APEXes).
-- croot:      Changes directory to the top of the tree, or a subdirectory thereof.
-- m:          Makes from the top of the tree.
-- mm:         Builds and installs all of the modules in the current directory, and their
-              dependencies.
-- mmm:        Builds and installs all of the modules in the supplied directories, and their
-              dependencies.
-              To limit the modules being built use the syntax: mmm dir/:target1,target2.
-- mma:        Same as 'mm'
-- mmma:       Same as 'mmm'
-- provision:  Flash device with all required partitions. Options will be passed on to fastboot.
-- cgrep:      Greps on all local C/C++ files.
-- ggrep:      Greps on all local Gradle files.
-- gogrep:     Greps on all local Go files.
-- jgrep:      Greps on all local Java files.
-- jsongrep:   Greps on all local Json files.
-- ktgrep:     Greps on all local Kotlin files.
-- resgrep:    Greps on all local res/*.xml files.
-- mangrep:    Greps on all local AndroidManifest.xml files.
-- mgrep:      Greps on all local Makefiles and *.bp files.
-- owngrep:    Greps on all local OWNERS files.
-- rsgrep:     Greps on all local Rust files.
-- sepgrep:    Greps on all local sepolicy files.
-- sgrep:      Greps on all local source files.
-- tomlgrep:   Greps on all local Toml files.
-- pygrep:     Greps on all local Python files.
-- godir:      Go to the directory containing a file.
-- allmod:     List all modules.
-- gomod:      Go to the directory containing a module.
-- pathmod:    Get the directory containing a module.
-- outmod:     Gets the location of a module's installed outputs with a certain extension.
-- dirmods:    Gets the modules defined in a given directory.
-- installmod: Adb installs a module's built APK.
-- refreshmod: Refresh list of modules for allmod/gomod/pathmod/outmod/installmod.
-- syswrite:   Remount partitions (e.g. system.img) as writable, rebooting if necessary.
-
-Environment options:
-- SANITIZE_HOST: Set to 'address' to use ASAN for all host modules.
-- ANDROID_QUIET_BUILD: set to 'true' to display only the essential messages.
-
-Look at the source to view more functions. The complete list is:
-EOF
-    local T=$(gettop)
-    local A=""
-    local i
-    for i in `cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
-      A="$A $i"
-    done
-    echo $A
-}
-
 # Get all the build variables needed by this script in a single call to the build system.
 function build_build_var_cache()
 {
     local T=$(gettop)
     # Grep out the variable names from the script.
-    cached_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`)
-    cached_abs_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_abs_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`)
+    cached_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/_get_build_var_cached/) print $(i+1)}' | sort -u | tr '\n' ' '`)
+    cached_abs_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/_get_abs_build_var_cached/) print $(i+1)}' | sort -u | tr '\n' ' '`)
     # Call the build system to dump the "<val>=<value>" pairs as a shell script.
     build_dicts_script=`\builtin cd $T; build/soong/soong_ui.bash --dumpvars-mode \
                         --vars="${cached_vars[*]}" \
@@ -162,7 +95,7 @@
 }
 
 # Get the value of a build variable as an absolute path.
-function get_abs_build_var()
+function _get_abs_build_var_cached()
 {
     if [ "$BUILD_VAR_CACHE_READY" = "true" ]
     then
@@ -179,7 +112,7 @@
 }
 
 # Get the exact value of a build variable.
-function get_build_var()
+function _get_build_var_cached()
 {
     if [ "$BUILD_VAR_CACHE_READY" = "true" ]
     then
@@ -251,25 +184,25 @@
     fi
 
     # And in with the new...
-    ANDROID_LUNCH_BUILD_PATHS=$(get_abs_build_var SOONG_HOST_OUT_EXECUTABLES)
-    ANDROID_LUNCH_BUILD_PATHS+=:$(get_abs_build_var HOST_OUT_EXECUTABLES)
+    ANDROID_LUNCH_BUILD_PATHS=$(_get_abs_build_var_cached SOONG_HOST_OUT_EXECUTABLES)
+    ANDROID_LUNCH_BUILD_PATHS+=:$(_get_abs_build_var_cached HOST_OUT_EXECUTABLES)
 
     # Append llvm binutils prebuilts path to ANDROID_LUNCH_BUILD_PATHS.
-    local ANDROID_LLVM_BINUTILS=$(get_abs_build_var ANDROID_CLANG_PREBUILTS)/llvm-binutils-stable
+    local ANDROID_LLVM_BINUTILS=$(_get_abs_build_var_cached ANDROID_CLANG_PREBUILTS)/llvm-binutils-stable
     ANDROID_LUNCH_BUILD_PATHS+=:$ANDROID_LLVM_BINUTILS
 
     # Set up ASAN_SYMBOLIZER_PATH for SANITIZE_HOST=address builds.
     export ASAN_SYMBOLIZER_PATH=$ANDROID_LLVM_BINUTILS/llvm-symbolizer
 
     # Append asuite prebuilts path to ANDROID_LUNCH_BUILD_PATHS.
-    local os_arch=$(get_build_var HOST_PREBUILT_TAG)
+    local os_arch=$(_get_build_var_cached HOST_PREBUILT_TAG)
     ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/acloud/$os_arch
     ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/aidegen/$os_arch
     ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/atest/$os_arch
 
-    export ANDROID_JAVA_HOME=$(get_abs_build_var ANDROID_JAVA_HOME)
+    export ANDROID_JAVA_HOME=$(_get_abs_build_var_cached ANDROID_JAVA_HOME)
     export JAVA_HOME=$ANDROID_JAVA_HOME
-    export ANDROID_JAVA_TOOLCHAIN=$(get_abs_build_var ANDROID_JAVA_TOOLCHAIN)
+    export ANDROID_JAVA_TOOLCHAIN=$(_get_abs_build_var_cached ANDROID_JAVA_TOOLCHAIN)
     ANDROID_LUNCH_BUILD_PATHS+=:$ANDROID_JAVA_TOOLCHAIN
 
     # Fix up PYTHONPATH
@@ -298,20 +231,20 @@
     export PYTHONPATH=$ANDROID_PYTHONPATH$PYTHONPATH
 
     unset ANDROID_PRODUCT_OUT
-    export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
+    export ANDROID_PRODUCT_OUT=$(_get_abs_build_var_cached PRODUCT_OUT)
     export OUT=$ANDROID_PRODUCT_OUT
 
     unset ANDROID_HOST_OUT
-    export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
+    export ANDROID_HOST_OUT=$(_get_abs_build_var_cached HOST_OUT)
 
     unset ANDROID_SOONG_HOST_OUT
-    export ANDROID_SOONG_HOST_OUT=$(get_abs_build_var SOONG_HOST_OUT)
+    export ANDROID_SOONG_HOST_OUT=$(_get_abs_build_var_cached SOONG_HOST_OUT)
 
     unset ANDROID_HOST_OUT_TESTCASES
-    export ANDROID_HOST_OUT_TESTCASES=$(get_abs_build_var HOST_OUT_TESTCASES)
+    export ANDROID_HOST_OUT_TESTCASES=$(_get_abs_build_var_cached HOST_OUT_TESTCASES)
 
     unset ANDROID_TARGET_OUT_TESTCASES
-    export ANDROID_TARGET_OUT_TESTCASES=$(get_abs_build_var TARGET_OUT_TESTCASES)
+    export ANDROID_TARGET_OUT_TESTCASES=$(_get_abs_build_var_cached TARGET_OUT_TESTCASES)
 
     # Finally, set PATH
     export PATH=$ANDROID_LUNCH_BUILD_PATHS:$PATH
@@ -384,7 +317,7 @@
         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
         return
     fi
-    get_build_var report_config
+    _get_build_var_cached report_config
 }
 
 function set_stuff_for_environment()
@@ -452,6 +385,7 @@
         complete -F _bazel__complete -o nospace b
     fi
     complete -F _lunch lunch
+    complete -F _lunch_completion lunch2
 
     complete -F _complete_android_module_names pathmod
     complete -F _complete_android_module_names gomod
@@ -474,7 +408,7 @@
 {
     local uname=$(uname)
     local choices
-    choices=$(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
+    choices=$(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= _get_build_var_cached COMMON_LUNCH_CHOICES 2>/dev/null)
     local ret=$?
 
     echo
@@ -533,7 +467,7 @@
         selection=aosp_cf_x86_64_phone-trunk_staging-eng
     elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
     then
-        local choices=($(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null))
+        local choices=($(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= _get_build_var_cached COMMON_LUNCH_CHOICES 2>/dev/null))
         if [ $answer -le ${#choices[@]} ]
         then
             # array in zsh starts from 1 instead of 0.
@@ -563,9 +497,18 @@
         return 1
     fi
 
+    _lunch_meat $product $release $variant
+}
+
+function _lunch_meat()
+{
+    local product=$1
+    local release=$2
+    local variant=$3
+
     TARGET_PRODUCT=$product \
-    TARGET_BUILD_VARIANT=$variant \
     TARGET_RELEASE=$release \
+    TARGET_BUILD_VARIANT=$variant \
     build_build_var_cache
     if [ $? -ne 0 ]
     then
@@ -575,8 +518,8 @@
         fi
         return 1
     fi
-    export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
-    export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
+    export TARGET_PRODUCT=$(_get_build_var_cached TARGET_PRODUCT)
+    export TARGET_BUILD_VARIANT=$(_get_build_var_cached TARGET_BUILD_VARIANT)
     export TARGET_RELEASE=$release
     # Note this is the string "release", not the value of the variable.
     export TARGET_BUILD_TYPE=release
@@ -586,14 +529,11 @@
     set_stuff_for_environment
     [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig
 
-    if [ "${TARGET_BUILD_VARIANT}" = "userdebug" ] && [[  -z "${ANDROID_QUIET_BUILD}" ]]; then
-      echo
-      echo "Want FASTER LOCAL BUILDS? Use -eng instead of -userdebug (however for" \
-        "performance benchmarking continue to use userdebug)"
-    fi
-    if [ $used_lunch_menu -eq 1 ]; then
-      echo
-      echo "Hint: next time you can simply run 'lunch $selection'"
+    if [[ -z "${ANDROID_QUIET_BUILD}" ]]; then
+        local spam_for_lunch=$(gettop)/build/make/tools/envsetup/spam_for_lunch
+        if [[ -x $spam_for_lunch ]]; then
+            $spam_for_lunch
+        fi
     fi
 
     destroy_build_var_cache
@@ -613,13 +553,119 @@
     prev="${COMP_WORDS[COMP_CWORD-1]}"
 
     if [ -z "$COMMON_LUNCH_CHOICES_CACHE" ]; then
-        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
+        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= _get_build_var_cached COMMON_LUNCH_CHOICES)
     fi
 
     COMPREPLY=( $(compgen -W "${COMMON_LUNCH_CHOICES_CACHE}" -- ${cur}) )
     return 0
 }
 
+function _lunch_usage()
+{
+    (
+        echo "The lunch command selects the configuration to use for subsequent"
+        echo "Android builds."
+        echo
+        echo "Usage: lunch TARGET_PRODUCT [TARGET_RELEASE [TARGET_BUILD_VARIANT]]"
+        echo
+        echo "  Choose the product, release and variant to use. If not"
+        echo "  supplied, TARGET_RELEASE will be 'trunk_staging' and"
+        echo "  TARGET_BUILD_VARIANT will be 'eng'"
+        echo
+        echo
+        echo "Usage: lunch TARGET_PRODUCT-TARGET_RELEASE-TARGET_BUILD_VARIANT"
+        echo
+        echo "  Chose the product, release and variant to use. This"
+        echo "  legacy format is maintained for compatibility."
+        echo
+        echo
+        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_release_configs, list_variants"
+        echo "respectively."
+        echo
+    ) 1>&2
+}
+
+function lunch2()
+{
+    if [[ $# -eq 1 && $1 = "--help" ]]; then
+        _lunch_usage
+        return 0
+    fi
+    if [[ $# -eq 0 ]]; then
+        echo "No target specified. See lunch --help" 1>&2
+        return 1
+    fi
+    if [[ $# -gt 3 ]]; then
+        echo "Too many parameters given. See lunch --help" 1>&2
+        return 1
+    fi
+
+    local product release variant
+
+    # Handle the legacy format
+    local legacy=$(echo $1 | grep "-")
+    if [[ $# -eq 1 && -n $legacy ]]; then
+        IFS="-" read -r product release variant <<< "$1"
+        if [[ -z "$product" ]] || [[ -z "$release" ]] || [[ -z "$variant" ]]; then
+            echo "Invalid lunch combo: $1" 1>&2
+            echo "Valid combos must be of the form <product>-<release>-<variant> when using" 1>&2
+            echo "the legacy format.  Run 'lunch --help' for usage." 1>&2
+            return 1
+        fi
+    fi
+
+    # Handle the new format.
+    if [[ -z $legacy ]]; then
+        product=$1
+        release=$2
+        if [[ -z $release ]]; then
+            release=trunk_staging
+        fi
+        variant=$3
+        if [[ -z $variant ]]; then
+            variant=eng
+        fi
+    fi
+
+    # Validate the selection and set all the environment stuff
+    _lunch_meat $product $release $variant
+}
+
+unset ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE
+unset ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT
+unset ANDROID_LUNCH_COMPLETION_RELEASE_CACHE
+# Tab completion for lunch.
+function _lunch_completion()
+{
+    # Available products
+    if [[ $COMP_CWORD -eq 1 ]] ; then
+        if [[ -z $ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE ]]; then
+            ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE=$(list_products)
+        fi
+        COMPREPLY=( $(compgen -W "${ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE}" -- "${COMP_WORDS[COMP_CWORD]}") )
+    fi
+
+    # Available release configs
+    if [[ $COMP_CWORD -eq 2 ]] ; then
+        if [[ -z $ANDROID_LUNCH_COMPLETION_RELEASE_CACHE || $ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT != ${COMP_WORDS[1]} ]] ; then
+            ANDROID_LUNCH_COMPLETION_RELEASE_CACHE=$(list_releases ${COMP_WORDS[1]})
+            ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT=${COMP_WORDS[1]}
+        fi
+        COMPREPLY=( $(compgen -W "${ANDROID_LUNCH_COMPLETION_RELEASE_CACHE}" -- "${COMP_WORDS[COMP_CWORD]}") )
+    fi
+
+    # Available variants
+    if [[ $COMP_CWORD -eq 3 ]] ; then
+        COMPREPLY=(user userdebug eng)
+    fi
+
+    return 0
+}
+
+
 # Configures the build to build unbundled apps.
 # Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
 function tapas()
@@ -862,142 +908,6 @@
   )
 }
 
-# simplified version of ps; output in the form
-# <pid> <procname>
-function qpid() {
-    local prepend=''
-    local append=''
-    if [ "$1" = "--exact" ]; then
-        prepend=' '
-        append='$'
-        shift
-    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
-        echo "usage: qpid [[--exact] <process name|pid>"
-        return 255
-    fi
-
-    local EXE="$1"
-    if [ "$EXE" ] ; then
-        qpid | \grep "$prepend$EXE$append"
-    else
-        adb shell ps \
-            | tr -d '\r' \
-            | sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
-    fi
-}
-
-# coredump_setup - enable core dumps globally for any process
-#                  that has the core-file-size limit set correctly
-#
-# NOTE: You must call also coredump_enable for a specific process
-#       if its core-file-size limit is not set already.
-# NOTE: Core dumps are written to ramdisk; they will not survive a reboot!
-
-function coredump_setup()
-{
-    echo "Getting root...";
-    adb root;
-    adb wait-for-device;
-
-    echo "Remounting root partition read-write...";
-    adb shell mount -w -o remount -t rootfs rootfs;
-    sleep 1;
-    adb wait-for-device;
-    adb shell mkdir -p /cores;
-    adb shell mount -t tmpfs tmpfs /cores;
-    adb shell chmod 0777 /cores;
-
-    echo "Granting SELinux permission to dump in /cores...";
-    adb shell restorecon -R /cores;
-
-    echo "Set core pattern.";
-    adb shell 'echo /cores/core.%p > /proc/sys/kernel/core_pattern';
-
-    echo "Done."
-}
-
-# coredump_enable - enable core dumps for the specified process
-# $1 = PID of process (e.g., $(pid mediaserver))
-#
-# NOTE: coredump_setup must have been called as well for a core
-#       dump to actually be generated.
-
-function coredump_enable()
-{
-    local PID=$1;
-    if [ -z "$PID" ]; then
-        printf "Expecting a PID!\n";
-        return;
-    fi;
-    echo "Setting core limit for $PID to infinite...";
-    adb shell /system/bin/ulimit -P $PID -c unlimited
-}
-
-# core - send SIGV and pull the core for process
-# $1 = PID of process (e.g., $(pid mediaserver))
-#
-# NOTE: coredump_setup must be called once per boot for core dumps to be
-#       enabled globally.
-
-function core()
-{
-    local PID=$1;
-
-    if [ -z "$PID" ]; then
-        printf "Expecting a PID!\n";
-        return;
-    fi;
-
-    local CORENAME=core.$PID;
-    local COREPATH=/cores/$CORENAME;
-    local SIG=SEGV;
-
-    coredump_enable $1;
-
-    local done=0;
-    while [ $(adb shell "[ -d /proc/$PID ] && echo -n yes") ]; do
-        printf "\tSending SIG%s to %d...\n" $SIG $PID;
-        adb shell kill -$SIG $PID;
-        sleep 1;
-    done;
-
-    adb shell "while [ ! -f $COREPATH ] ; do echo waiting for $COREPATH to be generated; sleep 1; done"
-    echo "Done: core is under $COREPATH on device.";
-}
-
-# systemstack - dump the current stack trace of all threads in the system process
-# to the usual ANR traces file
-function systemstack()
-{
-    stacks system_server
-}
-
-# Read the ELF header from /proc/$PID/exe to determine if the process is
-# 64-bit.
-function is64bit()
-{
-    local PID="$1"
-    if [ "$PID" ] ; then
-        if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -p)" -eq "02" ]] ; then
-            echo "64"
-        else
-            echo ""
-        fi
-    else
-        echo ""
-    fi
-}
-
-function gettargetarch
-{
-    get_build_var TARGET_ARCH
-}
-
-function getprebuilt
-{
-    get_abs_build_var ANDROID_PREBUILTS
-}
-
 # communicate with a running device or emulator, set up necessary state,
 # and run the hat command.
 function runhat()
@@ -1050,100 +960,6 @@
     hat -JXmx512m $localFile
 }
 
-function getbugreports()
-{
-    local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)
-
-    if [ ! "$reports" ]; then
-        echo "Could not locate any bugreports."
-        return
-    fi
-
-    local report
-    for report in ${reports[@]}
-    do
-        echo "/sdcard/bugreports/${report}"
-        adb pull /sdcard/bugreports/${report} ${report}
-        gunzip ${report}
-    done
-}
-
-function getsdcardpath()
-{
-    adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
-}
-
-function getscreenshotpath()
-{
-    echo "$(getsdcardpath)/Pictures/Screenshots"
-}
-
-function getlastscreenshot()
-{
-    local screenshot_path=$(getscreenshotpath)
-    local screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
-    if [ "$screenshot" = "" ]; then
-        echo "No screenshots found."
-        return
-    fi
-    echo "${screenshot}"
-    adb ${adbOptions} pull ${screenshot_path}/${screenshot}
-}
-
-function startviewserver()
-{
-    local port=4939
-    if [ $# -gt 0 ]; then
-            port=$1
-    fi
-    adb shell service call window 1 i32 $port
-}
-
-function stopviewserver()
-{
-    adb shell service call window 2
-}
-
-function isviewserverstarted()
-{
-    adb shell service call window 3
-}
-
-function key_home()
-{
-    adb shell input keyevent 3
-}
-
-function key_back()
-{
-    adb shell input keyevent 4
-}
-
-function key_menu()
-{
-    adb shell input keyevent 82
-}
-
-function smoketest()
-{
-    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
-        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
-        return
-    fi
-    local T=$(gettop)
-    if [ ! "$T" ]; then
-        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
-        return
-    fi
-
-    (\cd "$T" && mmm tests/SmokeTest) &&
-      adb uninstall com.android.smoketest > /dev/null &&
-      adb uninstall com.android.smoketest.tests > /dev/null &&
-      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
-      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk &&
-      adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner
-}
-
 function godir () {
     if [[ -z "$1" ]]; then
         echo "Usage: godir <regex>"
@@ -1195,87 +1011,10 @@
     \cd $T/$pathname
 }
 
-# Verifies that module-info.txt exists, returning nonzero if it doesn't.
-function verifymodinfo() {
-    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
-        if [ "$QUIET_VERIFYMODINFO" != "true" ] ; then
-            echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
-        fi
-        return 1
-    fi
-
-    if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
-        if [ "$QUIET_VERIFYMODINFO" != "true" ] ; then
-            echo "Could not find module-info.json. Please run 'refreshmod' first." >&2
-        fi
-        return 1
-    fi
-}
-
-# List all modules for the current device, as cached in all_modules.txt. If any build change is
-# made and it should be reflected in the output, you should run `m nothing` first.
-function allmod() {
-    cat $ANDROID_PRODUCT_OUT/all_modules.txt 2>/dev/null
-}
-
-# Get the path of a specific module in the android tree, as cached in module-info.json.
-# If any build change is made, and it should be reflected in the output, you should run
-# 'refreshmod' first.  Note: This is the inverse of dirmods.
-function pathmod() {
-    if [[ $# -ne 1 ]]; then
-        echo "usage: pathmod <module>" >&2
-        return 1
-    fi
-
-    verifymodinfo || return 1
-
-    local relpath=$(python3 -c "import json, os
-module = '$1'
-module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
-if module not in module_info:
-    exit(1)
-print(module_info[module]['path'][0])" 2>/dev/null)
-
-    if [ -z "$relpath" ]; then
-        echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)." >&2
-        return 1
-    else
-        echo "$ANDROID_BUILD_TOP/$relpath"
-    fi
-}
-
-# Get the path of a specific module in the android tree, as cached in module-info.json.
-# If any build change is made, and it should be reflected in the output, you should run
-# 'refreshmod' first.  Note: This is the inverse of pathmod.
-function dirmods() {
-    if [[ $# -ne 1 ]]; then
-        echo "usage: dirmods <path>" >&2
-        return 1
-    fi
-
-    verifymodinfo || return 1
-
-    python3 -c "import json, os
-dir = '$1'
-while dir.endswith('/'):
-    dir = dir[:-1]
-prefix = dir + '/'
-module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
-results = set()
-for m in module_info.values():
-    for path in m.get(u'path', []):
-        if path == dir or path.startswith(prefix):
-            name = m.get(u'module_name')
-            if name:
-                results.add(name)
-for name in sorted(results):
-    print(name)
-"
-}
-
-
 # Go to a specific module in the android tree, as cached in module-info.json. If any build change
 # is made, and it should be reflected in the output, you should run 'refreshmod' first.
+# Note: This function is in envsetup because changing the directory needs to happen in the current
+# shell. All other functions that use module-info.json should be in build/soong/bin.
 function gomod() {
     if [[ $# -ne 1 ]]; then
         echo "usage: gomod <module>" >&2
@@ -1289,90 +1028,11 @@
     cd $path
 }
 
-# Gets the list of a module's installed outputs, as cached in module-info.json.
-# If any build change is made, and it should be reflected in the output, you should run 'refreshmod' first.
-function outmod() {
-    if [[ $# -ne 1 ]]; then
-        echo "usage: outmod <module>" >&2
-        return 1
-    fi
-
-    verifymodinfo || return 1
-
-    local relpath
-    relpath=$(python3 -c "import json, os
-module = '$1'
-module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
-if module not in module_info:
-    exit(1)
-for output in module_info[module]['installed']:
-    print(os.path.join('$ANDROID_BUILD_TOP', output))" 2>/dev/null)
-
-    if [ $? -ne 0 ]; then
-        echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)" >&2
-        return 1
-    elif [ ! -z "$relpath" ]; then
-        echo "$relpath"
-    fi
-}
-
-# adb install a module's apk, as cached in module-info.json. If any build change
-# is made, and it should be reflected in the output, you should run 'refreshmod' first.
-# Usage: installmod [adb install arguments] <module>
-# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
-function installmod() {
-    if [[ $# -eq 0 ]]; then
-        echo "usage: installmod [adb install arguments] <module>" >&2
-        echo "" >&2
-        echo "Only flags to be passed after the \"install\" in adb install are supported," >&2
-        echo "with the exception of -s. If -s is passed it will be placed before the \"install\"." >&2
-        echo "-s must be the first flag passed if it exists." >&2
-        return 1
-    fi
-
-    local _path
-    _path=$(outmod ${@:$#:1})
-    if [ $? -ne 0 ]; then
-        return 1
-    fi
-
-    _path=$(echo "$_path" | grep -E \\.apk$ | head -n 1)
-    if [ -z "$_path" ]; then
-        echo "Module '$1' does not produce a file ending with .apk (try 'refreshmod' if there have been build changes?)" >&2
-        return 1
-    fi
-    local serial_device=""
-    if [[ "$1" == "-s" ]]; then
-        if [[ $# -le 2 ]]; then
-            echo "-s requires an argument" >&2
-            return 1
-        fi
-        serial_device="-s $2"
-        shift 2
-    fi
-    local length=$(( $# - 1 ))
-    echo adb $serial_device install ${@:1:$length} $_path
-    adb $serial_device install ${@:1:$length} $_path
-}
-
 function _complete_android_module_names() {
     local word=${COMP_WORDS[COMP_CWORD]}
     COMPREPLY=( $(allmod | grep -E "^$word") )
 }
 
-# Print colored exit condition
-function pez {
-    "$@"
-    local retval=$?
-    if [ $retval -ne 0 ]
-    then
-        echo $'\E'"[0;31mFAILURE\e[00m"
-    else
-        echo $'\E'"[0;32mSUCCESS\e[00m"
-    fi
-    return $retval
-}
-
 function get_make_command()
 {
     # If we're in the top of an Android tree, use soong_ui.bash instead of make
@@ -1390,57 +1050,11 @@
     fi
 }
 
-function _trigger_build()
-(
-    local -r bc="$1"; shift
-    local T=$(gettop)
-    if [ -n "$T" ]; then
-      _wrap_build "$T/build/soong/soong_ui.bash" --build-mode --${bc} --dir="$(pwd)" "$@"
-    else
-      >&2 echo "Couldn't locate the top of the tree. Try setting TOP."
-      return 1
-    fi
-    local ret=$?
-    if [[ ret -eq 0 &&  -z "${ANDROID_QUIET_BUILD:-}" && -n "${ANDROID_BUILD_BANNER}" ]]; then
-      echo "${ANDROID_BUILD_BANNER}"
-    fi
-    return $ret
-)
-
 function make()
 {
     _wrap_build $(get_make_command "$@") "$@"
 }
 
-function provision()
-{
-    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
-        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
-        return 1
-    fi
-    if [ ! -e "$ANDROID_PRODUCT_OUT/provision-device" ]; then
-        echo "There is no provisioning script for the device." >&2
-        return 1
-    fi
-
-    # Check if user really wants to do this.
-    if [ "$1" = "--no-confirmation" ]; then
-        shift 1
-    else
-        echo "This action will reflash your device."
-        echo ""
-        echo "ALL DATA ON THE DEVICE WILL BE IRREVOCABLY ERASED."
-        echo ""
-        echo -n "Are you sure you want to do this (yes/no)? "
-        read
-        if [[ "${REPLY}" != "yes" ]] ; then
-            echo "Not taking any action. Exiting." >&2
-            return 1
-        fi
-    fi
-    "$ANDROID_PRODUCT_OUT/provision-device" "$@"
-}
-
 # Zsh needs bashcompinit called to support bash-style completion.
 function enable_zsh_completion() {
     # Don't override user's options if bash-style completion is already enabled.
@@ -1522,7 +1136,7 @@
             return
             ;;
     esac
-    OUT_DIR="$(get_abs_build_var OUT_DIR)"
+    OUT_DIR="$(_get_abs_build_var_cached OUT_DIR)"
     if [[ "$1" == "--regenerate" ]]; then
       shift 1
       NINJA_ARGS="-t commands $@" m
@@ -1537,32 +1151,58 @@
 # in build/soong/bin.  Unset these for the time being so the real
 # script is picked up.
 # TODO: Remove this some time after a suitable delay (maybe 2025?)
+unset allmod
 unset aninja
-unset overrideflags
-unset m
-unset mm
-unset mmm
-unset mma
-unset mmma
 unset cgrep
+unset core
+unset coredump_enable
+unset coredump_setup
+unset dirmods
+unset get_build_var
+unset get_abs_build_var
+unset getlastscreenshot
+unset getprebuilt
+unset getscreenshotpath
+unset getsdcardpath
+unset gettargetarch
 unset ggrep
 unset gogrep
+unset hmm
+unset installmod
+unset is64bit
+unset isviewserverstarted
 unset jgrep
 unset jsongrep
+unset key_back
+unset key_home
+unset key_menu
 unset ktgrep
+unset m
 unset mangrep
 unset mgrep
+unset mm
+unset mma
+unset mmm
+unset mmma
+unset outmod
+unset overrideflags
 unset owngrep
+unset pathmod
+unset pez
 unset pygrep
+unset qpid
 unset rcgrep
+unset refreshmod
 unset resgrep
 unset rsgrep
 unset sepgrep
 unset sgrep
+unset startviewserver
+unset stopviewserver
+unset systemstack
+unset syswrite
 unset tomlgrep
 unset treegrep
-unset syswrite
-unset refreshmod
 
 
 validate_current_shell
@@ -1571,4 +1211,3 @@
 addcompletions
 
 
-
diff --git a/target/board/ndk/BoardConfig.mk b/target/board/ndk/BoardConfig.mk
index d5399b2..e367918 100644
--- a/target/board/ndk/BoardConfig.mk
+++ b/target/board/ndk/BoardConfig.mk
@@ -14,7 +14,3 @@
 #
 
 TARGET_ARCH_SUITE := ndk
-
-MALLOC_LOW_MEMORY := true
-
-USE_SAFESTACK := false
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 364fed4..7a9325d 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -44,7 +44,7 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
 
 # pKVM
-$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
+$(call inherit-product-if-exists, packages/modules/Virtualization/apex/product_packages.mk)
 
 #
 # All components inherited here go to product image
diff --git a/target/product/generic_system.mk b/target/product/generic_system.mk
index 9748c7c..4793657 100644
--- a/target/product/generic_system.mk
+++ b/target/product/generic_system.mk
@@ -146,3 +146,6 @@
   $(TARGET_COPY_OUT_SYSTEM)/ \
 
 $(call require-artifacts-in-path, $(_my_paths), $(_my_allowed_list))
+
+# Product config map to toggle between sources and prebuilts of required mainline modules
+PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google_shared/build/release/gms_mainline/required/release_config_map.textproto)
diff --git a/target/product/go_defaults.mk b/target/product/go_defaults.mk
index a10cfa8..7fbc09d 100644
--- a/target/product/go_defaults.mk
+++ b/target/product/go_defaults.mk
@@ -17,6 +17,9 @@
 # Inherit common Android Go defaults.
 $(call inherit-product, build/make/target/product/go_defaults_common.mk)
 
+PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google_shared/build/release/go_devices/release_config_map.mk)
+
+# TODO (b/342265627): Remove v/g/r once all the flags have been moved to v/g_s/b/r
 PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google/release/go_devices/release_config_map.mk)
 
 # Add the system properties.
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 884b419..da1284e 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -50,13 +50,13 @@
     init.gsi.rc \
     init.vndk-nodef.rc \
 
-# Overlay the GSI specific SystemUI setting
-PRODUCT_PACKAGES += gsi_overlay_systemui
-PRODUCT_COPY_FILES += \
-    device/generic/common/overlays/overlay-config.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/overlay/config/config.xml
 
-# b/308878144 no more VNDK on 24Q1 and beyond
-KEEP_VNDK ?= false
+# Overlay the GSI specific SystemUI setting
+ifneq ($(PRODUCT_IS_AUTOMOTIVE),true)
+    PRODUCT_PACKAGES += gsi_overlay_systemui
+    PRODUCT_COPY_FILES += \
+        device/generic/common/overlays/overlay-config.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/overlay/config/config.xml
+endif
 
 # Support additional VNDK snapshots
 PRODUCT_EXTRA_VNDK_VERSIONS := \
diff --git a/target/product/security/README b/target/product/security/README
index 2b161bb..1e015f0 100644
--- a/target/product/security/README
+++ b/target/product/security/README
@@ -37,3 +37,31 @@
 
 This is called by build/make/core/Makefile to incorporate the OTA signing keys
 into the recovery image.
+
+converting to java keystore for Android Studio
+----------------------------------------------
+
+Suppose we want to convert shared.pk8 and shared.x509.pem to shared.keystore.
+
+ $ openssl pkcs8 -inform DER -nocrypt                      \
+   -in build/make/target/product/security/shared.pk8       \
+   -out shared.pem
+ $ openssl pkcs12 -export                                  \
+   -in build/make/target/product/security/shared.x509.pem  \
+   -inkey shared.pem -out shared.p12                       \
+   -password pass:android -name AndroidDebugKey
+ $ keytool -importkeystore -deststorepass android          \
+   -destkeystore shared.keystore -srckeystore shared.p12   \
+   -srcstoretype PKCS12 -srcstorepass android
+
+The keystore can be used in build.gradle as follows.
+
+signingConfigs {
+    shared {
+        storeFile file("shared.keystore")
+        storePassword "android"
+        keyPassword "android"
+        keyAlias "AndroidDebugKey"
+    }
+}
+
diff --git a/tools/aconfig/.editorconfig b/tools/aconfig/.editorconfig
new file mode 100644
index 0000000..cc5985f
--- /dev/null
+++ b/tools/aconfig/.editorconfig
@@ -0,0 +1,9 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*.java]
+indent_style = tab
+indent_size = 4
+
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index 421e94a..448d8cf 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -94,12 +94,16 @@
     {
       // aconfig_storage read api cpp integration tests
       "name": "aconfig_storage_read_api.test.cpp"
+    },
+    {
+      // aconfig_storage file cpp integration tests
+      "name": "aconfig_storage_file.test.cpp"
     }
   ],
   "postsubmit": [
     {
-      // aconfig_storage file cpp integration tests
-      "name": "aconfig_storage_file.test.cpp"
+      // aconfig_storage read api java integration tests
+      "name": "aconfig_storage_read_api.test.java"
     }
   ]
 }
diff --git a/tools/aconfig/aconfig/templates/cpp_source_file.template b/tools/aconfig/aconfig/templates/cpp_source_file.template
index 4c098c5..38dda7d 100644
--- a/tools/aconfig/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/aconfig/templates/cpp_source_file.template
@@ -124,14 +124,14 @@
         "{item.container}",
         aconfig_storage::StorageFileType::package_map);
     if (!package_map_file.ok()) \{
-        ALOGI("error: failed to get package map file: %s", package_map_file.error().message().c_str());
+        ALOGI("error: failed to get package map file: %s", package_map_file.error().c_str());
         return result;
     }
 
     auto package_read_context = aconfig_storage::get_package_read_context(
         **package_map_file, "{package}");
     if (!package_read_context.ok()) \{
-        ALOGI("error: failed to get package read context: %s", package_map_file.error().message().c_str());
+        ALOGI("error: failed to get package read context: %s", package_map_file.error().c_str());
         return result;
     }
 
@@ -141,7 +141,7 @@
         "{item.container}",
         aconfig_storage::StorageFileType::flag_val);
     if (!flag_val_map.ok()) \{
-        ALOGI("error: failed to get flag val map: %s", package_map_file.error().message().c_str());
+        ALOGI("error: failed to get flag val map: %s", package_map_file.error().c_str());
         return result;
     }
 
@@ -149,7 +149,7 @@
         **flag_val_map,
         package_read_context->boolean_start_index + {item.flag_offset});
     if (!value.ok()) \{
-        ALOGI("error: failed to get flag val: %s", package_map_file.error().message().c_str());
+        ALOGI("error: failed to get flag val: %s", package_map_file.error().c_str());
         return result;
     }
 
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index db36294..3b124b1 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -9,8 +9,6 @@
     srcs: ["src/lib.rs"],
     rustlibs: [
         "libanyhow",
-        "libonce_cell",
-        "libtempfile",
         "libmemmap2",
         "libcxx",
         "libthiserror",
@@ -34,6 +32,9 @@
     name: "aconfig_storage_read_api.test",
     test_suites: ["general-tests"],
     defaults: ["aconfig_storage_read_api.defaults"],
+    rustlibs: [
+        "librand",
+    ],
     data: [
         "tests/package.map",
         "tests/flag.map",
@@ -89,14 +90,6 @@
     host_supported: true,
     vendor_available: true,
     product_available: true,
-    static_libs: [
-        "libaconfig_storage_protos_cc",
-        "libprotobuf-cpp-lite",
-    ],
-    shared_libs: [
-        "liblog",
-        "libbase",
-    ],
     apex_available: [
         "//apex_available:platform",
         "//apex_available:anyapex",
@@ -108,6 +101,7 @@
         },
     },
     double_loadable: true,
+    afdo: true,
 }
 
 cc_defaults {
@@ -117,3 +111,28 @@
         "liblog",
     ],
 }
+
+rust_ffi_shared {
+    name: "libaconfig_storage_read_api_rust_jni",
+    crate_name: "aconfig_storage_read_api_rust_jni",
+    srcs: ["srcs/lib.rs"],
+    rustlibs: [
+        "libaconfig_storage_read_api",
+        "libanyhow",
+        "libjni",
+    ],
+    prefer_rlib: true,
+}
+
+java_library {
+    name: "libaconfig_storage_read_api_java",
+    srcs: [
+        "srcs/**/*.java",
+    ],
+    required: ["libaconfig_storage_read_api_rust_jni"],
+    min_sdk_version: "UpsideDownCake",
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/Cargo.toml b/tools/aconfig/aconfig_storage_read_api/Cargo.toml
index 30a4298..2b27e4b 100644
--- a/tools/aconfig/aconfig_storage_read_api/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_read_api/Cargo.toml
@@ -8,10 +8,9 @@
 cargo = []
 
 [dependencies]
+rand = "0.8.5"
 anyhow = "1.0.69"
 memmap2 = "0.8.0"
-once_cell = "1.19.0"
-tempfile = "3.9.0"
 cxx = "1.0"
 thiserror = "1.0.56"
 aconfig_storage_file = { path = "../aconfig_storage_file" }
diff --git a/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp b/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp
index 0aa936a..97ada3a 100644
--- a/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp
+++ b/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp
@@ -1,85 +1,56 @@
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <protos/aconfig_storage_metadata.pb.h>
-
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <errno.h>
+#include <string.h>
 
 #include "rust/cxx.h"
 #include "aconfig_storage/lib.rs.h"
 #include "aconfig_storage/aconfig_storage_read_api.hpp"
 
-using storage_records_pb = android::aconfig_storage_metadata::storage_files;
-using storage_record_pb = android::aconfig_storage_metadata::storage_file_info;
-using namespace android::base;
-
 namespace aconfig_storage {
 
 /// Storage location pb file
-static constexpr char kAvailableStorageRecordsPb[] =
-    "/metadata/aconfig/boot/available_storage_file_records.pb";
+static constexpr char kStorageDir[] = "/metadata/aconfig";
 
 /// destructor
 MappedStorageFile::~MappedStorageFile() {
   munmap(file_ptr, file_size);
 }
 
-/// Read aconfig storage records pb file
-static Result<storage_records_pb> read_storage_records_pb(std::string const& pb_file) {
-  auto records = storage_records_pb();
-  auto content = std::string();
-  if (!ReadFileToString(pb_file, &content)) {
-    return ErrnoError() << "ReadFileToString failed";
-  }
-
-  if (!records.ParseFromString(content)) {
-    return ErrnoError() << "Unable to parse persistent storage records protobuf";
-  }
-  return records;
-}
-
 /// Get storage file path
 static Result<std::string> find_storage_file(
-    std::string const& pb_file,
+    std::string const& storage_dir,
     std::string const& container,
     StorageFileType file_type) {
-  auto records_pb = read_storage_records_pb(pb_file);
-  if (!records_pb.ok()) {
-    return Error() << "Unable to read storage records from " << pb_file
-                   << " : " << records_pb.error();
+  switch(file_type) {
+    case StorageFileType::package_map:
+      return storage_dir + "/maps/" + container + ".package.map";
+    case StorageFileType::flag_map:
+      return storage_dir + "/maps/" + container + ".flag.map";
+    case StorageFileType::flag_val:
+      return storage_dir + "/boot/" + container + ".val";
+    case StorageFileType::flag_info:
+      return storage_dir + "/boot/" + container + ".info";
+    default:
+      auto result = Result<std::string>();
+      result.errmsg = "Invalid storage file type";
+      return result;
   }
-
-  for (auto& entry : records_pb->files()) {
-    if (entry.container() == container) {
-      switch(file_type) {
-        case StorageFileType::package_map:
-          return entry.package_map();
-        case StorageFileType::flag_map:
-          return entry.flag_map();
-        case StorageFileType::flag_val:
-          return entry.flag_val();
-        case StorageFileType::flag_info:
-          return entry.flag_info();
-        default:
-          return Error() << "Invalid file type " << file_type;
-      }
-    }
-  }
-
-  return Error() << "Unable to find storage files for container " << container;;
 }
 
 namespace private_internal_api {
 
 /// Get mapped file implementation.
 Result<MappedStorageFile*> get_mapped_file_impl(
-    std::string const& pb_file,
+    std::string const& storage_dir,
     std::string const& container,
     StorageFileType file_type) {
-  auto file_result = find_storage_file(pb_file, container, file_type);
+  auto file_result = find_storage_file(storage_dir, container, file_type);
   if (!file_result.ok()) {
-    return Error() << file_result.error();
+    auto result = Result<MappedStorageFile*>();
+    result.errmsg = file_result.error();
+    return result;
   }
   return map_storage_file(*file_result);
 }
@@ -90,18 +61,24 @@
 Result<MappedStorageFile*> map_storage_file(std::string const& file) {
   int fd = open(file.c_str(), O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
   if (fd == -1) {
-    return ErrnoError() << "failed to open " << file;
+    auto result = Result<MappedStorageFile*>();
+    result.errmsg = std::string("failed to open ") + file + ": " + strerror(errno);
+    return result;
   };
 
   struct stat fd_stat;
   if (fstat(fd, &fd_stat) < 0) {
-    return ErrnoError() << "fstat failed";
+    auto result = Result<MappedStorageFile*>();
+    result.errmsg = std::string("fstat failed: ") + strerror(errno);
+    return result;
   }
   size_t file_size = fd_stat.st_size;
 
   void* const map_result = mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
   if (map_result == MAP_FAILED) {
-    return ErrnoError() << "mmap failed";
+    auto result = Result<MappedStorageFile*>();
+    result.errmsg = std::string("mmap failed: ") + strerror(errno);
+    return result;
   }
 
   auto mapped_file = new MappedStorageFile();
@@ -112,7 +89,7 @@
 }
 
 /// Map from StoredFlagType to FlagValueType
-android::base::Result<FlagValueType> map_to_flag_value_type(
+Result<FlagValueType> map_to_flag_value_type(
     StoredFlagType stored_type) {
   switch (stored_type) {
     case StoredFlagType::ReadWriteBoolean:
@@ -120,7 +97,9 @@
     case StoredFlagType::FixedReadOnlyBoolean:
       return FlagValueType::Boolean;
     default:
-      return Error() << "Unsupported stored flag type";
+      auto result = Result<FlagValueType>();
+      result.errmsg = "Unsupported stored flag type";
+      return result;
   }
 }
 
@@ -129,7 +108,7 @@
     std::string const& container,
     StorageFileType file_type) {
   return private_internal_api::get_mapped_file_impl(
-      kAvailableStorageRecordsPb, container, file_type);
+      kStorageDir, container, file_type);
 }
 
 /// Get storage file version number
@@ -140,7 +119,9 @@
   if (version_cxx.query_success) {
     return version_cxx.version_number;
   } else {
-    return Error() << version_cxx.error_message;
+    auto result = Result<uint32_t>();
+    result.errmsg = version_cxx.error_message.c_str();
+    return result;
   }
 }
 
@@ -158,7 +139,9 @@
     context.boolean_start_index = context_cxx.boolean_start_index;
     return context;
   } else {
-    return Error() << context_cxx.error_message;
+    auto result = Result<PackageReadContext>();
+    result.errmsg = context_cxx.error_message.c_str();
+    return result;
   }
 }
 
@@ -177,7 +160,9 @@
     context.flag_index = context_cxx.flag_index;
     return context;
   } else {
-   return Error() << context_cxx.error_message;
+    auto result = Result<FlagReadContext>();
+    result.errmsg = context_cxx.error_message.c_str();
+    return result;
   }
 }
 
@@ -191,7 +176,9 @@
   if (value_cxx.query_success) {
     return value_cxx.flag_value;
   } else {
-    return Error() << value_cxx.error_message;
+    auto result = Result<bool>();
+    result.errmsg = value_cxx.error_message.c_str();
+    return result;
   }
 }
 
@@ -207,7 +194,9 @@
   if (info_cxx.query_success) {
     return info_cxx.flag_attribute;
   } else {
-    return Error() << info_cxx.error_message;
+    auto result = Result<uint8_t>();
+    result.errmsg = info_cxx.error_message.c_str();
+    return result;
   }
 }
 } // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp b/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp
index e6d7537..b50935b 100644
--- a/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp
+++ b/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp
@@ -2,7 +2,7 @@
 
 #include <stdint.h>
 #include <string>
-#include <android-base/result.h>
+#include <cassert>
 
 namespace aconfig_storage {
 
@@ -58,46 +58,86 @@
   uint16_t flag_index;
 };
 
+
+template <class T>
+class Result {
+  public:
+
+  Result()
+      : data()
+      , errmsg()
+      , has_data(false)
+  {}
+
+  Result(T const& value)
+      : data(value)
+      , errmsg()
+      , has_data(true)
+  {}
+
+  bool ok() {
+    return has_data;
+  }
+
+  T& operator*() {
+    assert(has_data);
+    return data;
+  }
+
+  T* operator->() {
+    assert(has_data);
+    return &data;
+  }
+
+  std::string const& error() {
+    assert(!has_data);
+    return errmsg;
+  }
+
+  T data;
+  std::string errmsg;
+  bool has_data;
+};
+
 /// DO NOT USE APIS IN THE FOLLOWING NAMESPACE DIRECTLY
 namespace private_internal_api {
 
-android::base::Result<MappedStorageFile*> get_mapped_file_impl(
+Result<MappedStorageFile*> get_mapped_file_impl(
     std::string const& pb_file,
     std::string const& container,
     StorageFileType file_type);
-
 } // namespace private_internal_api
 
 /// Map a storage file
-android::base::Result<MappedStorageFile*> map_storage_file(
+Result<MappedStorageFile*> map_storage_file(
     std::string const& file);
 
 
 /// Map from StoredFlagType to FlagValueType
 /// \input stored_type: stored flag type in the storage file
 /// \returns the flag value type enum
-android::base::Result<FlagValueType> map_to_flag_value_type(
+Result<FlagValueType> map_to_flag_value_type(
     StoredFlagType stored_type);
 
 /// Get mapped storage file
 /// \input container: stoarge container name
 /// \input file_type: storage file type enum
 /// \returns a MappedStorageFileQuery
-android::base::Result<MappedStorageFile*> get_mapped_file(
+Result<MappedStorageFile*> get_mapped_file(
     std::string const& container,
     StorageFileType file_type);
 
 /// Get storage file version number
 /// \input file_path: the path to the storage file
 /// \returns the storage file version
-android::base::Result<uint32_t> get_storage_file_version(
+Result<uint32_t> get_storage_file_version(
     std::string const& file_path);
 
 /// Get package read context
 /// \input file: mapped storage file
 /// \input package: the flag package name
 /// \returns a package read context
-android::base::Result<PackageReadContext> get_package_read_context(
+Result<PackageReadContext> get_package_read_context(
     MappedStorageFile const& file,
     std::string const& package);
 
@@ -106,7 +146,7 @@
 /// \input package_id: the flag package id obtained from package offset query
 /// \input flag_name: flag name
 /// \returns the flag read context
-android::base::Result<FlagReadContext> get_flag_read_context(
+Result<FlagReadContext> get_flag_read_context(
     MappedStorageFile const& file,
     uint32_t package_id,
     std::string const& flag_name);
@@ -115,7 +155,7 @@
 /// \input file: mapped storage file
 /// \input index: the boolean flag index in the file
 /// \returns the boolean flag value
-android::base::Result<bool> get_boolean_flag_value(
+Result<bool> get_boolean_flag_value(
     MappedStorageFile const& file,
     uint32_t index);
 
@@ -124,7 +164,7 @@
 /// \input value_type: flag value type
 /// \input index: the boolean flag index in the file
 /// \returns the boolean flag attribute
-android::base::Result<uint8_t> get_flag_attribute(
+Result<uint8_t> get_flag_attribute(
     MappedStorageFile const& file,
     FlagValueType value_type,
     uint32_t index);
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index e419206..61f9e96 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -42,9 +42,6 @@
 pub mod mapped_file;
 pub mod package_table_query;
 
-#[cfg(test)]
-mod test_utils;
-
 pub use aconfig_storage_file::{AconfigStorageError, FlagValueType, StorageFileType};
 pub use flag_table_query::FlagReadContext;
 pub use package_table_query::PackageReadContext;
@@ -60,8 +57,8 @@
 use std::fs::File;
 use std::io::Read;
 
-/// Storage file location pb file
-pub const STORAGE_LOCATION_FILE: &str = "/metadata/aconfig/boot/available_storage_file_records.pb";
+/// Storage file location
+pub const STORAGE_LOCATION: &str = "/metadata/aconfig";
 
 /// Get read only mapped storage files.
 ///
@@ -78,7 +75,7 @@
     container: &str,
     file_type: StorageFileType,
 ) -> Result<Mmap, AconfigStorageError> {
-    unsafe { crate::mapped_file::get_mapped_file(STORAGE_LOCATION_FILE, container, file_type) }
+    unsafe { crate::mapped_file::get_mapped_file(STORAGE_LOCATION, container, file_type) }
 }
 
 /// Get package read context for a specific package.
@@ -394,45 +391,41 @@
 mod tests {
     use super::*;
     use crate::mapped_file::get_mapped_file;
-    use crate::test_utils::copy_to_temp_file;
-    use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
     use aconfig_storage_file::{FlagInfoBit, StoredFlagType};
-    use tempfile::NamedTempFile;
+    use rand::Rng;
+    use std::fs;
 
-    fn create_test_storage_files() -> [NamedTempFile; 5] {
-        let package_map = copy_to_temp_file("./tests/package.map").unwrap();
-        let flag_map = copy_to_temp_file("./tests/flag.map").unwrap();
-        let flag_val = copy_to_temp_file("./tests/flag.val").unwrap();
-        let flag_info = copy_to_temp_file("./tests/flag.info").unwrap();
+    fn create_test_storage_files() -> String {
+        let mut rng = rand::thread_rng();
+        let number: u32 = rng.gen();
+        let storage_dir = String::from("/tmp/") + &number.to_string();
+        if std::fs::metadata(&storage_dir).is_ok() {
+            fs::remove_dir_all(&storage_dir).unwrap();
+        }
+        let maps_dir = storage_dir.clone() + "/maps";
+        let boot_dir = storage_dir.clone() + "/boot";
+        fs::create_dir(&storage_dir).unwrap();
+        fs::create_dir(&maps_dir).unwrap();
+        fs::create_dir(&boot_dir).unwrap();
 
-        let text_proto = format!(
-            r#"
-files {{
-    version: 0
-    container: "mockup"
-    package_map: "{}"
-    flag_map: "{}"
-    flag_val: "{}"
-    flag_info: "{}"
-    timestamp: 12345
-}}
-"#,
-            package_map.path().display(),
-            flag_map.path().display(),
-            flag_val.path().display(),
-            flag_info.path().display()
-        );
-        let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
-        [package_map, flag_map, flag_val, flag_info, pb_file]
+        let package_map = storage_dir.clone() + "/maps/mockup.package.map";
+        let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
+        let flag_val = storage_dir.clone() + "/boot/mockup.val";
+        let flag_info = storage_dir.clone() + "/boot/mockup.info";
+        fs::copy("./tests/package.map", &package_map).unwrap();
+        fs::copy("./tests/flag.map", &flag_map).unwrap();
+        fs::copy("./tests/flag.val", &flag_val).unwrap();
+        fs::copy("./tests/flag.info", &flag_info).unwrap();
+
+        return storage_dir;
     }
 
     #[test]
     // this test point locks down flag package read context query
     fn test_package_context_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         let package_mapped_file = unsafe {
-            get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
+            get_mapped_file(&storage_dir, "mockup", StorageFileType::PackageMap).unwrap()
         };
 
         let package_context =
@@ -460,10 +453,9 @@
     #[test]
     // this test point locks down flag read context query
     fn test_flag_context_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         let flag_mapped_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagMap).unwrap() };
 
         let baseline = vec![
             (0, "enabled_ro", StoredFlagType::ReadOnlyBoolean, 1u16),
@@ -486,10 +478,9 @@
     #[test]
     // this test point locks down flag value query
     fn test_flag_value_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         let flag_value_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagVal).unwrap() };
         let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
         for (offset, expected_value) in baseline.into_iter().enumerate() {
             let flag_value = get_boolean_flag_value(&flag_value_file, offset as u32).unwrap();
@@ -500,10 +491,9 @@
     #[test]
     // this test point locks donw flag info query
     fn test_flag_info_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         let flag_info_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagInfo).unwrap() };
         let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true];
         for (offset, expected_value) in is_rw.into_iter().enumerate() {
             let attribute =
diff --git a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
index 3786443..5a16645 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
@@ -14,47 +14,12 @@
  * limitations under the License.
  */
 
-use std::fs::File;
-use std::io::{BufReader, Read};
-
 use anyhow::anyhow;
 use memmap2::Mmap;
+use std::fs::File;
 
-use crate::AconfigStorageError::{
-    self, FileReadFail, MapFileFail, ProtobufParseFail, StorageFileNotFound,
-};
+use crate::AconfigStorageError::{self, FileReadFail, MapFileFail, StorageFileNotFound};
 use crate::StorageFileType;
-use aconfig_storage_file::protos::{
-    storage_record_pb::try_from_binary_proto, ProtoStorageFileInfo, ProtoStorageFiles,
-};
-
-/// Find where storage files are stored for a particular container
-pub fn find_container_storage_location(
-    location_pb_file: &str,
-    container: &str,
-) -> Result<ProtoStorageFileInfo, AconfigStorageError> {
-    let file = File::open(location_pb_file).map_err(|errmsg| {
-        FileReadFail(anyhow!("Failed to open file {}: {}", location_pb_file, errmsg))
-    })?;
-    let mut reader = BufReader::new(file);
-    let mut bytes = Vec::new();
-    reader.read_to_end(&mut bytes).map_err(|errmsg| {
-        FileReadFail(anyhow!("Failed to read file {}: {}", location_pb_file, errmsg))
-    })?;
-    let storage_locations: ProtoStorageFiles = try_from_binary_proto(&bytes).map_err(|errmsg| {
-        ProtobufParseFail(anyhow!(
-            "Failed to parse storage location pb file {}: {}",
-            location_pb_file,
-            errmsg
-        ))
-    })?;
-    for location_info in storage_locations.files.iter() {
-        if location_info.container() == container {
-            return Ok(location_info.clone());
-        }
-    }
-    Err(StorageFileNotFound(anyhow!("Storage file does not exist for {}", container)))
-}
 
 /// Get the read only memory mapping of a storage file
 ///
@@ -82,123 +47,70 @@
 /// file after being mapped. Ensure no writes can happen to this file while this
 /// mapping stays alive.
 pub unsafe fn get_mapped_file(
-    location_pb_file: &str,
+    storage_dir: &str,
     container: &str,
     file_type: StorageFileType,
 ) -> Result<Mmap, AconfigStorageError> {
-    let files_location = find_container_storage_location(location_pb_file, container)?;
-    match file_type {
-        StorageFileType::PackageMap => unsafe { map_file(files_location.package_map()) },
-        StorageFileType::FlagMap => unsafe { map_file(files_location.flag_map()) },
-        StorageFileType::FlagVal => unsafe { map_file(files_location.flag_val()) },
-        StorageFileType::FlagInfo => unsafe { map_file(files_location.flag_info()) },
+    let storage_file = match file_type {
+        StorageFileType::PackageMap => {
+            String::from(storage_dir) + "/maps/" + container + ".package.map"
+        }
+        StorageFileType::FlagMap => String::from(storage_dir) + "/maps/" + container + ".flag.map",
+        StorageFileType::FlagVal => String::from(storage_dir) + "/boot/" + container + ".val",
+        StorageFileType::FlagInfo => String::from(storage_dir) + "/boot/" + container + ".info",
+    };
+    if std::fs::metadata(&storage_file).is_err() {
+        return Err(StorageFileNotFound(anyhow!("storage file {} does not exist", storage_file)));
     }
+    unsafe { map_file(&storage_file) }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::copy_to_temp_file;
-    use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
-    use tempfile::NamedTempFile;
+    use rand::Rng;
+    use std::fs;
+    use std::io::Read;
 
-    #[test]
-    fn test_find_storage_file_location() {
-        let text_proto = r#"
-files {
-    version: 0
-    container: "system"
-    package_map: "/system/etc/package.map"
-    flag_map: "/system/etc/flag.map"
-    flag_val: "/metadata/aconfig/system.val"
-    timestamp: 12345
-}
-files {
-    version: 1
-    container: "product"
-    package_map: "/product/etc/package.map"
-    flag_map: "/product/etc/flag.map"
-    flag_val: "/metadata/aconfig/product.val"
-    timestamp: 54321
-}
-"#;
-        let file = write_proto_to_temp_file(&text_proto).unwrap();
-        let file_full_path = file.path().display().to_string();
-        let file_info = find_container_storage_location(&file_full_path, "system").unwrap();
-        assert_eq!(file_info.version(), 0);
-        assert_eq!(file_info.container(), "system");
-        assert_eq!(file_info.package_map(), "/system/etc/package.map");
-        assert_eq!(file_info.flag_map(), "/system/etc/flag.map");
-        assert_eq!(file_info.flag_val(), "/metadata/aconfig/system.val");
-        assert_eq!(file_info.timestamp(), 12345);
-
-        let file_info = find_container_storage_location(&file_full_path, "product").unwrap();
-        assert_eq!(file_info.version(), 1);
-        assert_eq!(file_info.container(), "product");
-        assert_eq!(file_info.package_map(), "/product/etc/package.map");
-        assert_eq!(file_info.flag_map(), "/product/etc/flag.map");
-        assert_eq!(file_info.flag_val(), "/metadata/aconfig/product.val");
-        assert_eq!(file_info.timestamp(), 54321);
-
-        let err = find_container_storage_location(&file_full_path, "vendor").unwrap_err();
-        assert_eq!(
-            format!("{:?}", err),
-            "StorageFileNotFound(Storage file does not exist for vendor)"
-        );
-    }
-
-    fn map_and_verify(location_pb_file: &str, file_type: StorageFileType, actual_file: &str) {
+    fn map_and_verify(storage_dir: &str, file_type: StorageFileType, actual_file: &str) {
         let mut opened_file = File::open(actual_file).unwrap();
         let mut content = Vec::new();
         opened_file.read_to_end(&mut content).unwrap();
-
-        let mmaped_file =
-            unsafe { get_mapped_file(location_pb_file, "system", file_type).unwrap() };
+        let mmaped_file = unsafe { get_mapped_file(storage_dir, "mockup", file_type).unwrap() };
         assert_eq!(mmaped_file[..], content[..]);
     }
 
-    fn create_test_storage_files() -> [NamedTempFile; 4] {
-        let package_map = copy_to_temp_file("./tests/package.map").unwrap();
-        let flag_map = copy_to_temp_file("./tests/flag.map").unwrap();
-        let flag_val = copy_to_temp_file("./tests/package.map").unwrap();
+    fn create_test_storage_files() -> String {
+        let mut rng = rand::thread_rng();
+        let number: u32 = rng.gen();
+        let storage_dir = String::from("/tmp/") + &number.to_string();
+        if std::fs::metadata(&storage_dir).is_ok() {
+            fs::remove_dir_all(&storage_dir).unwrap();
+        }
+        let maps_dir = storage_dir.clone() + "/maps";
+        let boot_dir = storage_dir.clone() + "/boot";
+        fs::create_dir(&storage_dir).unwrap();
+        fs::create_dir(&maps_dir).unwrap();
+        fs::create_dir(&boot_dir).unwrap();
 
-        let text_proto = format!(
-            r#"
-files {{
-    version: 0
-    container: "system"
-    package_map: "{}"
-    flag_map: "{}"
-    flag_val: "{}"
-    timestamp: 12345
-}}
-"#,
-            package_map.path().display(),
-            flag_map.path().display(),
-            flag_val.path().display()
-        );
-        let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
-        [package_map, flag_map, flag_val, pb_file]
+        let package_map = storage_dir.clone() + "/maps/mockup.package.map";
+        let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
+        let flag_val = storage_dir.clone() + "/boot/mockup.val";
+        let flag_info = storage_dir.clone() + "/boot/mockup.info";
+        fs::copy("./tests/package.map", &package_map).unwrap();
+        fs::copy("./tests/flag.map", &flag_map).unwrap();
+        fs::copy("./tests/flag.val", &flag_val).unwrap();
+        fs::copy("./tests/flag.info", &flag_info).unwrap();
+
+        return storage_dir;
     }
 
     #[test]
     fn test_mapped_file_contents() {
-        let [package_map, flag_map, flag_val, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
-        map_and_verify(
-            &pb_file_path,
-            StorageFileType::PackageMap,
-            &package_map.path().display().to_string(),
-        );
-        map_and_verify(
-            &pb_file_path,
-            StorageFileType::FlagMap,
-            &flag_map.path().display().to_string(),
-        );
-        map_and_verify(
-            &pb_file_path,
-            StorageFileType::FlagVal,
-            &flag_val.path().display().to_string(),
-        );
+        let storage_dir = create_test_storage_files();
+        map_and_verify(&storage_dir, StorageFileType::PackageMap, "./tests/package.map");
+        map_and_verify(&storage_dir, StorageFileType::FlagMap, "./tests/flag.map");
+        map_and_verify(&storage_dir, StorageFileType::FlagVal, "./tests/flag.val");
+        map_and_verify(&storage_dir, StorageFileType::FlagInfo, "./tests/flag.info");
     }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigStorageReadAPI.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigStorageReadAPI.java
new file mode 100644
index 0000000..406ff24
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigStorageReadAPI.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package android.aconfig.storage;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+
+import android.aconfig.storage.PackageReadContext;
+import android.aconfig.storage.FlagReadContext;
+
+import dalvik.annotation.optimization.FastNative;
+
+public class AconfigStorageReadAPI {
+
+    // Storage file dir on device
+    private static final String STORAGEDIR = "/metadata/aconfig";
+
+    // Stoarge file type
+    public enum StorageFileType {
+        PACKAGE_MAP,
+        FLAG_MAP,
+        FLAG_VAL,
+        FLAG_INFO
+    }
+
+    // Map a storage file given file path
+    public static MappedByteBuffer mapStorageFile(String file) throws IOException {
+        FileInputStream stream = new FileInputStream(file);
+        FileChannel channel = stream.getChannel();
+        return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+    }
+
+    // Map a storage file given container and file type
+    public static MappedByteBuffer getMappedFile(
+        String container,
+        StorageFileType type) throws IOException{
+        switch (type) {
+            case PACKAGE_MAP:
+                return mapStorageFile(STORAGEDIR + "/maps/" + container + ".package.map");
+            case FLAG_MAP:
+                return mapStorageFile(STORAGEDIR + "/maps/" + container + ".flag.map");
+            case FLAG_VAL:
+                return mapStorageFile(STORAGEDIR + "/boot/" + container + ".val");
+            case FLAG_INFO:
+                return mapStorageFile(STORAGEDIR + "/boot/" + container + ".info");
+            default:
+                throw new IOException("Invalid storage file type");
+        }
+    }
+
+    // JNI interface to get package read context
+    // @param mappedFile: memory mapped package map file
+    // @param packageName: package name
+    // @throws IOException if the passed in file is not a valid package map file
+    @FastNative
+    private static native ByteBuffer getPackageReadContextImpl(
+        ByteBuffer mappedFile, String packageName) throws IOException;
+
+    // API to get package read context
+    // @param mappedFile: memory mapped package map file
+    // @param packageName: package name
+    // @throws IOException if the passed in file is not a valid package map file
+    static public PackageReadContext getPackageReadContext (
+        ByteBuffer mappedFile, String packageName) throws IOException {
+        ByteBuffer buffer = getPackageReadContextImpl(mappedFile, packageName);
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+        return new PackageReadContext(buffer.getInt(), buffer.getInt(4));
+    }
+
+    // JNI interface to get flag read context
+    // @param mappedFile: memory mapped flag map file
+    // @param packageId: package id to represent a specific package, obtained from
+    // package map file
+    // @param flagName: flag name
+    // @throws IOException if the passed in file is not a valid flag map file
+    @FastNative
+    private static native ByteBuffer getFlagReadContextImpl(
+        ByteBuffer mappedFile, int packageId, String flagName) throws IOException;
+
+    // API to get flag read context
+    // @param mappedFile: memory mapped flag map file
+    // @param packageId: package id to represent a specific package, obtained from
+    // package map file
+    // @param flagName: flag name
+    // @throws IOException if the passed in file is not a valid flag map file
+    public static FlagReadContext getFlagReadContext(
+        ByteBuffer mappedFile, int packageId, String flagName) throws IOException {
+        ByteBuffer buffer = getFlagReadContextImpl(mappedFile, packageId, flagName);
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+        return new FlagReadContext(buffer.getInt(), buffer.getInt(4));
+    }
+
+    // JNI interface to get boolean flag value
+    // @param mappedFile: memory mapped flag value file
+    // @param flagIndex: flag global index in the flag value array
+    // @throws IOException if the passed in file is not a valid flag value file or the
+    // flag index went over the file boundary.
+    @FastNative
+    public static native boolean getBooleanFlagValue(
+        ByteBuffer mappedFile, int flagIndex) throws IOException;
+
+    static {
+        System.loadLibrary("aconfig_storage_read_api_rust_jni");
+    }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/FlagReadContext.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/FlagReadContext.java
new file mode 100644
index 0000000..60559a9
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/FlagReadContext.java
@@ -0,0 +1,47 @@
+package android.aconfig.storage;
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class FlagReadContext {
+    public StoredFlagType mFlagType;
+    public int mFlagIndex;
+
+    public FlagReadContext(int flagType,
+            int flagIndex) {
+        mFlagType = StoredFlagType.fromInteger(flagType);
+        mFlagIndex = flagIndex;
+    }
+
+    // Flag type enum, consistent with the definition in aconfig_storage_file/src/lib.rs
+    public enum StoredFlagType {
+        ReadWriteBoolean,
+        ReadOnlyBoolean,
+        FixedReadOnlyBoolean;
+
+        public static StoredFlagType fromInteger(int x) {
+            switch(x) {
+                case 0:
+                    return ReadWriteBoolean;
+                case 1:
+                    return ReadOnlyBoolean;
+                case 2:
+                    return FixedReadOnlyBoolean;
+                default:
+                    return null;
+            }
+        }
+    }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/PackageReadContext.java
similarity index 60%
rename from tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
rename to tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/PackageReadContext.java
index 84f31aa..b781d9b 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/PackageReadContext.java
@@ -1,5 +1,6 @@
+package android.aconfig.storage;
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,13 +15,13 @@
  * limitations under the License.
  */
 
-use anyhow::Result;
-use std::fs;
-use tempfile::NamedTempFile;
+public class PackageReadContext {
+    public int mPackageId;
+    public int mBooleanStartIndex;
 
-/// Create temp file copy
-pub(crate) fn copy_to_temp_file(source_file: &str) -> Result<NamedTempFile> {
-    let file = NamedTempFile::new()?;
-    fs::copy(source_file, file.path())?;
-    Ok(file)
+    public PackageReadContext(int packageId,
+                              int booleanStartIndex) {
+        mPackageId = packageId;
+        mBooleanStartIndex = booleanStartIndex;
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/lib.rs b/tools/aconfig/aconfig_storage_read_api/srcs/lib.rs
new file mode 100644
index 0000000..304a059
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/lib.rs
@@ -0,0 +1,160 @@
+//! aconfig storage read api java rust interlop
+
+use aconfig_storage_read_api::flag_table_query::find_flag_read_context;
+use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value;
+use aconfig_storage_read_api::package_table_query::find_package_read_context;
+use aconfig_storage_read_api::{FlagReadContext, PackageReadContext};
+
+use anyhow::Result;
+use jni::objects::{JByteBuffer, JClass, JString};
+use jni::sys::{jboolean, jint};
+use jni::JNIEnv;
+
+/// Call rust find package read context
+fn get_package_read_context_java(
+    env: &mut JNIEnv,
+    file: JByteBuffer,
+    package: JString,
+) -> Result<Option<PackageReadContext>> {
+    // SAFETY:
+    // The safety here is ensured as the package name is guaranteed to be a java string
+    let package_name: String = unsafe { env.get_string_unchecked(&package)?.into() };
+    let buffer_ptr = env.get_direct_buffer_address(&file)?;
+    let buffer_size = env.get_direct_buffer_capacity(&file)?;
+    // SAFETY:
+    // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
+    // so the conversion to slice is guaranteed to be valid
+    let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
+    Ok(find_package_read_context(buffer, &package_name)?)
+}
+
+/// Get package read context JNI
+#[no_mangle]
+#[allow(unused)]
+pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getPackageReadContextImpl<
+    'local,
+>(
+    mut env: JNIEnv<'local>,
+    class: JClass<'local>,
+    file: JByteBuffer<'local>,
+    package: JString<'local>,
+) -> JByteBuffer<'local> {
+    let mut package_id = -1;
+    let mut boolean_start_index = -1;
+
+    match get_package_read_context_java(&mut env, file, package) {
+        Ok(context_opt) => {
+            if let Some(context) = context_opt {
+                package_id = context.package_id as i32;
+                boolean_start_index = context.boolean_start_index as i32;
+            }
+        }
+        Err(errmsg) => {
+            env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
+        }
+    }
+
+    let mut bytes = Vec::new();
+    bytes.extend_from_slice(&package_id.to_le_bytes());
+    bytes.extend_from_slice(&boolean_start_index.to_le_bytes());
+    let (addr, len) = {
+        let buf = bytes.leak();
+        (buf.as_mut_ptr(), buf.len())
+    };
+    // SAFETY:
+    // The safety here is ensured as the content is ensured to be valid
+    unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
+}
+
+/// Call rust find flag read context
+fn get_flag_read_context_java(
+    env: &mut JNIEnv,
+    file: JByteBuffer,
+    package_id: jint,
+    flag: JString,
+) -> Result<Option<FlagReadContext>> {
+    // SAFETY:
+    // The safety here is ensured as the flag name is guaranteed to be a java string
+    let flag_name: String = unsafe { env.get_string_unchecked(&flag)?.into() };
+    let buffer_ptr = env.get_direct_buffer_address(&file)?;
+    let buffer_size = env.get_direct_buffer_capacity(&file)?;
+    // SAFETY:
+    // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
+    // so the conversion to slice is guaranteed to be valid
+    let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
+    Ok(find_flag_read_context(buffer, package_id as u32, &flag_name)?)
+}
+
+/// Get flag read context JNI
+#[no_mangle]
+#[allow(unused)]
+pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getFlagReadContextImpl<
+    'local,
+>(
+    mut env: JNIEnv<'local>,
+    class: JClass<'local>,
+    file: JByteBuffer<'local>,
+    package_id: jint,
+    flag: JString<'local>,
+) -> JByteBuffer<'local> {
+    let mut flag_type = -1;
+    let mut flag_index = -1;
+
+    match get_flag_read_context_java(&mut env, file, package_id, flag) {
+        Ok(context_opt) => {
+            if let Some(context) = context_opt {
+                flag_type = context.flag_type as i32;
+                flag_index = context.flag_index as i32;
+            }
+        }
+        Err(errmsg) => {
+            env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
+        }
+    }
+
+    let mut bytes = Vec::new();
+    bytes.extend_from_slice(&flag_type.to_le_bytes());
+    bytes.extend_from_slice(&flag_index.to_le_bytes());
+    let (addr, len) = {
+        let buf = bytes.leak();
+        (buf.as_mut_ptr(), buf.len())
+    };
+    // SAFETY:
+    // The safety here is ensured as the content is ensured to be valid
+    unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
+}
+
+/// Call rust find boolean flag value
+fn get_boolean_flag_value_java(
+    env: &mut JNIEnv,
+    file: JByteBuffer,
+    flag_index: jint,
+) -> Result<bool> {
+    let buffer_ptr = env.get_direct_buffer_address(&file)?;
+    let buffer_size = env.get_direct_buffer_capacity(&file)?;
+    // SAFETY:
+    // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
+    // so the conversion to slice is guaranteed to be valid
+    let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
+    Ok(find_boolean_flag_value(buffer, flag_index as u32)?)
+}
+
+/// Get flag value JNI
+#[no_mangle]
+#[allow(unused)]
+pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getBooleanFlagValue<
+    'local,
+>(
+    mut env: JNIEnv<'local>,
+    class: JClass<'local>,
+    file: JByteBuffer<'local>,
+    flag_index: jint,
+) -> jboolean {
+    match get_boolean_flag_value_java(&mut env, file, flag_index) {
+        Ok(value) => value as u8,
+        Err(errmsg) => {
+            env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
+            0u8
+        }
+    }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
index 6b05ca6..ed0c728 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
@@ -1,20 +1,25 @@
+filegroup {
+    name: "read_api_test_storage_files",
+    srcs: ["package.map",
+        "flag.map",
+        "flag.val",
+        "flag.info"
+    ],
+}
+
 rust_test {
     name: "aconfig_storage_read_api.test.rust",
     srcs: [
-        "storage_read_api_test.rs"
+        "storage_read_api_test.rs",
     ],
     rustlibs: [
         "libanyhow",
         "libaconfig_storage_file",
         "libaconfig_storage_read_api",
-        "libprotobuf",
-        "libtempfile",
+        "librand",
     ],
     data: [
-        "package.map",
-        "flag.map",
-        "flag.val",
-        "flag.info",
+        ":read_api_test_storage_files",
     ],
     test_suites: ["general-tests"],
 }
@@ -26,17 +31,12 @@
     ],
     static_libs: [
         "libgmock",
-        "libaconfig_storage_protos_cc",
-        "libprotobuf-cpp-lite",
         "libaconfig_storage_read_api_cc",
         "libbase",
         "liblog",
     ],
     data: [
-        "package.map",
-        "flag.map",
-        "flag.val",
-        "flag.info",
+        ":read_api_test_storage_files",
     ],
     test_suites: [
         "device-tests",
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigStorageReadAPITest.java b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigStorageReadAPITest.java
new file mode 100644
index 0000000..a26b257
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigStorageReadAPITest.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package android.aconfig.storage.test;
+
+import java.io.IOException;
+import java.nio.MappedByteBuffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import android.aconfig.storage.AconfigStorageReadAPI;
+import android.aconfig.storage.PackageReadContext;
+import android.aconfig.storage.FlagReadContext;
+import android.aconfig.storage.FlagReadContext.StoredFlagType;
+
+@RunWith(JUnit4.class)
+public class AconfigStorageReadAPITest{
+
+    private String mStorageDir = "/data/local/tmp/aconfig_java_api_test";
+
+    @Test
+    public void testPackageContextQuery() {
+        MappedByteBuffer packageMap = null;
+        try {
+            packageMap = AconfigStorageReadAPI.mapStorageFile(
+                mStorageDir + "/maps/mockup.package.map");
+        } catch(IOException ex){
+            assertTrue(ex.toString(), false);
+        }
+        assertTrue(packageMap != null);
+
+        try {
+            PackageReadContext context = AconfigStorageReadAPI.getPackageReadContext(
+                packageMap, "com.android.aconfig.storage.test_1");
+            assertEquals(context.mPackageId, 0);
+            assertEquals(context.mBooleanStartIndex, 0);
+
+            context = AconfigStorageReadAPI.getPackageReadContext(
+                packageMap, "com.android.aconfig.storage.test_2");
+            assertEquals(context.mPackageId, 1);
+            assertEquals(context.mBooleanStartIndex, 3);
+
+            context = AconfigStorageReadAPI.getPackageReadContext(
+                packageMap, "com.android.aconfig.storage.test_4");
+            assertEquals(context.mPackageId, 2);
+            assertEquals(context.mBooleanStartIndex, 6);
+        } catch (IOException ex) {
+            assertTrue(ex.toString(), false);
+        }
+    }
+
+    @Test
+    public void testNonExistPackageContextQuery() {
+        MappedByteBuffer packageMap = null;
+        try {
+            packageMap = AconfigStorageReadAPI.mapStorageFile(
+                mStorageDir + "/maps/mockup.package.map");
+        } catch(IOException ex){
+            assertTrue(ex.toString(), false);
+        }
+        assertTrue(packageMap != null);
+
+        try {
+            PackageReadContext context = AconfigStorageReadAPI.getPackageReadContext(
+                packageMap, "unknown");
+            assertEquals(context.mPackageId, -1);
+            assertEquals(context.mBooleanStartIndex, -1);
+        } catch(IOException ex){
+            assertTrue(ex.toString(), false);
+        }
+    }
+
+    @Test
+    public void testFlagContextQuery() {
+        MappedByteBuffer flagMap = null;
+        try {
+            flagMap = AconfigStorageReadAPI.mapStorageFile(
+                mStorageDir + "/maps/mockup.flag.map");
+        } catch(IOException ex){
+            assertTrue(ex.toString(), false);
+        }
+        assertTrue(flagMap!= null);
+
+        class Baseline {
+            public int mPackageId;
+            public String mFlagName;
+            public StoredFlagType mFlagType;
+            public int mFlagIndex;
+
+            public Baseline(int packageId,
+                    String flagName,
+                    StoredFlagType flagType,
+                    int flagIndex) {
+                mPackageId = packageId;
+                mFlagName = flagName;
+                mFlagType = flagType;
+                mFlagIndex = flagIndex;
+            }
+        }
+
+        List<Baseline> baselines = new ArrayList();
+        baselines.add(new Baseline(0, "enabled_ro", StoredFlagType.ReadOnlyBoolean, 1));
+        baselines.add(new Baseline(0, "enabled_rw", StoredFlagType.ReadWriteBoolean, 2));
+        baselines.add(new Baseline(2, "enabled_rw", StoredFlagType.ReadWriteBoolean, 1));
+        baselines.add(new Baseline(1, "disabled_rw", StoredFlagType.ReadWriteBoolean, 0));
+        baselines.add(new Baseline(1, "enabled_fixed_ro", StoredFlagType.FixedReadOnlyBoolean, 1));
+        baselines.add(new Baseline(1, "enabled_ro", StoredFlagType.ReadOnlyBoolean, 2));
+        baselines.add(new Baseline(2, "enabled_fixed_ro", StoredFlagType.FixedReadOnlyBoolean, 0));
+        baselines.add(new Baseline(0, "disabled_rw", StoredFlagType.ReadWriteBoolean, 0));
+
+        try {
+            for (Baseline baseline : baselines) {
+                FlagReadContext context = AconfigStorageReadAPI.getFlagReadContext(
+                    flagMap, baseline.mPackageId,  baseline.mFlagName);
+                assertEquals(context.mFlagType, baseline.mFlagType);
+                assertEquals(context.mFlagIndex, baseline.mFlagIndex);
+            }
+        } catch (IOException ex) {
+            assertTrue(ex.toString(), false);
+        }
+    }
+
+    @Test
+    public void testNonExistFlagContextQuery() {
+        MappedByteBuffer flagMap = null;
+        try {
+            flagMap = AconfigStorageReadAPI.mapStorageFile(
+                mStorageDir + "/maps/mockup.flag.map");
+        } catch(IOException ex){
+            assertTrue(ex.toString(), false);
+        }
+        assertTrue(flagMap!= null);
+
+        try {
+            FlagReadContext context = AconfigStorageReadAPI.getFlagReadContext(
+                flagMap, 0,  "unknown");
+            assertEquals(context.mFlagType, null);
+            assertEquals(context.mFlagIndex, -1);
+
+            context = AconfigStorageReadAPI.getFlagReadContext(
+                flagMap, 3,  "enabled_ro");
+            assertEquals(context.mFlagType, null);
+            assertEquals(context.mFlagIndex, -1);
+        } catch (IOException ex) {
+            assertTrue(ex.toString(), false);
+        }
+    }
+
+    @Test
+    public void testBooleanFlagValueQuery() {
+        MappedByteBuffer flagVal = null;
+        try {
+            flagVal = AconfigStorageReadAPI.mapStorageFile(
+                mStorageDir + "/boot/mockup.val");
+        } catch (IOException ex) {
+            assertTrue(ex.toString(), false);
+        }
+        assertTrue(flagVal!= null);
+
+        boolean[] baselines = {false, true, true, false, true, true, true, true};
+        for (int i = 0; i < 8; ++i) {
+            try {
+                Boolean value = AconfigStorageReadAPI.getBooleanFlagValue(flagVal, i);
+                assertEquals(value, baselines[i]);
+            } catch (IOException ex) {
+                assertTrue(ex.toString(), false);
+            }
+        }
+    }
+
+    @Test
+    public void testInvalidBooleanFlagValueQuery() {
+        MappedByteBuffer flagVal = null;
+        try {
+            flagVal = AconfigStorageReadAPI.mapStorageFile(
+                mStorageDir + "/boot/mockup.val");
+        } catch (IOException ex) {
+            assertTrue(ex.toString(), false);
+        }
+        assertTrue(flagVal!= null);
+
+        try {
+            Boolean value = AconfigStorageReadAPI.getBooleanFlagValue(flagVal, 9);
+            assertTrue("should throw", false);
+        } catch (IOException ex) {
+            String expectedErrmsg = "invalid storage file byte offset";
+            assertTrue(ex.toString(), ex.toString().contains(expectedErrmsg));
+        }
+    }
+ }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
new file mode 100644
index 0000000..d94b2b4
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
@@ -0,0 +1,21 @@
+android_test {
+    name: "aconfig_storage_read_api.test.java",
+    srcs: ["AconfigStorageReadAPITest.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "libaconfig_storage_read_api_java",
+        "junit",
+    ],
+    jni_libs: [
+        "libaconfig_storage_read_api_rust_jni",
+    ],
+    data: [
+        ":read_api_test_storage_files",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+    test_suites: [
+        "general-tests",
+    ],
+    team: "trendy_team_android_core_experiments",
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidManifest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidManifest.xml
new file mode 100644
index 0000000..78bfb37
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.aconfig_storage.test">
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.aconfig_storage.test" />
+
+</manifest>
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
new file mode 100644
index 0000000..99c9e25
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Config for aconfig storage read java api tests">
+    <!-- Need root to start virtualizationservice -->
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <!-- Prepare test directories. -->
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="throw-if-cmd-fail" value="true" />
+        <option name="run-command" value="mkdir -p /data/local/tmp/aconfig_java_api" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/aconfig_java_api" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="aconfig_storage_read_api.test.java.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer" />
+
+    <!-- Test data files -->
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="abort-on-push-failure" value="true" />
+        <option name="push-file" key="package.map"
+                value="/data/local/tmp/aconfig_java_api_test/maps/mockup.package.map" />
+        <option name="push-file" key="flag.map"
+                value="/data/local/tmp/aconfig_java_api_test/maps/mockup.flag.map" />
+        <option name="push-file" key="flag.val"
+                value="/data/local/tmp/aconfig_java_api_test/boot/mockup.val" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="package" value="android.aconfig_storage.test" />
+        <option name="runtime-hint" value="1m" />
+    </test>
+</configuration>
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
index 5393c49..6d29045 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
@@ -22,11 +22,9 @@
 #include <sys/stat.h>
 #include "aconfig_storage/aconfig_storage_read_api.hpp"
 #include <gtest/gtest.h>
-#include <protos/aconfig_storage_metadata.pb.h>
 #include <android-base/file.h>
 #include <android-base/result.h>
 
-using android::aconfig_storage_metadata::storage_files;
 using namespace android::base;
 
 namespace api = aconfig_storage;
@@ -34,49 +32,33 @@
 
 class AconfigStorageTest : public ::testing::Test {
  protected:
-  Result<std::string> copy_to_temp_file(std::string const& source_file) {
-    auto temp_file = std::string(std::tmpnam(nullptr));
+  Result<void> copy_file(std::string const& src_file,
+                         std::string const& dst_file) {
     auto content = std::string();
-    if (!ReadFileToString(source_file, &content)) {
-      return Error() << "failed to read file: " << source_file;
+    if (!ReadFileToString(src_file, &content)) {
+      return Error() << "failed to read file: " << src_file;
     }
-    if (!WriteStringToFile(content, temp_file)) {
-      return Error() << "failed to copy file: " << source_file;
+    if (!WriteStringToFile(content, dst_file)) {
+      return Error() << "failed to copy file: " << dst_file;
     }
-    return temp_file;
-  }
-
-  Result<std::string> write_storage_location_pb_file(std::string const& package_map,
-                                                     std::string const& flag_map,
-                                                     std::string const& flag_val,
-                                                     std::string const& flag_info) {
-    auto temp_file = std::tmpnam(nullptr);
-    auto proto = storage_files();
-    auto* info = proto.add_files();
-    info->set_version(0);
-    info->set_container("mockup");
-    info->set_package_map(package_map);
-    info->set_flag_map(flag_map);
-    info->set_flag_val(flag_val);
-    info->set_flag_info(flag_info);
-    info->set_timestamp(12345);
-
-    auto content = std::string();
-    proto.SerializeToString(&content);
-    if (!WriteStringToFile(content, temp_file)) {
-      return Error() << "failed to write storage records pb file";
-    }
-    return temp_file;
+    return {};
   }
 
   void SetUp() override {
     auto const test_dir = android::base::GetExecutableDirectory();
-    package_map = *copy_to_temp_file(test_dir + "/package.map");
-    flag_map = *copy_to_temp_file(test_dir + "/flag.map");
-    flag_val = *copy_to_temp_file(test_dir + "/flag.val");
-    flag_info = *copy_to_temp_file(test_dir + "/flag.info");
-    storage_record_pb = *write_storage_location_pb_file(
-        package_map, flag_map, flag_val, flag_info);
+    storage_dir = std::string(root_dir.path);
+    auto maps_dir = storage_dir + "/maps";
+    auto boot_dir = storage_dir + "/boot";
+    mkdir(maps_dir.c_str(), 0775);
+    mkdir(boot_dir.c_str(), 0775);
+    package_map = std::string(maps_dir) + "/mockup.package.map";
+    flag_map = std::string(maps_dir) + "/mockup.flag.map";
+    flag_val = std::string(boot_dir) + "/mockup.val";
+    flag_info = std::string(boot_dir) + "/mockup.info";
+    copy_file(test_dir + "/package.map", package_map);
+    copy_file(test_dir + "/flag.map", flag_map);
+    copy_file(test_dir + "/flag.val", flag_val);
+    copy_file(test_dir + "/flag.info", flag_info);
   }
 
   void TearDown() override {
@@ -84,14 +66,14 @@
     std::remove(flag_map.c_str());
     std::remove(flag_val.c_str());
     std::remove(flag_info.c_str());
-    std::remove(storage_record_pb.c_str());
   }
 
+  TemporaryDir root_dir;
+  std::string storage_dir;
   std::string package_map;
   std::string flag_map;
   std::string flag_val;
   std::string flag_info;
-  std::string storage_record_pb;
 };
 
 /// Test to lock down storage file version query api
@@ -113,16 +95,17 @@
 /// Negative test to lock down the error when mapping none exist storage files
 TEST_F(AconfigStorageTest, test_none_exist_storage_file_mapping) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "vendor", api::StorageFileType::package_map);
+      storage_dir, "vendor", api::StorageFileType::package_map);
   ASSERT_FALSE(mapped_file_result.ok());
-  ASSERT_EQ(mapped_file_result.error().message(),
-            "Unable to find storage files for container vendor");
+  ASSERT_EQ(mapped_file_result.error(),
+            std::string("failed to open ") + storage_dir
+            + "/maps/vendor.package.map: No such file or directory");
 }
 
 /// Test to lock down storage package context query api
 TEST_F(AconfigStorageTest, test_package_context_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::package_map);
+      storage_dir, "mockup", api::StorageFileType::package_map);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
@@ -151,7 +134,7 @@
 /// Test to lock down when querying none exist package
 TEST_F(AconfigStorageTest, test_none_existent_package_context_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::package_map);
+      storage_dir, "mockup", api::StorageFileType::package_map);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
@@ -164,7 +147,7 @@
 /// Test to lock down storage flag context query api
 TEST_F(AconfigStorageTest, test_flag_context_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::flag_map);
+      storage_dir, "mockup", api::StorageFileType::flag_map);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
@@ -190,7 +173,7 @@
 /// Test to lock down when querying none exist flag
 TEST_F(AconfigStorageTest, test_none_existent_flag_context_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::flag_map);
+      storage_dir, "mockup", api::StorageFileType::flag_map);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
@@ -206,7 +189,7 @@
 /// Test to lock down storage flag value query api
 TEST_F(AconfigStorageTest, test_boolean_flag_value_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::flag_val);
+      storage_dir, "mockup", api::StorageFileType::flag_val);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
@@ -222,20 +205,20 @@
 /// Negative test to lock down the error when querying flag value out of range
 TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::flag_val);
+      storage_dir, "mockup", api::StorageFileType::flag_val);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
   auto value = api::get_boolean_flag_value(*mapped_file, 8);
   ASSERT_FALSE(value.ok());
-  ASSERT_EQ(value.error().message(),
+  ASSERT_EQ(value.error(),
             std::string("InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"));
 }
 
 /// Test to lock down storage flag info query api
 TEST_F(AconfigStorageTest, test_boolean_flag_info_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::flag_info);
+      storage_dir, "mockup", api::StorageFileType::flag_info);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
@@ -254,12 +237,12 @@
 /// Negative test to lock down the error when querying flag info out of range
 TEST_F(AconfigStorageTest, test_invalid_boolean_flag_info_query) {
   auto mapped_file_result = private_api::get_mapped_file_impl(
-      storage_record_pb, "mockup", api::StorageFileType::flag_info);
+      storage_dir, "mockup", api::StorageFileType::flag_info);
   ASSERT_TRUE(mapped_file_result.ok());
   auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result);
 
   auto attribute = api::get_flag_attribute(*mapped_file, api::FlagValueType::Boolean, 8);
   ASSERT_FALSE(attribute.ok());
-  ASSERT_EQ(attribute.error().message(),
+  ASSERT_EQ(attribute.error(),
             std::string("InvalidStorageFileOffset(Flag info offset goes beyond the end of the file.)"));
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
index ecba573..afc44d4 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
@@ -1,71 +1,63 @@
 #[cfg(not(feature = "cargo"))]
 mod aconfig_storage_rust_test {
-    use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
     use aconfig_storage_file::{FlagInfoBit, FlagValueType, StorageFileType, StoredFlagType};
     use aconfig_storage_read_api::{
         get_boolean_flag_value, get_flag_attribute, get_flag_read_context,
         get_package_read_context, get_storage_file_version, mapped_file::get_mapped_file,
         PackageReadContext,
     };
+    use rand::Rng;
     use std::fs;
-    use tempfile::NamedTempFile;
 
-    pub fn copy_to_temp_file(source_file: &str) -> NamedTempFile {
-        let file = NamedTempFile::new().unwrap();
-        fs::copy(source_file, file.path()).unwrap();
-        file
-    }
+    fn create_test_storage_files() -> String {
+        let mut rng = rand::thread_rng();
+        let number: u32 = rng.gen();
+        let storage_dir = String::from("/tmp/") + &number.to_string();
+        if std::fs::metadata(&storage_dir).is_ok() {
+            fs::remove_dir_all(&storage_dir).unwrap();
+        }
+        let maps_dir = storage_dir.clone() + "/maps";
+        let boot_dir = storage_dir.clone() + "/boot";
+        fs::create_dir(&storage_dir).unwrap();
+        fs::create_dir(maps_dir).unwrap();
+        fs::create_dir(boot_dir).unwrap();
 
-    fn create_test_storage_files() -> [NamedTempFile; 5] {
-        let package_map = copy_to_temp_file("./package.map");
-        let flag_map = copy_to_temp_file("./flag.map");
-        let flag_val = copy_to_temp_file("./flag.val");
-        let flag_info = copy_to_temp_file("./flag.info");
+        let package_map = storage_dir.clone() + "/maps/mockup.package.map";
+        let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
+        let flag_val = storage_dir.clone() + "/boot/mockup.val";
+        let flag_info = storage_dir.clone() + "/boot/mockup.info";
+        fs::copy("./package.map", package_map).unwrap();
+        fs::copy("./flag.map", flag_map).unwrap();
+        fs::copy("./flag.val", flag_val).unwrap();
+        fs::copy("./flag.info", flag_info).unwrap();
 
-        let text_proto = format!(
-            r#"
-files {{
-    version: 0
-    container: "mockup"
-    package_map: "{}"
-    flag_map: "{}"
-    flag_val: "{}"
-    flag_info: "{}"
-    timestamp: 12345
-}}
-"#,
-            package_map.path().display(),
-            flag_map.path().display(),
-            flag_val.path().display(),
-            flag_info.path().display()
-        );
-        let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
-        [package_map, flag_map, flag_val, flag_info, pb_file]
+        storage_dir
     }
 
     #[test]
     fn test_unavailable_stoarge() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let err = unsafe {
-            get_mapped_file(&pb_file_path, "vendor", StorageFileType::PackageMap).unwrap_err()
+            get_mapped_file(&storage_dir, "vendor", StorageFileType::PackageMap).unwrap_err()
         };
         assert_eq!(
             format!("{:?}", err),
-            "StorageFileNotFound(Storage file does not exist for vendor)"
+            format!(
+                "StorageFileNotFound(storage file {}/maps/vendor.package.map does not exist)",
+                storage_dir
+            )
         );
     }
 
     #[test]
     fn test_package_context_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let package_mapped_file = unsafe {
-            get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
+            get_mapped_file(&storage_dir, "mockup", StorageFileType::PackageMap).unwrap()
         };
 
         let package_context =
@@ -92,12 +84,11 @@
 
     #[test]
     fn test_none_exist_package_context_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let package_mapped_file = unsafe {
-            get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
+            get_mapped_file(&storage_dir, "mockup", StorageFileType::PackageMap).unwrap()
         };
 
         let package_context_option =
@@ -108,12 +99,11 @@
 
     #[test]
     fn test_flag_context_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_mapped_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagMap).unwrap() };
 
         let baseline = vec![
             (0, "enabled_ro", StoredFlagType::ReadOnlyBoolean, 1u16),
@@ -135,12 +125,11 @@
 
     #[test]
     fn test_none_exist_flag_context_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_mapped_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagMap).unwrap() };
         let flag_context_option =
             get_flag_read_context(&flag_mapped_file, 0, "none_exist").unwrap();
         assert_eq!(flag_context_option, None);
@@ -152,12 +141,11 @@
 
     #[test]
     fn test_boolean_flag_value_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_value_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagVal).unwrap() };
         let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
         for (offset, expected_value) in baseline.into_iter().enumerate() {
             let flag_value = get_boolean_flag_value(&flag_value_file, offset as u32).unwrap();
@@ -167,12 +155,11 @@
 
     #[test]
     fn test_invalid_boolean_flag_value_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_value_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagVal).unwrap() };
         let err = get_boolean_flag_value(&flag_value_file, 8u32).unwrap_err();
         assert_eq!(
             format!("{:?}", err),
@@ -182,12 +169,11 @@
 
     #[test]
     fn test_flag_info_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_info_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagInfo).unwrap() };
         let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true];
         for (offset, expected_value) in is_rw.into_iter().enumerate() {
             let attribute =
@@ -200,12 +186,11 @@
 
     #[test]
     fn test_invalid_boolean_flag_info_query() {
-        let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
-        let pb_file_path = pb_file.path().display().to_string();
+        let storage_dir = create_test_storage_files();
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_info_file =
-            unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
+            unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagInfo).unwrap() };
         let err = get_flag_attribute(&flag_info_file, FlagValueType::Boolean, 8u32).unwrap_err();
         assert_eq!(
             format!("{:?}", err),
diff --git a/tools/aconfig/aconfig_storage_write_api/Android.bp b/tools/aconfig/aconfig_storage_write_api/Android.bp
index 4dbdbbf..0f1962c 100644
--- a/tools/aconfig/aconfig_storage_write_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_write_api/Android.bp
@@ -77,7 +77,6 @@
     export_include_dirs: ["include"],
     static_libs: [
         "libaconfig_storage_read_api_cc",
-        "libaconfig_storage_protos_cc",
         "libprotobuf-cpp-lite",
         "libbase",
     ],
diff --git a/tools/aconfig/aconfig_storage_write_api/Cargo.toml b/tools/aconfig/aconfig_storage_write_api/Cargo.toml
index eaa55f2..2ce6edf 100644
--- a/tools/aconfig/aconfig_storage_write_api/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_write_api/Cargo.toml
@@ -13,7 +13,6 @@
 memmap2 = "0.8.0"
 tempfile = "3.9.0"
 thiserror = "1.0.56"
-protobuf = "3.2.0"
 aconfig_storage_file = { path = "../aconfig_storage_file" }
 aconfig_storage_read_api = { path = "../aconfig_storage_read_api" }
 
diff --git a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
index f529f79..cabc65e 100644
--- a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
+++ b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
@@ -1,7 +1,6 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <protos/aconfig_storage_metadata.pb.h>
 
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -11,34 +10,31 @@
 #include "aconfig_storage/lib.rs.h"
 #include "aconfig_storage/aconfig_storage_write_api.hpp"
 
-using storage_records_pb = android::aconfig_storage_metadata::storage_files;
-using storage_record_pb = android::aconfig_storage_metadata::storage_file_info;
-using namespace android::base;
-
 namespace aconfig_storage {
 
 /// Map a storage file
-Result<MutableMappedStorageFile*> map_mutable_storage_file(std::string const& file) {
+android::base::Result<MutableMappedStorageFile*> map_mutable_storage_file(
+    std::string const& file) {
   struct stat file_stat;
   if (stat(file.c_str(), &file_stat) < 0) {
-    return ErrnoError() << "stat failed";
+    return android::base::ErrnoError() << "stat failed";
   }
 
   if ((file_stat.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0) {
-    return Error() << "cannot map nonwriteable file";
+    return android::base::Error() << "cannot map nonwriteable file";
   }
 
   size_t file_size = file_stat.st_size;
 
   const int fd = open(file.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC);
   if (fd == -1) {
-    return ErrnoError() << "failed to open " << file;
+    return android::base::ErrnoError() << "failed to open " << file;
   };
 
   void* const map_result =
       mmap(nullptr, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
   if (map_result == MAP_FAILED) {
-    return ErrnoError() << "mmap failed";
+    return android::base::ErrnoError() << "mmap failed";
   }
 
   auto mapped_file = new MutableMappedStorageFile();
@@ -49,7 +45,7 @@
 }
 
 /// Set boolean flag value
-Result<void> set_boolean_flag_value(
+android::base::Result<void> set_boolean_flag_value(
     const MutableMappedStorageFile& file,
     uint32_t offset,
     bool value) {
@@ -57,13 +53,13 @@
       static_cast<uint8_t*>(file.file_ptr), file.file_size);
   auto update_cxx = update_boolean_flag_value_cxx(content, offset, value);
   if (!update_cxx.update_success) {
-    return Error() << std::string(update_cxx.error_message.c_str());
+    return android::base::Error() << update_cxx.error_message.c_str();
   }
   return {};
 }
 
 /// Set if flag has server override
-Result<void> set_flag_has_server_override(
+android::base::Result<void> set_flag_has_server_override(
     const MutableMappedStorageFile& file,
     FlagValueType value_type,
     uint32_t offset,
@@ -73,13 +69,13 @@
   auto update_cxx = update_flag_has_server_override_cxx(
       content, static_cast<uint16_t>(value_type), offset, value);
   if (!update_cxx.update_success) {
-    return Error() << std::string(update_cxx.error_message.c_str());
+    return android::base::Error() << update_cxx.error_message.c_str();
   }
   return {};
 }
 
 /// Set if flag has local override
-Result<void> set_flag_has_local_override(
+android::base::Result<void> set_flag_has_local_override(
     const MutableMappedStorageFile& file,
     FlagValueType value_type,
     uint32_t offset,
@@ -89,12 +85,12 @@
   auto update_cxx = update_flag_has_local_override_cxx(
       content, static_cast<uint16_t>(value_type), offset, value);
   if (!update_cxx.update_success) {
-    return Error() << std::string(update_cxx.error_message.c_str());
+    return android::base::Error() << update_cxx.error_message.c_str();
   }
   return {};
 }
 
-Result<void> create_flag_info(
+android::base::Result<void> create_flag_info(
     std::string const& package_map,
     std::string const& flag_map,
     std::string const& flag_info_out) {
diff --git a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp
index ff06cbc..0bba7ff 100644
--- a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp
+++ b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp
@@ -6,7 +6,6 @@
 #include <android-base/result.h>
 #include <aconfig_storage/aconfig_storage_read_api.hpp>
 
-using namespace android::base;
 
 namespace aconfig_storage {
 
@@ -14,24 +13,24 @@
 struct MutableMappedStorageFile : MappedStorageFile {};
 
 /// Map a storage file
-Result<MutableMappedStorageFile*> map_mutable_storage_file(
+android::base::Result<MutableMappedStorageFile*> map_mutable_storage_file(
     std::string const& file);
 
 /// Set boolean flag value
-Result<void> set_boolean_flag_value(
+android::base::Result<void> set_boolean_flag_value(
     const MutableMappedStorageFile& file,
     uint32_t offset,
     bool value);
 
 /// Set if flag has server override
-Result<void> set_flag_has_server_override(
+android::base::Result<void> set_flag_has_server_override(
     const MutableMappedStorageFile& file,
     FlagValueType value_type,
     uint32_t offset,
     bool value);
 
 /// Set if flag has local override
-Result<void> set_flag_has_local_override(
+android::base::Result<void> set_flag_has_local_override(
     const MutableMappedStorageFile& file,
     FlagValueType value_type,
     uint32_t offset,
@@ -41,7 +40,7 @@
 /// \input package_map: package map file
 /// \input flag_map: flag map file
 /// \input flag_info_out: flag info file to be created
-Result<void> create_flag_info(
+android::base::Result<void> create_flag_info(
     std::string const& package_map,
     std::string const& flag_map,
     std::string const& flag_info_out);
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
index 85568e0..f6409b7 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
@@ -25,8 +25,6 @@
     ],
     static_libs: [
         "libgmock",
-        "libaconfig_storage_protos_cc",
-        "libprotobuf-cpp-lite",
         "libaconfig_storage_read_api_cc",
         "libaconfig_storage_write_api_cc",
         "libbase",
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
index 5437379..31183fa 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
@@ -22,11 +22,9 @@
 #include "aconfig_storage/aconfig_storage_read_api.hpp"
 #include "aconfig_storage/aconfig_storage_write_api.hpp"
 #include <gtest/gtest.h>
-#include <protos/aconfig_storage_metadata.pb.h>
 #include <android-base/file.h>
 #include <android-base/result.h>
 
-using android::aconfig_storage_metadata::storage_files;
 using namespace android::base;
 
 namespace api = aconfig_storage;
diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py
index 51ec23b..1fd7950 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -67,7 +67,7 @@
 
 ELF = collections.namedtuple(
   'ELF',
-  ('dt_soname', 'dt_needed', 'imported', 'exported', 'header'))
+  ('alignments', 'dt_soname', 'dt_needed', 'imported', 'exported', 'header'))
 
 
 def _get_os_name():
@@ -195,7 +195,8 @@
   @classmethod
   def _read_llvm_readobj(cls, elf_file_path, header, llvm_readobj):
     """Run llvm-readobj and parse the output."""
-    cmd = [llvm_readobj, '--dynamic-table', '--dyn-symbols', elf_file_path]
+    cmd = [llvm_readobj, '--program-headers', '--dynamic-table',
+           '--dyn-symbols', elf_file_path]
     out = subprocess.check_output(cmd, text=True)
     lines = out.splitlines()
     return cls._parse_llvm_readobj(elf_file_path, header, lines)
@@ -205,9 +206,56 @@
   def _parse_llvm_readobj(cls, elf_file_path, header, lines):
     """Parse the output of llvm-readobj."""
     lines_it = iter(lines)
+    alignments = cls._parse_program_headers(lines_it)
     dt_soname, dt_needed = cls._parse_dynamic_table(elf_file_path, lines_it)
     imported, exported = cls._parse_dynamic_symbols(lines_it)
-    return ELF(dt_soname, dt_needed, imported, exported, header)
+    return ELF(alignments, dt_soname, dt_needed, imported, exported, header)
+
+
+  _PROGRAM_HEADERS_START_PATTERN = 'ProgramHeaders ['
+  _PROGRAM_HEADERS_END_PATTERN = ']'
+  _PROGRAM_HEADER_START_PATTERN = 'ProgramHeader {'
+  _PROGRAM_HEADER_TYPE_PATTERN = re.compile('^\\s+Type:\\s+(.*)$')
+  _PROGRAM_HEADER_ALIGN_PATTERN = re.compile('^\\s+Alignment:\\s+(.*)$')
+  _PROGRAM_HEADER_END_PATTERN = '}'
+
+
+  @classmethod
+  def _parse_program_headers(cls, lines_it):
+    """Parse the dynamic table section."""
+    alignments = []
+
+    if not cls._find_prefix(cls._PROGRAM_HEADERS_START_PATTERN, lines_it):
+      raise ELFError()
+
+    for line in lines_it:
+      # Parse each program header
+      if line.strip() == cls._PROGRAM_HEADER_START_PATTERN:
+        p_align = None
+        p_type = None
+        for line in lines_it:
+          if line.strip() == cls._PROGRAM_HEADER_END_PATTERN:
+            if not p_align:
+              raise ELFError("Could not parse alignment from program header!")
+            if not p_type:
+              raise ELFError("Could not parse type from program header!")
+
+            if p_type.startswith("PT_LOAD "):
+              alignments.append(int(p_align))
+            break
+
+          match = cls._PROGRAM_HEADER_TYPE_PATTERN.match(line)
+          if match:
+            p_type = match.group(1)
+
+          match = cls._PROGRAM_HEADER_ALIGN_PATTERN.match(line)
+          if match:
+            p_align = match.group(1)
+
+      if line == cls._PROGRAM_HEADERS_END_PATTERN:
+        break
+
+    return alignments
 
 
   _DYNAMIC_SECTION_START_PATTERN = 'DynamicSection ['
@@ -434,6 +482,24 @@
 
       sys.exit(2)
 
+  def check_max_page_size(self, max_page_size):
+    for alignment in self._file_under_test.alignments:
+      if alignment % max_page_size != 0:
+        self._error(f'Load segment has alignment {alignment} but '
+                    f'{max_page_size} required.')
+        self._note()
+        self._note('Fix suggestions:')
+        self._note(f'  use linker flag "-Wl,-z,max-page-size={max_page_size}" '
+                   f'when compiling this lib')
+        self._note()
+        self._note('If the fix above doesn\'t work, bypass this check with:')
+        self._note('  Android.bp: ignore_max_page_size: true,')
+        self._note('  Android.mk: LOCAL_IGNORE_MAX_PAGE_SIZE := true')
+        self._note('  Device mk: PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := false')
+
+        # TODO: instead of exiting immediately, we may want to collect the
+        # errors from all checks and emit them at once
+        sys.exit(2)
 
   @staticmethod
   def _find_symbol(lib, name, version):
@@ -514,6 +580,8 @@
                       help='Ignore the input file with unknown machine ID')
   parser.add_argument('--allow-undefined-symbols', action='store_true',
                       help='Ignore unresolved undefined symbols')
+  parser.add_argument('--max-page-size', action='store', type=int,
+                      help='Required page size alignment support')
 
   # Other options
   parser.add_argument('--llvm-readobj',
@@ -542,6 +610,9 @@
 
   checker.check_dt_needed(args.system_shared_lib)
 
+  if args.max_page_size:
+    checker.check_max_page_size(args.max_page_size)
+
   if not args.allow_undefined_symbols:
     checker.check_symbols()
 
diff --git a/tools/compliance/go.mod b/tools/compliance/go.mod
index bd04077..532efd4 100644
--- a/tools/compliance/go.mod
+++ b/tools/compliance/go.mod
@@ -1,29 +1,11 @@
+go 1.22
+
 module android/soong/tools/compliance
 
-require google.golang.org/protobuf v0.0.0
-
-replace google.golang.org/protobuf v0.0.0 => ../../../../external/golang-protobuf
-
 require (
-	android/soong v0.0.0
 	github.com/google/blueprint v0.0.0
+	android/soong v0.0.0
+	google.golang.org/protobuf v0.0.0
 	github.com/spdx/tools-golang v0.0.0
+	github.com/google/go-cmp v0.0.0
 )
-
-replace github.com/spdx/tools-golang v0.0.0 => ../../../../external/spdx-tools
-
-require golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
-
-replace android/soong v0.0.0 => ../../../soong
-
-replace github.com/google/blueprint => ../../../blueprint
-
-// Indirect deps from golang-protobuf
-exclude github.com/golang/protobuf v1.5.0
-
-replace github.com/google/go-cmp v0.5.5 => ../../../../external/go-cmp
-
-// Indirect dep from go-cmp
-exclude golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
-
-go 1.21
diff --git a/tools/compliance/go.sum b/tools/compliance/go.sum
deleted file mode 100644
index cbe76d9..0000000
--- a/tools/compliance/go.sum
+++ /dev/null
@@ -1,2 +0,0 @@
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
diff --git a/tools/compliance/go.work b/tools/compliance/go.work
new file mode 100644
index 0000000..a24d2ea
--- /dev/null
+++ b/tools/compliance/go.work
@@ -0,0 +1,18 @@
+go 1.22
+
+use (
+	.
+	../../../../build/blueprint
+	../../../../build/soong
+	../../../../external/go-cmp
+	../../../../external/golang-protobuf
+	../../../../external/spdx-tools
+)
+
+replace (
+	github.com/google/blueprint v0.0.0 => ../../../../build/blueprint
+	android/soong v0.0.0 => ../../../../build/soong
+	github.com/google/go-cmp v0.0.0 => ../../../../external/go-cmp
+	google.golang.org/protobuf v0.0.0 => ../../../../external/golang-protobuf
+	github.com/spdx/tools-golang v0.0.0 => ../../../../external/spdx-tools
+)
diff --git a/tools/envsetup/run_envsetup_tests b/tools/envsetup/run_envsetup_tests
new file mode 100755
index 0000000..5977448
--- /dev/null
+++ b/tools/envsetup/run_envsetup_tests
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import pathlib
+import subprocess
+import sys
+
+SOURCE_ENVSETUP="source build/make/envsetup.sh && "
+
+def update_display():
+    sys.stderr.write("passed\n")
+
+def go_to_root():
+    while True:
+        if os.path.exists("build/make/envsetup.sh"):
+            return
+        if os.getcwd() == "/":
+            sys.stderr.write("Can't find root of the source tree\n");
+            print("\nFAILED")
+            sys.exit(1)
+        os.chdir("..")
+
+def is_test(name, thing):
+    if not callable(thing):
+        return False
+    if name == "test":
+        return False
+    return name.startswith("test")
+
+
+def test(shell, command, expected_return, expected_stdout, expected_stderr, expected_env):
+    command += "; _rc=$?"
+    for env in expected_env.keys():
+        command += f"; echo ENV: {env}=\\\"${env}\\\""
+    command += "; exit $_rc"
+
+    cmd = [shell, "-c", command]
+    result = subprocess.run(cmd, capture_output=True, text=True)
+
+    status = True
+
+    if result.returncode != expected_return:
+        print()
+        print(f"Expected return code: {expected_return}")
+        print(f"Actual return code:   {result.returncode}")
+        status = False
+
+    printed_stdout = False
+    if expected_stdout and expected_stdout not in result.stdout:
+        print()
+        print(f"Expected stdout to contain:\n{expected_stdout}")
+        print(f"\nActual stdout:\n{result.stdout}")
+        printed_stdout = True
+        status = False
+
+    if expected_stderr and expected_stderr not in result.stderr:
+        print()
+        print(f"Expected stderr to contain:\n{expected_stderr}")
+        print(f"\nActual stderr:\n{result.stderr}")
+        status = False
+
+    env_failure = False
+    for k, v in expected_env.items():
+        if f"{k}=\"{v}\"" not in result.stdout:
+            print()
+            print(f"Expected environment variable {k} to be: {v} --- {k}=\"{v}\"")
+            env_failure = True
+            status = False
+
+    if env_failure and not printed_stdout:
+        print()
+        print("See stdout:")
+        print(result.stdout)
+
+    if not status:
+        print()
+        print("Command to reproduce:")
+        print(command)
+        print()
+
+    return status
+
+NO_LUNCH = {
+    "TARGET_PRODUCT": "",
+    "TARGET_RELEASE": "",
+    "TARGET_BUILD_VARIANT": "",
+}
+
+def test_invalid_lunch_target(shell):
+    return test(shell, SOURCE_ENVSETUP + "lunch invalid-trunk_staging-eng",
+         expected_return=1, expected_stdout=None,
+         expected_stderr="Cannot locate config makefile for product",
+         expected_env=NO_LUNCH)
+
+
+def test_aosp_arm(shell):
+    return test(shell, SOURCE_ENVSETUP + "lunch aosp_arm-trunk_staging-eng",
+         expected_return=0, expected_stdout=None, expected_stderr=None,
+         expected_env={
+            "TARGET_PRODUCT": "aosp_arm",
+            "TARGET_RELEASE": "trunk_staging",
+            "TARGET_BUILD_VARIANT": "eng",
+        })
+
+
+def test_lunch2_empty(shell):
+    return test(shell, SOURCE_ENVSETUP + "lunch2",
+         expected_return=1, expected_stdout=None,
+         expected_stderr="No target specified. See lunch --help",
+         expected_env=NO_LUNCH)
+
+def test_lunch2_four_params(shell):
+    return test(shell, SOURCE_ENVSETUP + "lunch2 a b c d",
+         expected_return=1, expected_stdout=None,
+         expected_stderr="Too many parameters given. See lunch --help",
+         expected_env=NO_LUNCH)
+
+def test_lunch2_aosp_arm(shell):
+    return test(shell, SOURCE_ENVSETUP + "lunch2 aosp_arm",
+         expected_return=0, expected_stdout="=========", expected_stderr=None,
+         expected_env={
+            "TARGET_PRODUCT": "aosp_arm",
+            "TARGET_RELEASE": "trunk_staging",
+            "TARGET_BUILD_VARIANT": "eng",
+        })
+
+def test_lunch2_aosp_arm_trunk_staging(shell):
+    # Somewhat unfortunate because trunk_staging is the only config in
+    # aosp so we can't really test that this isn't just getting the default
+    return test(shell, SOURCE_ENVSETUP + "lunch2 aosp_arm trunk_staging",
+         expected_return=0, expected_stdout="=========", expected_stderr=None,
+         expected_env={
+            "TARGET_PRODUCT": "aosp_arm",
+            "TARGET_RELEASE": "trunk_staging",
+            "TARGET_BUILD_VARIANT": "eng",
+        })
+
+def test_lunch2_aosp_arm_trunk_staging_userdebug(shell):
+    return test(shell, SOURCE_ENVSETUP + "lunch2 aosp_arm trunk_staging userdebug",
+         expected_return=0, expected_stdout="=========", expected_stderr=None,
+         expected_env={
+            "TARGET_PRODUCT": "aosp_arm",
+            "TARGET_RELEASE": "trunk_staging",
+            "TARGET_BUILD_VARIANT": "userdebug",
+        })
+
+def test_list_products(shell):
+    return test(shell, "build/soong/bin/list_products",
+         expected_return=0, expected_stdout="aosp_arm", expected_stderr=None,
+         expected_env=NO_LUNCH)
+
+def test_list_releases_param(shell):
+    return test(shell, "build/soong/bin/list_releases aosp_arm",
+         expected_return=0, expected_stdout="trunk_staging", expected_stderr=None,
+         expected_env=NO_LUNCH)
+
+def test_list_releases_env(shell):
+    return test(shell, "TARGET_PRODUCT=aosp_arm build/soong/bin/list_releases",
+         expected_return=0, expected_stdout="trunk_staging", expected_stderr=None,
+         expected_env=NO_LUNCH)
+
+def test_list_releases_no_product(shell):
+    return test(shell, "build/soong/bin/list_releases",
+         expected_return=1, expected_stdout=None, expected_stderr=None,
+         expected_env=NO_LUNCH)
+
+def test_list_variants(shell):
+    return test(shell, "build/soong/bin/list_variants",
+         expected_return=0, expected_stdout="userdebug", expected_stderr=None,
+         expected_env=NO_LUNCH)
+
+
+def test_get_build_var_in_path(shell):
+    return test(shell, SOURCE_ENVSETUP + "which get_build_var ",
+         expected_return=0, expected_stdout="soong/bin", expected_stderr=None,
+         expected_env=NO_LUNCH)
+
+
+
+TESTS=sorted([(name, thing) for name, thing in locals().items() if is_test(name, thing)])
+
+def main():
+    if any([x.endswith("/soong/bin") for x in os.getenv("PATH").split(":")]):
+        sys.stderr.write("run_envsetup_tests must be run in a shell that has not sourced"
+                + " envsetup.sh\n\nFAILED\n")
+        return 1
+
+    go_to_root()
+
+    tests = TESTS
+    if len(sys.argv) > 1:
+        tests = [(name, func) for name, func in tests if name in sys.argv]
+
+    shells = ["/usr/bin/bash", "/usr/bin/zsh"]
+    total_count = len(tests) * len(shells)
+    index = 1
+    failed_tests = 0
+
+    for name, func in tests:
+        for shell in shells:
+            sys.stdout.write(f"\33[2K\r{index} of {total_count}: {name} in {shell}")
+            passed = func(shell)
+            if not passed:
+                failed_tests += 1
+            index += 1
+
+    if failed_tests > 0:
+        print(f"\n\nFAILED: {failed_tests} of {total_count}")
+        return 1
+    else:
+        print("\n\nSUCCESS")
+        return 0
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/tools/envsetup/spam_for_lunch b/tools/envsetup/spam_for_lunch
new file mode 100755
index 0000000..2e150a6
--- /dev/null
+++ b/tools/envsetup/spam_for_lunch
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# Copyright 2024, 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 ad is kind of big, so only show it if this appears to be a clean build.
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../shell_utils.sh
+if [[ ! -e $(getoutdir)/soong/build.${TARGET_PRODUCT}.ninja ]]; then
+  echo
+  echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+  echo "  Wondering whether to use user, userdebug or eng?"
+  echo
+  echo "  user        The builds that ship to users. Reduced debugability."
+  echo "  userdebug   High fidelity to user builds but with some debugging options"
+  echo "              enabled. Best suited for performance testing or day-to-day use"
+  echo "              with debugging enabled."
+  echo "  eng         More debugging options enabled and faster build times, but"
+  echo "              runtime performance tradeoffs. Best suited for day-to-day"
+  echo "              local development when not doing performance testing."
+  echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+  echo
+fi
+
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 2367691..d91a713 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1971,7 +1971,7 @@
   return None
 
 
-def _BuildVendorBootImage(sourcedir, partition_name, info_dict=None):
+def _BuildVendorBootImage(sourcedir, fs_config_file, partition_name, info_dict=None):
   """Build a vendor boot image from the specified sourcedir.
 
   Take a ramdisk, dtb, and vendor_cmdline from the input (in 'sourcedir'), and
@@ -1987,7 +1987,7 @@
   img = tempfile.NamedTemporaryFile()
 
   ramdisk_format = GetRamdiskFormat(info_dict)
-  ramdisk_img = _MakeRamdisk(sourcedir, ramdisk_format=ramdisk_format)
+  ramdisk_img = _MakeRamdisk(sourcedir, fs_config_file=fs_config_file, ramdisk_format=ramdisk_format)
 
   # use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
   mkbootimg = os.getenv('MKBOOTIMG') or "mkbootimg"
@@ -2101,8 +2101,9 @@
   if info_dict is None:
     info_dict = OPTIONS.info_dict
 
+  fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
   data = _BuildVendorBootImage(
-      os.path.join(unpack_dir, tree_subdir), "vendor_boot", info_dict)
+      os.path.join(unpack_dir, tree_subdir), os.path.join(unpack_dir, fs_config), "vendor_boot", info_dict)
   if data:
     return File(name, data)
   return None
@@ -2126,7 +2127,7 @@
     info_dict = OPTIONS.info_dict
 
   data = _BuildVendorBootImage(
-      os.path.join(unpack_dir, tree_subdir), "vendor_kernel_boot", info_dict)
+      os.path.join(unpack_dir, tree_subdir), None, "vendor_kernel_boot", info_dict)
   if data:
     return File(name, data)
   return None
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 5a024ce..985cd56 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -329,7 +329,7 @@
 OPTIONS.enable_vabc_xor = True
 OPTIONS.force_minor_version = None
 OPTIONS.compressor_types = None
-OPTIONS.enable_zucchini = True
+OPTIONS.enable_zucchini = False
 OPTIONS.enable_puffdiff = None
 OPTIONS.enable_lz4diff = False
 OPTIONS.vabc_compression_param = None