Merge "Update dependencies on graphics.common HAL to latest" into main
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index 4d3b546..623d256 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -87,11 +87,14 @@
       if optimization_rationale:
         get_metrics_agent().report_unoptimized_target(target, optimization_rationale)
       else:
-        regex = r'\b(%s)\b' % re.escape(target)
-        if any(re.search(regex, opt) for opt in test_discovery_zip_regexes):
-          get_metrics_agent().report_unoptimized_target(target, 'Test artifact used.')
-        else:
-          get_metrics_agent().report_optimized_target(target)
+        try:
+          regex = r'\b(%s)\b' % re.escape(target)
+          if any(re.search(regex, opt) for opt in test_discovery_zip_regexes):
+            get_metrics_agent().report_unoptimized_target(target, 'Test artifact used.')
+          else:
+            get_metrics_agent().report_optimized_target(target)
+        except Exception as e:
+          logging.error(f'unable to parse test discovery output: {repr(e)}')
 
       if self._unused_target_exclusion_enabled(
           target
diff --git a/core/Makefile b/core/Makefile
index 92dd86d..a7ab442 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -872,6 +872,7 @@
 SOONG_CONV_DATA := $(call intermediates-dir-for,PACKAGING,soong_conversion)/soong_conv_data
 $(SOONG_CONV_DATA):
 	@rm -f $@
+	@touch $@ # This file must be present even if SOONG_CONV is empty.
 	@$(foreach s,$(SOONG_CONV),echo "$(s),$(SOONG_CONV.$(s).TYPE),$(sort $(SOONG_CONV.$(s).PROBLEMS)),$(sort $(filter-out $(SOONG_ALREADY_CONV),$(SOONG_CONV.$(s).DEPS))),$(sort $(SOONG_CONV.$(s).MAKEFILES)),$(sort $(SOONG_CONV.$(s).INSTALLED))" >>$@;)
 
 $(call declare-1p-target,$(SOONG_CONV_DATA),build)
@@ -1596,6 +1597,7 @@
 	$(AVBTOOL) add_hash_footer \
            --image $@ \
 	   $(call get-partition-size-argument,$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE)) \
+	   --salt $$(sha256sum $(BUILD_NUMBER_FILE) $(BUILD_DATETIME_FILE) | cut -d " " -f 1 | tr -d '\n') \
 	   --partition_name init_boot $(INTERNAL_AVB_INIT_BOOT_SIGNING_ARGS) \
 	   $(BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS)
 
@@ -1771,6 +1773,7 @@
 	$(AVBTOOL) add_hash_footer \
            --image $@ \
 	   $(call get-partition-size-argument,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)) \
+	   --salt $$(sha256sum $(BUILD_NUMBER_FILE) $(BUILD_DATETIME_FILE) | cut -d " " -f 1 | tr -d '\n') \
 	   --partition_name vendor_boot $(INTERNAL_AVB_VENDOR_BOOT_SIGNING_ARGS) \
 	   $(BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS)
 else
@@ -2934,6 +2937,9 @@
 $(error MTD device is no longer supported and thus BOARD_NAND_SPARE_SIZE is deprecated.)
 endif
 
+recovery_intermediates := $(call intermediates-dir-for,PACKAGING,recovery)
+$(eval $(call write-partition-file-list,$(recovery_intermediates)/file_list.txt,$(TARGET_RECOVERY_OUT),$(INTERNAL_RECOVERYIMAGE_FILES)))
+
 
 # -----------------------------------------------------------------
 # Build debug ramdisk and debug boot image.
@@ -5171,6 +5177,8 @@
 # Run apex_sepolicy_tests for all installed APEXes
 
 ifeq (,$(TARGET_BUILD_UNBUNDLED))
+# TODO(b/353896817) apex_sepolicy_tests supports only ext4
+ifeq (ext4,$(PRODUCT_DEFAULT_APEX_PAYLOAD_TYPE))
 intermediate := $(call intermediates-dir-for,PACKAGING,apex_sepolicy_tests)
 apex_dirs := \
   $(TARGET_OUT)/apex/% \
@@ -5210,6 +5218,7 @@
 
 apex_files :=
 intermediate :=
+endif # PRODUCT_DEFAULT_APEX_PAYLOAD_TYPE
 endif # TARGET_BUILD_UNBUNDLED
 
 # -----------------------------------------------------------------
@@ -5678,6 +5687,7 @@
   brotli \
   bsdiff \
   build_image \
+  build_mixed_kernels_ramdisk_host \
   build_super_image \
   build_verity_metadata \
   build_verity_tree \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 769a6f7..092ddb0 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -48,6 +48,11 @@
 RECOVERY_FSTAB_VERSION := 2
 $(call soong_config_set, recovery, recovery_api_version, $(RECOVERY_API_VERSION))
 $(call soong_config_set, recovery, recovery_fstab_version, $(RECOVERY_FSTAB_VERSION))
+$(call soong_config_set_bool, recovery ,target_userimages_use_f2fs ,$(if $(TARGET_USERIMAGES_USE_F2FS),true,false))
+$(call soong_config_set_bool, recovery ,has_board_cacheimage_partition_size ,$(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),true,false))
+ifdef TARGET_RECOVERY_UI_LIB
+  $(call soong_config_set_string_list, recovery, target_recovery_ui_lib, $(TARGET_RECOVERY_UI_LIB))
+endif
 
 # For Sanitizers
 $(call soong_config_set_bool,ANDROID,ASAN_ENABLED,$(if $(filter address,$(SANITIZE_TARGET)),true,false))
@@ -262,3 +267,8 @@
 $(call soong_config_set_bool,fs_config,vendor_dlkm,$(if $(BOARD_USES_VENDOR_DLKMIMAGE)$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE),true,false))
 $(call soong_config_set_bool,fs_config,odm_dlkm,$(if $(BOARD_USES_ODM_DLKMIMAGE)$(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE),true,false))
 $(call soong_config_set_bool,fs_config,system_dlkm,$(if $(BOARD_USES_SYSTEM_DLKMIMAGE)$(BOARD_SYSTEM_DLKMIMAGE_FILE_SYSTEM_TYPE),true,false))
+
+# Variables for telephony
+$(call soong_config_set_bool,telephony,sec_cp_secure_boot,$(if $(filter true,$(SEC_CP_SECURE_BOOT)),true,false))
+$(call soong_config_set_bool,telephony,cbd_protocol_sit,$(if $(filter true,$(CBD_PROTOCOL_SIT)),true,false))
+$(call soong_config_set_bool,telephony,use_radioexternal_hal_aidl,$(if $(filter true,$(USE_RADIOEXTERNAL_HAL_AIDL)),true,false))
diff --git a/core/config.mk b/core/config.mk
index b546ea1..d62b86d 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -330,6 +330,18 @@
 $(eval SOONG_CONFIG_TYPE_$(strip $1)_$(strip $2):=bool)
 endef
 
+# soong_config_set_string_list is the same as soong_config_set, but it will
+# also type the variable as a list of strings, so that when using select() expressions
+# in blueprint files they can use list values instead of strings.
+# The values of the list must be space-separated.
+# $1 is the namespace. $2 is the variable name. $3 is the variable value.
+# Ex: $(call soong_config_set_string_list,acme,COOL_LIBS,a b)
+define soong_config_set_string_list
+$(call soong_config_define_internal,$1,$2) \
+$(eval SOONG_CONFIG_$(strip $1)_$(strip $2):=$(strip $3))
+$(eval SOONG_CONFIG_TYPE_$(strip $1)_$(strip $2):=string_list)
+endef
+
 # soong_config_append appends to the value of the variable in the given Soong
 # config namespace. If the variable does not exist, it will be defined. If the
 # namespace does not  exist, it will be defined.
diff --git a/core/definitions.mk b/core/definitions.mk
index 7a32464..adb35e0 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2615,7 +2615,77 @@
         @$(call emit-line,$(wordlist 113501,114000,$(1)),$(2))
         @$(call emit-line,$(wordlist 114001,114500,$(1)),$(2))
         @$(call emit-line,$(wordlist 114501,115000,$(1)),$(2))
-        @$(if $(wordlist 115001,115002,$(1)),$(error dump-words-to-file: Too many words ($(words $(1)))))
+        @$(call emit-line,$(wordlist 115001,115500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 115501,116000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 116001,116500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 116501,117000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 117001,117500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 117501,118000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 118001,118500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 118501,119000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 119001,119500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 119501,120000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 120001,120500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 120501,121000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 121001,121500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 121501,122000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 122001,122500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 122501,123000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 123001,123500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 123501,124000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 124001,124500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 124501,125000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 125001,125500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 125501,126000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 126001,126500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 126501,127000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 127001,127500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 127501,128000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 128001,128500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 128501,129000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 129001,129500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 129501,130000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 130001,130500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 130501,131000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 131001,131500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 131501,132000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 132001,132500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 132501,133000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 133001,133500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 133501,134000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 134001,134500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 134501,135000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 135001,135500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 135501,136000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 136001,136500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 136501,137000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 137001,137500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 137501,138000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 138001,138500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 138501,139000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 139001,139500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 139501,140000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 140001,140500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 140501,141000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 141001,141500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 141501,142000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 142001,142500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 142501,143000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 143001,143500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 143501,144000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 144001,144500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 144501,145000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 145001,145500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 145501,146000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 146001,146500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 146501,147000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 147001,147500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 147501,148000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 148001,148500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 148501,149000,$(1)),$(2))
+        @$(call emit-line,$(wordlist 149001,149500,$(1)),$(2))
+        @$(call emit-line,$(wordlist 149501,150000,$(1)),$(2))
+        @$(if $(wordlist 150001,150002,$(1)),$(error dump-words-to-file: Too many words ($(words $(1)))))
 endef
 # Return jar arguments to compress files in a given directory
 # $(1): directory
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index ccb502c..fd9dc9b 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -24,10 +24,11 @@
 # -----------------------------------------------------------------
 # Aconfig Flags
 
-# Create a summary file of build flags for each partition
+# Create a summary file of build flags for a single partition
 # $(1): built aconfig flags file (out)
 # $(2): installed aconfig flags file (out)
 # $(3): the partition (in)
+# $(4): input aconfig files for the partition (in)
 define generate-partition-aconfig-flag-file
 $(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
 $(eval $(strip $(1)): PRIVATE_IN := $(strip $(4)))
@@ -35,7 +36,8 @@
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
 		$$(ACONFIG) dump --dedup --format protobuf --out $$(PRIVATE_OUT) \
-			--filter container:$(strip $(3)) \
+			--filter container:$(strip $(3))+state:ENABLED \
+			--filter container:$(strip $(3))+permission:READ_WRITE \
 			$$(addprefix --cache ,$$(PRIVATE_IN)), \
 		echo -n > $$(PRIVATE_OUT) \
 	)
diff --git a/core/product_config.mk b/core/product_config.mk
index 692e375..f93b63c 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -468,17 +468,26 @@
     $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
 _psmc_modules :=
 
-# Reset ADB keys for non-debuggable builds
-ifeq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)))
+# Reset ADB keys. If RELEASE_BUILD_USE_VARIANT_FLAGS is set look for
+# the value of a dedicated flag. Otherwise check if build variant is
+# non-debuggable.
+ifneq (,$(RELEASE_BUILD_USE_VARIANT_FLAGS))
+ifneq (,$(RELEASE_BUILD_PURGE_PRODUCT_ADB_KEYS))
   PRODUCT_ADB_KEYS :=
 endif
+else ifeq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)))
+  PRODUCT_ADB_KEYS :=
+endif
+
 ifneq ($(filter-out 0 1,$(words $(PRODUCT_ADB_KEYS))),)
   $(error Only one file may be in PRODUCT_ADB_KEYS: $(PRODUCT_ADB_KEYS))
 endif
 
 # Show a warning wall of text if non-compliance-GSI products set this option.
 ifdef PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT
-  ifeq (,$(filter gsi_arm gsi_arm64 gsi_x86 gsi_x86_64 gsi_car_arm64 gsi_car_x86_64 gsi_tv_arm gsi_tv_arm64,$(PRODUCT_NAME)))
+  ifeq (,$(filter gsi_arm gsi_arm64 gsi_arm64_soong_system gsi_x86 gsi_x86_64 \
+                  gsi_x86_64_soong_system gsi_car_arm64 gsi_car_x86_64 \
+                  gsi_tv_arm gsi_tv_arm64,$(PRODUCT_NAME)))
     $(warning PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT is set but \
       PRODUCT_NAME ($(PRODUCT_NAME)) doesn't look like a GSI for compliance \
       testing. This is a special configuration for compliance GSI, so do make \
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index df1cf2d..ab9227f 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -224,30 +224,6 @@
 include $(BUILD_SYSTEM)/link_type.mk
 endif # !LOCAL_IS_HOST_MODULE
 
-ifeq (,$(filter tests,$(LOCAL_MODULE_TAGS)))
-  ifdef LOCAL_SOONG_DEVICE_RRO_DIRS
-    $(call append_enforce_rro_sources, \
-        $(my_register_name), \
-        false, \
-        $(LOCAL_FULL_MANIFEST_FILE), \
-        $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
-        $(LOCAL_SOONG_DEVICE_RRO_DIRS), \
-        vendor \
-    )
-  endif
-
-  ifdef LOCAL_SOONG_PRODUCT_RRO_DIRS
-    $(call append_enforce_rro_sources, \
-        $(my_register_name), \
-        false, \
-        $(LOCAL_FULL_MANIFEST_FILE), \
-        $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
-        $(LOCAL_SOONG_PRODUCT_RRO_DIRS), \
-        product \
-    )
-  endif
-endif
-
 ifdef LOCAL_PREBUILT_COVERAGE_ARCHIVE
   my_coverage_dir := $(TARGET_OUT_COVERAGE)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
   my_coverage_copy_pairs := $(foreach f,$(LOCAL_PREBUILT_COVERAGE_ARCHIVE),$(f):$(my_coverage_dir)/$(notdir  $(f)))
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 4683476..a007888 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -194,6 +194,8 @@
 $(call add_json_str,  SystemDlkmPath,                    $(TARGET_COPY_OUT_SYSTEM_DLKM))
 $(call add_json_str,  OemPath,                           $(TARGET_COPY_OUT_OEM))
 $(call add_json_bool, MinimizeJavaDebugInfo,             $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
+$(call add_json_str,  RecoveryPath,                      $(TARGET_COPY_OUT_RECOVERY))
+$(call add_json_bool, BuildingRecoveryImage,             $(BUILDING_RECOVERY_IMAGE))
 
 $(call add_json_bool, UseGoma,                           $(filter-out false,$(USE_GOMA)))
 $(call add_json_bool, UseRBE,                            $(filter-out false,$(USE_RBE)))
@@ -402,6 +404,7 @@
     $(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 add_json_str, BoardAvbAddHashtreeFooterArgs, $(BOARD_AVB_$(image_type)_ADD_HASHTREE_FOOTER_ARGS)) \
     $(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)) \
@@ -446,6 +449,27 @@
   $(call add_json_str, VendorSecurityPatch, $(VENDOR_SECURITY_PATCH))
   $(call add_json_bool, BoardIncludeDtbInBootimg, $(BOARD_INCLUDE_DTB_IN_BOOTIMG))
   $(call add_json_list, InternalKernelCmdline, $(INTERNAL_KERNEL_CMDLINE))
+  $(call add_json_list, InternalBootconfig, $(INTERNAL_BOOTCONFIG))
+  $(call add_json_str, InternalBootconfigFile, $(INTERNAL_BOOTCONFIG_FILE))
+
+  # super image stuff
+  $(call add_json_bool, ProductUseDynamicPartitions, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITIONS)))
+  $(call add_json_bool, ProductRetrofitDynamicPartitions, $(filter true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)))
+  $(call add_json_bool, ProductBuildSuperPartition, $(filter true,$(PRODUCT_BUILD_SUPER_PARTITION)))
+  $(call add_json_str, BoardSuperPartitionSize, $(BOARD_SUPER_PARTITION_SIZE))
+  $(call add_json_str, BoardSuperPartitionMetadataDevice, $(BOARD_SUPER_PARTITION_METADATA_DEVICE))
+  $(call add_json_list, BoardSuperPartitionBlockDevices, $(BOARD_SUPER_PARTITION_BLOCK_DEVICES))
+  $(call add_json_map, BoardSuperPartitionGroups)
+    $(foreach group, $(BOARD_SUPER_PARTITION_GROUPS), \
+      $(call add_json_map, $(group)) \
+        $(call add_json_str, GroupSize, $(BOARD_$(call to-upper,$(group))_SIZE)) \
+        $(if $(BOARD_$(call to-upper,$(group))_PARTITION_LIST), \
+          $(call add_json_list, PartitionList, $(BOARD_$(call to-upper,$(group))_PARTITION_LIST))) \
+      $(call end_json_map))
+    $(call end_json_map)
+  $(call add_json_bool, ProductVirtualAbOta, $(filter true,$(PRODUCT_VIRTUAL_AB_OTA)))
+  $(call add_json_bool, ProductVirtualAbOtaRetrofit, $(filter true,$(PRODUCT_VIRTUAL_AB_OTA_RETROFIT)))
+  $(call add_json_bool, AbOtaUpdater, $(filter true,$(AB_OTA_UPDATER)))
 
   # Avb (android verified boot) stuff
   $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
@@ -484,6 +508,10 @@
   $(call add_json_bool, BuildingOdmDlkmImage,               $(BUILDING_ODM_DLKM_IMAGE))
   $(call add_json_list, OdmKernelModules, $(BOARD_ODM_KERNEL_MODULES))
   $(call add_json_str, OdmKernelBlocklistFile, $(BOARD_ODM_KERNEL_MODULES_BLOCKLIST_FILE))
+  $(call add_json_list, VendorRamdiskKernelModules, $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES))
+  $(call add_json_str, VendorRamdiskKernelBlocklistFile, $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_BLOCKLIST_FILE))
+  $(call add_json_list, VendorRamdiskKernelLoadModules, $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD))
+  $(call add_json_str, VendorRamdiskKernelOptionsFile, $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_OPTIONS_FILE))
 
   # Used to generate /vendor/build.prop
   $(call add_json_list, BoardInfoFiles, $(if $(TARGET_BOARD_INFO_FILES),$(TARGET_BOARD_INFO_FILES),$(firstword $(TARGET_BOARD_INFO_FILE) $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt))))
@@ -491,6 +519,12 @@
 
   $(call add_json_list, ProductCopyFiles, $(PRODUCT_COPY_FILES))
 
+  # Used to generate fsv meta
+  $(call add_json_bool, ProductFsverityGenerateMetadata,               $(PRODUCT_FSVERITY_GENERATE_METADATA))
+
+  # Used to generate recovery partition
+  $(call add_json_str, TargetScreenDensity, $(TARGET_SCREEN_DENSITY))
+
 $(call end_json_map)
 
 # For converting vintf_data
diff --git a/core/sysprop.mk b/core/sysprop.mk
index 255b699..e5f1267 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -183,7 +183,7 @@
 endif
 
 BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
-ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE)))
+ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE).tmp && (if ! cmp -s $(BUILD_FINGERPRINT_FILE).tmp $(BUILD_FINGERPRINT_FILE); then mv $(BUILD_FINGERPRINT_FILE).tmp $(BUILD_FINGERPRINT_FILE); else rm $(BUILD_FINGERPRINT_FILE).tmp; fi) && grep " " $(BUILD_FINGERPRINT_FILE)))
   $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))")
 endif
 BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE))
diff --git a/core/version_util.mk b/core/version_util.mk
index 0e34634..2bf41ec 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -23,6 +23,7 @@
 #     PLATFORM_DISPLAY_VERSION
 #     PLATFORM_SDK_VERSION
 #     PLATFORM_SDK_EXTENSION_VERSION
+#     PLATFORM_BASE_SDK_EXTENSION_VERSION
 #     PLATFORM_VERSION_CODENAME
 #     DEFAULT_APP_TARGET_SDK
 #     BUILD_ID
@@ -67,8 +68,16 @@
 PLATFORM_SDK_EXTENSION_VERSION := $(RELEASE_PLATFORM_SDK_EXTENSION_VERSION)
 .KATI_READONLY := PLATFORM_SDK_EXTENSION_VERSION
 
-# This is the sdk extension version that PLATFORM_SDK_VERSION ships with.
-PLATFORM_BASE_SDK_EXTENSION_VERSION := $(PLATFORM_SDK_EXTENSION_VERSION)
+ifdef PLATFORM_BASE_SDK_EXTENSION_VERSION
+  $(error Do not set PLATFORM_BASE_SDK_EXTENSION_VERSION directly. Use RELEASE_PLATFORM_BASE_SDK_EXTENSION_VERSION. value: $(PLATFORM_BASE_SDK_EXTENSION_VERSION))
+endif
+ifdef RELEASE_PLATFORM_BASE_SDK_EXTENSION_VERSION
+  # This is the sdk extension version that PLATFORM_SDK_VERSION ships with.
+  PLATFORM_BASE_SDK_EXTENSION_VERSION := $(RELEASE_PLATFORM_BASE_SDK_EXTENSION_VERSION)
+else
+  # Fallback to PLATFORM_SDK_EXTENSION_VERSION if RELEASE_PLATFORM_BASE_SDK_EXTENSION_VERSION is undefined.
+  PLATFORM_BASE_SDK_EXTENSION_VERSION := $(PLATFORM_SDK_EXTENSION_VERSION)
+endif
 .KATI_READONLY := PLATFORM_BASE_SDK_EXTENSION_VERSION
 
 ifdef PLATFORM_VERSION_CODENAME
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 15e6c04..b9b226b 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -17,7 +17,6 @@
 # Base modules and settings for the system partition.
 PRODUCT_PACKAGES += \
     abx \
-    aconfigd \
     aconfigd-system \
     adbd_system_api \
     aflags \
diff --git a/target/product/build_variables.mk b/target/product/build_variables.mk
index 7661e06..e99ab06 100644
--- a/target/product/build_variables.mk
+++ b/target/product/build_variables.mk
@@ -20,6 +20,12 @@
 # Control libbinder client caching
 $(call soong_config_set, libbinder, release_libbinder_client_cache, $(RELEASE_LIBBINDER_CLIENT_CACHE))
 
+# Control caching while adding service in libbinder cache
+$(call soong_config_set, libbinder, release_libbinder_addservice_cache, $(RELEASE_LIBBINDER_ADDSERVICE_CACHE))
+
+# Remove static list in libbinder cache
+$(call soong_config_set, libbinder, release_libbinder_remove_cache_static_list, $(RELEASE_LIBBINDER_REMOVE_CACHE_STATIC_LIST))
+
 # Use the configured release of sqlite
 $(call soong_config_set, libsqlite3, release_package_libsqlite3, $(RELEASE_PACKAGE_LIBSQLITE3))
 
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index 59172f0..4a3d21b 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -381,7 +381,6 @@
 
     deps: [
         "abx",
-        "aconfigd",
         "aconfigd-system",
         "aflags",
         "am",
@@ -873,6 +872,14 @@
             }),
         },
     },
+    arch: {
+        arm64: {
+            deps: [
+                "libclang_rt.hwasan",
+                "libc_hwasan",
+            ],
+        },
+    },
 }
 
 android_system_image {
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 39428d2..f00c38c 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -82,6 +82,7 @@
 # Additional settings used in all GSI builds
 PRODUCT_PRODUCT_PROPERTIES += \
     ro.crypto.metadata_init_delete_all_keys.enabled=false \
+    debug.codec2.bqpool_dealloc_after_stop=1 \
 
 # Window Extensions
 ifneq ($(PRODUCT_IS_ATV),true)
diff --git a/teams/Android.bp b/teams/Android.bp
index 6307f5c..a2b0d14 100644
--- a/teams/Android.bp
+++ b/teams/Android.bp
@@ -3367,6 +3367,13 @@
 }
 
 team {
+    name: "trendy_team_aaos_display_safety_triage",
+
+    // go/trendy/manage/engineers/6522093663780864
+    trendy_team_id: "6522093663780864",
+}
+
+team {
     name: "trendy_team_camera_htc_lg_qualcomm",
 
     // go/trendy/manage/engineers/6332099480911872
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index 043a956..a7f0a4f 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -102,9 +102,7 @@
     {
       // aconfig_storage file java integration tests
       "name": "aconfig_storage_file.test.java"
-    }
-  ],
-  "postsubmit": [
+    },
     {
       // aconfig_storage read functional test
       "name": "aconfig_storage_read_functional"
diff --git a/tools/aconfig/aconfig/src/codegen/cpp.rs b/tools/aconfig/aconfig/src/codegen/cpp.rs
index 7a9c382..ae18679 100644
--- a/tools/aconfig/aconfig/src/codegen/cpp.rs
+++ b/tools/aconfig/aconfig/src/codegen/cpp.rs
@@ -127,6 +127,26 @@
     flag_ids: HashMap<String, u16>,
     rw_count: &mut i32,
 ) -> ClassElement {
+    let no_assigned_offset =
+        (pf.container() == "system" || pf.container() == "vendor" || pf.container() == "product")
+            && pf.permission() == ProtoFlagPermission::READ_ONLY
+            && pf.state() == ProtoFlagState::DISABLED;
+
+    let flag_offset = match flag_ids.get(pf.name()) {
+        Some(offset) => offset,
+        None => {
+            // System/vendor/product RO+disabled flags have no offset in storage files.
+            // Assign placeholder value.
+            if no_assigned_offset {
+                &0
+            }
+            // All other flags _must_ have an offset.
+            else {
+                panic!("{}", format!("missing flag offset for {}", pf.name()));
+            }
+        }
+    };
+
     ClassElement {
         readwrite_idx: if pf.permission() == ProtoFlagPermission::READ_WRITE {
             let index = *rw_count;
@@ -144,7 +164,7 @@
         },
         flag_name: pf.name().to_string(),
         flag_macro: pf.name().to_uppercase(),
-        flag_offset: *flag_ids.get(pf.name()).expect("values checked at flag parse time"),
+        flag_offset: *flag_offset,
         device_config_namespace: pf.namespace().to_string(),
         device_config_flag: codegen::create_device_config_ident(package, pf.name())
             .expect("values checked at flag parse time"),
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 2cb98ed..7aff4e9 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -32,6 +32,7 @@
     codegen_mode: CodegenMode,
     flag_ids: HashMap<String, u16>,
     allow_instrumentation: bool,
+    package_fingerprint: u64,
 ) -> Result<Vec<OutputFile>>
 where
     I: Iterator<Item = ProtoParsedFlag>,
@@ -46,6 +47,7 @@
     let runtime_lookup_required =
         flag_elements.iter().any(|elem| elem.is_read_write) || library_exported;
     let container = (flag_elements.first().expect("zero template flags").container).to_string();
+    let is_platform_container = matches!(container.as_str(), "system" | "product" | "vendor");
     let context = Context {
         flag_elements,
         namespace_flags,
@@ -56,6 +58,8 @@
         library_exported,
         allow_instrumentation,
         container,
+        is_platform_container,
+        package_fingerprint: format!("0x{:X}L", package_fingerprint),
     };
     let mut template = TinyTemplate::new();
     template.add_template("Flags.java", include_str!("../../templates/Flags.java.template"))?;
@@ -123,6 +127,8 @@
     pub library_exported: bool,
     pub allow_instrumentation: bool,
     pub container: String,
+    pub is_platform_container: bool,
+    pub package_fingerprint: String,
 }
 
 #[derive(Serialize, Debug)]
@@ -152,6 +158,27 @@
 ) -> FlagElement {
     let device_config_flag = codegen::create_device_config_ident(package, pf.name())
         .expect("values checked at flag parse time");
+
+    let no_assigned_offset =
+        (pf.container() == "system" || pf.container() == "vendor" || pf.container() == "product")
+            && pf.permission() == ProtoFlagPermission::READ_ONLY
+            && pf.state() == ProtoFlagState::DISABLED;
+
+    let flag_offset = match flag_offsets.get(pf.name()) {
+        Some(offset) => offset,
+        None => {
+            // System/vendor/product RO+disabled flags have no offset in storage files.
+            // Assign placeholder value.
+            if no_assigned_offset {
+                &0
+            }
+            // All other flags _must_ have an offset.
+            else {
+                panic!("{}", format!("missing flag offset for {}", pf.name()));
+            }
+        }
+    };
+
     FlagElement {
         container: pf.container().to_string(),
         default_value: pf.state() == ProtoFlagState::ENABLED,
@@ -159,7 +186,7 @@
         device_config_flag,
         flag_name: pf.name().to_string(),
         flag_name_constant_suffix: pf.name().to_ascii_uppercase(),
-        flag_offset: *flag_offsets.get(pf.name()).expect("didnt find package offset :("),
+        flag_offset: *flag_offset,
         is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
         method_name: format_java_method_name(pf.name()),
         properties: format_property_name(pf.namespace()),
@@ -502,6 +529,7 @@
             mode,
             flag_ids,
             true,
+            5801144784618221668,
         )
         .unwrap();
         let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
@@ -513,10 +541,12 @@
         package com.android.aconfig.test;
         // TODO(b/303773055): Remove the annotation after access issue is resolved.
         import android.compat.annotation.UnsupportedAppUsage;
-        import android.aconfig.storage.StorageInternalReader;
-
+        import android.os.Build;
+        import android.os.flagging.PlatformAconfigPackageInternal;
+        import android.util.Log;
         /** @hide */
         public final class FeatureFlagsImpl implements FeatureFlags {
+            private static final String TAG = "com.android.aconfig.test.FeatureFlagsImpl";
             private static volatile boolean isCached = false;
             private static boolean disabledRw = false;
             private static boolean disabledRwExported = false;
@@ -524,16 +554,17 @@
             private static boolean enabledRw = true;
             private void init() {
                 try {
-                    StorageInternalReader reader = new StorageInternalReader("system", "com.android.aconfig.test");
-                    disabledRw = reader.getBooleanFlagValue(1);
-                    disabledRwExported = reader.getBooleanFlagValue(2);
-                    enabledRw = reader.getBooleanFlagValue(8);
-                    disabledRwInOtherNamespace = reader.getBooleanFlagValue(3);
+                    PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("system", "com.android.aconfig.test", 0x5081CE7221C77064L);
+                    disabledRw = reader.getBooleanFlagValue(0);
+                    disabledRwExported = reader.getBooleanFlagValue(1);
+                    enabledRw = reader.getBooleanFlagValue(7);
+                    disabledRwInOtherNamespace = reader.getBooleanFlagValue(2);
                 } catch (Exception e) {
-                    // pass
+                    Log.e(TAG, e.toString());
                 } catch (NoClassDefFoundError e) {
                     // for mainline module running on older devices.
                     // This should be replaces to version check, after the version bump.
+                    Log.e(TAG, e.toString());
                 }
                 isCached = true;
             }
@@ -653,6 +684,7 @@
             mode,
             flag_ids,
             true,
+            5801144784618221668,
         )
         .unwrap();
 
@@ -851,6 +883,7 @@
             mode,
             flag_ids,
             true,
+            5801144784618221668,
         )
         .unwrap();
 
@@ -972,6 +1005,7 @@
             mode,
             flag_ids,
             true,
+            5801144784618221668,
         )
         .unwrap();
         let expect_featureflags_content = r#"
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index 82a6ebc..2bf565a 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -88,6 +88,27 @@
 impl TemplateParsedFlag {
     #[allow(clippy::nonminimal_bool)]
     fn new(package: &str, flag_offsets: HashMap<String, u16>, pf: &ProtoParsedFlag) -> Self {
+        let no_assigned_offset = (pf.container() == "system"
+            || pf.container() == "vendor"
+            || pf.container() == "product")
+            && pf.permission() == ProtoFlagPermission::READ_ONLY
+            && pf.state() == ProtoFlagState::DISABLED;
+
+        let flag_offset = match flag_offsets.get(pf.name()) {
+            Some(offset) => offset,
+            None => {
+                // System/vendor/product RO+disabled flags have no offset in storage files.
+                // Assign placeholder value.
+                if no_assigned_offset {
+                    &0
+                }
+                // All other flags _must_ have an offset.
+                else {
+                    panic!("{}", format!("missing flag offset for {}", pf.name()));
+                }
+            }
+        };
+
         Self {
             readwrite: pf.permission() == ProtoFlagPermission::READ_WRITE,
             default_value: match pf.state() {
@@ -96,7 +117,7 @@
             },
             name: pf.name().to_string(),
             container: pf.container().to_string(),
-            flag_offset: *flag_offsets.get(pf.name()).expect("didnt find package offset :("),
+            flag_offset: *flag_offset,
             device_config_namespace: pf.namespace().to_string(),
             device_config_flag: codegen::create_device_config_ident(package, pf.name())
                 .expect("values checked at flag parse time"),
@@ -287,7 +308,7 @@
                .and_then(|package_offset| {
                    match package_offset {
                        Some(offset) => {
-                           get_boolean_flag_value(&flag_val_map, offset + 1)
+                           get_boolean_flag_value(&flag_val_map, offset + 0)
                                .map_err(|err| format!("failed to get flag: {err}"))
                        },
                        None => {
@@ -327,7 +348,7 @@
                     .and_then(|package_offset| {
                         match package_offset {
                             Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 2)
+                                get_boolean_flag_value(&flag_val_map, offset + 1)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -367,7 +388,7 @@
                     .and_then(|package_offset| {
                         match package_offset {
                             Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 3)
+                                get_boolean_flag_value(&flag_val_map, offset + 2)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
@@ -408,7 +429,7 @@
                     .and_then(|package_offset| {
                         match package_offset {
                             Some(offset) => {
-                                get_boolean_flag_value(&flag_val_map, offset + 8)
+                                get_boolean_flag_value(&flag_val_map, offset + 7)
                                     .map_err(|err| format!("failed to get flag: {err}"))
                             },
                             None => {
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 81119f3..3f869de 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -225,6 +225,9 @@
         bail!("no parsed flags, or the parsed flags use different packages");
     };
     let package = package.to_string();
+    let mut flag_names =
+        modified_parsed_flags.iter().map(|pf| pf.name().to_string()).collect::<Vec<_>>();
+    let package_fingerprint = compute_flags_fingerprint(&mut flag_names);
     let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
     generate_java_code(
         &package,
@@ -232,6 +235,7 @@
         codegen_mode,
         flag_ids,
         allow_instrumentation,
+        package_fingerprint,
     )
 }
 
@@ -419,17 +423,28 @@
 {
     assert!(parsed_flags_iter.clone().tuple_windows().all(|(a, b)| a.name() <= b.name()));
     let mut flag_ids = HashMap::new();
-    for (id_to_assign, pf) in (0_u32..).zip(parsed_flags_iter) {
+    let mut flag_idx = 0;
+    for pf in parsed_flags_iter {
         if package != pf.package() {
             return Err(anyhow::anyhow!("encountered a flag not in current package"));
         }
 
         // put a cap on how many flags a package can contain to 65535
-        if id_to_assign > u16::MAX as u32 {
+        if flag_idx > u16::MAX as u32 {
             return Err(anyhow::anyhow!("the number of flags in a package cannot exceed 65535"));
         }
 
-        flag_ids.insert(pf.name().to_string(), id_to_assign as u16);
+        // Exclude system/vendor/product flags that are RO+disabled.
+        let should_filter_container = pf.container == Some("vendor".to_string())
+            || pf.container == Some("system".to_string())
+            || pf.container == Some("vendor".to_string());
+        if !(should_filter_container
+            && pf.state == Some(ProtoFlagState::DISABLED.into())
+            && pf.permission == Some(ProtoFlagPermission::READ_ONLY.into()))
+        {
+            flag_ids.insert(pf.name().to_string(), flag_idx as u16);
+            flag_idx += 1;
+        }
     }
     Ok(flag_ids)
 }
@@ -887,6 +902,30 @@
     }
 
     #[test]
+    fn test_dump_multiple_filters() {
+        let input = parse_test_flags_as_input();
+        let bytes = dump_parsed_flags(
+            vec![input],
+            DumpFormat::Custom("{fully_qualified_name}".to_string()),
+            &["container:system+state:ENABLED", "container:system+permission:READ_WRITE"],
+            false,
+        )
+        .unwrap();
+        let text = std::str::from_utf8(&bytes).unwrap();
+        let expected_flag_list = &[
+            "com.android.aconfig.test.disabled_rw",
+            "com.android.aconfig.test.disabled_rw_exported",
+            "com.android.aconfig.test.disabled_rw_in_other_namespace",
+            "com.android.aconfig.test.enabled_fixed_ro",
+            "com.android.aconfig.test.enabled_fixed_ro_exported",
+            "com.android.aconfig.test.enabled_ro",
+            "com.android.aconfig.test.enabled_ro_exported",
+            "com.android.aconfig.test.enabled_rw",
+        ];
+        assert_eq!(expected_flag_list.map(|s| format!("{}\n", s)).join(""), text);
+    }
+
+    #[test]
     fn test_dump_textproto_format_dedup() {
         let input = parse_test_flags_as_input();
         let input2 = parse_test_flags_as_input();
@@ -948,15 +987,14 @@
         let package = find_unique_package(&parsed_flags.parsed_flag).unwrap().to_string();
         let flag_ids = assign_flag_ids(&package, parsed_flags.parsed_flag.iter()).unwrap();
         let expected_flag_ids = HashMap::from([
-            (String::from("disabled_ro"), 0_u16),
-            (String::from("disabled_rw"), 1_u16),
-            (String::from("disabled_rw_exported"), 2_u16),
-            (String::from("disabled_rw_in_other_namespace"), 3_u16),
-            (String::from("enabled_fixed_ro"), 4_u16),
-            (String::from("enabled_fixed_ro_exported"), 5_u16),
-            (String::from("enabled_ro"), 6_u16),
-            (String::from("enabled_ro_exported"), 7_u16),
-            (String::from("enabled_rw"), 8_u16),
+            (String::from("disabled_rw"), 0_u16),
+            (String::from("disabled_rw_exported"), 1_u16),
+            (String::from("disabled_rw_in_other_namespace"), 2_u16),
+            (String::from("enabled_fixed_ro"), 3_u16),
+            (String::from("enabled_fixed_ro_exported"), 4_u16),
+            (String::from("enabled_ro"), 5_u16),
+            (String::from("enabled_ro_exported"), 6_u16),
+            (String::from("enabled_rw"), 7_u16),
         ]);
         assert_eq!(flag_ids, expected_flag_ids);
     }
diff --git a/tools/aconfig/aconfig/src/storage/flag_info.rs b/tools/aconfig/aconfig/src/storage/flag_info.rs
index 0b5a67b..0943daa 100644
--- a/tools/aconfig/aconfig/src/storage/flag_info.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_info.rs
@@ -16,7 +16,7 @@
 
 use crate::commands::assign_flag_ids;
 use crate::storage::FlagPackage;
-use aconfig_protos::ProtoFlagPermission;
+use aconfig_protos::{ProtoFlagPermission, ProtoFlagState};
 use aconfig_storage_file::{FlagInfoHeader, FlagInfoList, FlagInfoNode, StorageFileType};
 use anyhow::{anyhow, Result};
 
@@ -36,14 +36,24 @@
     packages: &[FlagPackage],
     version: u32,
 ) -> Result<FlagInfoList> {
-    // create list
-    let num_flags = packages.iter().map(|pkg| pkg.boolean_flags.len() as u32).sum();
+    // Exclude system/vendor/product flags that are RO+disabled.
+    let mut filtered_packages = packages.to_vec();
+    if container == "system" || container == "vendor" || container == "product" {
+        for package in filtered_packages.iter_mut() {
+            package.boolean_flags.retain(|b| {
+                !(b.state == Some(ProtoFlagState::DISABLED.into())
+                    && b.permission == Some(ProtoFlagPermission::READ_ONLY.into()))
+            });
+        }
+    }
+
+    let num_flags = filtered_packages.iter().map(|pkg| pkg.boolean_flags.len() as u32).sum();
 
     let mut is_flag_rw = vec![false; num_flags as usize];
-    for pkg in packages.iter() {
+    for pkg in filtered_packages {
         let start_index = pkg.boolean_start_index as usize;
         let flag_ids = assign_flag_ids(pkg.package_name, pkg.boolean_flags.iter().copied())?;
-        for pf in pkg.boolean_flags.iter() {
+        for pf in pkg.boolean_flags {
             let fid = flag_ids
                 .get(pf.name())
                 .ok_or(anyhow!(format!("missing flag id for {}", pf.name())))?;
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index ae5a16c..3b245a7 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -16,7 +16,7 @@
 
 use crate::commands::assign_flag_ids;
 use crate::storage::FlagPackage;
-use aconfig_protos::ProtoFlagPermission;
+use aconfig_protos::{ProtoFlagPermission, ProtoFlagState};
 use aconfig_storage_file::{
     get_table_size, FlagTable, FlagTableHeader, FlagTableNode, StorageFileType, StoredFlagType,
 };
@@ -62,9 +62,19 @@
     }
 
     fn create_nodes(package: &FlagPackage, num_buckets: u32) -> Result<Vec<Self>> {
+        // Exclude system/vendor/product flags that are RO+disabled.
+        let mut filtered_package = package.clone();
+        filtered_package.boolean_flags.retain(|f| {
+            !((f.container == Some("system".to_string())
+                || f.container == Some("vendor".to_string())
+                || f.container == Some("product".to_string()))
+                && f.permission == Some(ProtoFlagPermission::READ_ONLY.into())
+                && f.state == Some(ProtoFlagState::DISABLED.into()))
+        });
+
         let flag_ids =
-            assign_flag_ids(package.package_name, package.boolean_flags.iter().copied())?;
-        package
+            assign_flag_ids(package.package_name, filtered_package.boolean_flags.iter().copied())?;
+        filtered_package
             .boolean_flags
             .iter()
             .map(|&pf| {
diff --git a/tools/aconfig/aconfig/src/storage/flag_value.rs b/tools/aconfig/aconfig/src/storage/flag_value.rs
index 065b7e3..3cfa447 100644
--- a/tools/aconfig/aconfig/src/storage/flag_value.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_value.rs
@@ -16,7 +16,7 @@
 
 use crate::commands::assign_flag_ids;
 use crate::storage::FlagPackage;
-use aconfig_protos::ProtoFlagState;
+use aconfig_protos::{ProtoFlagPermission, ProtoFlagState};
 use aconfig_storage_file::{FlagValueHeader, FlagValueList, StorageFileType};
 use anyhow::{anyhow, Result};
 
@@ -36,15 +36,22 @@
     packages: &[FlagPackage],
     version: u32,
 ) -> Result<FlagValueList> {
-    // create list
-    let num_flags = packages.iter().map(|pkg| pkg.boolean_flags.len() as u32).sum();
-
+    // Exclude system/vendor/product flags that are RO+disabled.
+    let mut filtered_packages = packages.to_vec();
+    if container == "system" || container == "vendor" || container == "product" {
+        for package in filtered_packages.iter_mut() {
+            package.boolean_flags.retain(|b| {
+                !(b.state == Some(ProtoFlagState::DISABLED.into())
+                    && b.permission == Some(ProtoFlagPermission::READ_ONLY.into()))
+            });
+        }
+    }
+    let num_flags = filtered_packages.iter().map(|pkg| pkg.boolean_flags.len() as u32).sum();
     let mut list = FlagValueList {
         header: new_header(container, num_flags, version),
         booleans: vec![false; num_flags as usize],
     };
-
-    for pkg in packages.iter() {
+    for pkg in filtered_packages {
         let start_index = pkg.boolean_start_index as usize;
         let flag_ids = assign_flag_ids(pkg.package_name, pkg.boolean_flags.iter().copied())?;
         for pf in pkg.boolean_flags.iter() {
diff --git a/tools/aconfig/aconfig/src/storage/mod.rs b/tools/aconfig/aconfig/src/storage/mod.rs
index 4bc72f7..61e65d1 100644
--- a/tools/aconfig/aconfig/src/storage/mod.rs
+++ b/tools/aconfig/aconfig/src/storage/mod.rs
@@ -27,9 +27,10 @@
     flag_info::create_flag_info, flag_table::create_flag_table, flag_value::create_flag_value,
     package_table::create_package_table,
 };
-use aconfig_protos::{ProtoParsedFlag, ProtoParsedFlags};
+use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag, ProtoParsedFlags};
 use aconfig_storage_file::StorageFileType;
 
+#[derive(Clone)]
 pub struct FlagPackage<'a> {
     pub package_name: &'a str,
     pub package_id: u32,
@@ -73,6 +74,17 @@
             if index == packages.len() {
                 packages.push(FlagPackage::new(parsed_flag.package(), index as u32));
             }
+
+            // Exclude system/vendor/product flags that are RO+disabled.
+            if (parsed_flag.container == Some("system".to_string())
+                || parsed_flag.container == Some("vendor".to_string())
+                || parsed_flag.container == Some("product".to_string()))
+                && parsed_flag.permission == Some(ProtoFlagPermission::READ_ONLY.into())
+                && parsed_flag.state == Some(ProtoFlagState::DISABLED.into())
+            {
+                continue;
+            }
+
             packages[index].insert(parsed_flag);
         }
     }
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 98add32..b605e72 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -5,11 +5,18 @@
 // TODO(b/303773055): Remove the annotation after access issue is resolved.
 import android.compat.annotation.UnsupportedAppUsage;
 {{ -if runtime_lookup_required }}
-import android.aconfig.storage.StorageInternalReader;
+import android.os.Build;
+{{ if is_platform_container }}
+import android.os.flagging.PlatformAconfigPackageInternal;
+{{ -else }}
+import android.os.flagging.AconfigPackageInternal;
+{{ -endif }}
+import android.util.Log;
 {{ -endif }}
 /** @hide */
 public final class FeatureFlagsImpl implements FeatureFlags \{
 {{ -if runtime_lookup_required }}
+    private static final String TAG = "{package_name}.FeatureFlagsImpl";
     private static volatile boolean isCached = false;
 {{ for flag in flag_elements }}
 {{ -if flag.is_read_write }}
@@ -19,19 +26,24 @@
 
     private void init() \{
         try \{
-            StorageInternalReader reader = new StorageInternalReader("{container}", "{package_name}");
-            {{ for namespace_with_flags in namespace_flags }}
-            {{ -for flag in namespace_with_flags.flags }}
-            {{ if flag.is_read_write }}
-                {flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
-            {{ endif }}
-            {{ -endfor }}
-            {{ -endfor }}
+{{ if is_platform_container }}
+            PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("{container}", "{package_name}", {package_fingerprint});
+{{ -else }}
+            AconfigPackageInternal reader = AconfigPackageInternal.load("{container}", "{package_name}", {package_fingerprint});
+{{ -endif }}
+        {{ -for namespace_with_flags in namespace_flags }}
+        {{ -for flag in namespace_with_flags.flags }}
+        {{ -if flag.is_read_write }}
+            {flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
+        {{ -endif }}
+        {{ -endfor }}
+        {{ -endfor }}
         } catch (Exception e) \{
-            // pass
+            Log.e(TAG, e.toString());
         } catch (NoClassDefFoundError e) \{
             // for mainline module running on older devices.
             // This should be replaces to version check, after the version bump.
+            Log.e(TAG, e.toString());
         }
         isCached = true;
     }
diff --git a/tools/aconfig/aconfig_flags/flags.aconfig b/tools/aconfig/aconfig_flags/flags.aconfig
index b66d282..0a004ca 100644
--- a/tools/aconfig/aconfig_flags/flags.aconfig
+++ b/tools/aconfig/aconfig_flags/flags.aconfig
@@ -14,11 +14,3 @@
   bug: "369808805"
   description: "When enabled, launch aconfigd from config infra module."
 }
-
-flag {
-  name: "enable_system_aconfigd_rust"
-  namespace: "core_experiments_team_internal"
-  bug: "378079539"
-  description: "When enabled, the aconfigd cc_binary target becomes a no-op, and the rust_binary aconfigd-system target starts up."
-  is_fixed_read_only: true
-}
diff --git a/tools/aconfig/aconfig_flags/src/lib.rs b/tools/aconfig/aconfig_flags/src/lib.rs
index b413c62..2e89127 100644
--- a/tools/aconfig/aconfig_flags/src/lib.rs
+++ b/tools/aconfig/aconfig_flags/src/lib.rs
@@ -39,11 +39,6 @@
     pub fn enable_aconfigd_from_mainline() -> bool {
         aconfig_flags_rust::enable_only_new_storage()
     }
-
-    /// Returns the value for the enable_system_aconfigd_rust flag.
-    pub fn enable_system_aconfigd_rust() -> bool {
-        aconfig_flags_rust::enable_system_aconfigd_rust()
-    }
 }
 
 /// Module used when building with cargo
@@ -60,10 +55,4 @@
         // Used only to enable typechecking and testing with cargo
         true
     }
-
-    /// Returns a placeholder value for the enable_system_aconfigd_rust flag.
-    pub fn enable_system_aconfigd_rust() -> bool {
-        // Used only to enable typechecking and testing with cargo
-        true
-    }
 }
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java
index a820970..c2720f9 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java
@@ -58,10 +58,6 @@
                 new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
         PackageTable pt = p.getPackageTable("mock.v1");
         assertNotNull(pt);
-        pt =
-                StorageFileProvider.getPackageTable(
-                        Paths.get(TestDataUtils.TESTDATA_PATH, "mock.v1.package.map"));
-        assertNotNull(pt);
         FlagTable f = p.getFlagTable("mock.v1");
         assertNotNull(f);
         FlagValueList v = p.getFlagValueList("mock.v1");
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 09daeea..6214e2c 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -167,27 +167,8 @@
     ],
     sdk_version: "core_current",
     host_supported: true,
-    min_sdk_version: "29",
-    apex_available: [
-        "//apex_available:platform",
-        "//apex_available:anyapex",
+    visibility: [
+        "//frameworks/base",
+        "//build/make/tools/aconfig/aconfig_storage_read_api/tests",
     ],
 }
-
-java_library {
-    name: "aconfig_storage_reader_java_none",
-    srcs: [
-        "srcs/android/aconfig/storage/StorageInternalReader.java",
-        "srcs/android/os/flagging/PlatformAconfigPackageInternal.java",
-    ],
-    libs: [
-        "unsupportedappusage-sdk-none",
-        "fake_device_config",
-    ],
-    static_libs: [
-        "aconfig_storage_file_java_none",
-    ],
-    sdk_version: "none",
-    system_modules: "core-all-system-modules",
-    host_supported: true,
-}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
index 83310be..d73d9eb 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
@@ -17,7 +17,6 @@
 package android.os.flagging;
 
 import android.aconfig.storage.AconfigStorageException;
-import android.aconfig.storage.FlagTable;
 import android.aconfig.storage.FlagValueList;
 import android.aconfig.storage.PackageTable;
 import android.aconfig.storage.StorageFileProvider;
@@ -41,75 +40,13 @@
  */
 public class PlatformAconfigPackageInternal {
 
-    private final FlagTable mFlagTable;
     private final FlagValueList mFlagValueList;
-    private final int mPackageId;
     private final int mPackageBooleanStartOffset;
-    private final AconfigStorageException mException;
 
     private PlatformAconfigPackageInternal(
-            FlagValueList flagValueList,
-            FlagTable flagTable,
-            int packageBooleanStartOffset,
-            int packageId,
-            AconfigStorageException exception) {
+            FlagValueList flagValueList, int packageBooleanStartOffset) {
         this.mFlagValueList = flagValueList;
-        this.mFlagTable = flagTable;
         this.mPackageBooleanStartOffset = packageBooleanStartOffset;
-        this.mPackageId = packageId;
-        this.mException = exception;
-    }
-
-    /**
-     * Loads an Aconfig Package from platform Aconfig Storage.
-     *
-     * <p>This method is intended for internal use only and may be changed or removed without
-     * notice.
-     *
-     * <p>This method loads the specified Aconfig Package from the given container.
-     *
-     * <p>AconfigStorageException will be stored if there is an error reading from Aconfig Storage.
-     * The specific error code can be got using {@link #getException()}.
-     *
-     * @param container The name of the container.
-     * @param packageName The name of the Aconfig package to load.
-     * @return An instance of {@link PlatformAconfigPackageInternal}
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static PlatformAconfigPackageInternal load(String container, String packageName) {
-        return load(container, packageName, StorageFileProvider.getDefaultProvider());
-    }
-
-    /** @hide */
-    public static PlatformAconfigPackageInternal load(
-            String container, String packageName, StorageFileProvider fileProvider) {
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        try {
-            PackageTable.Node pNode = fileProvider.getPackageTable(container).get(packageName);
-
-            if (pNode == null) {
-                return createExceptionInstance(
-                        AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
-                        "package "
-                                + packageName
-                                + " in container "
-                                + container
-                                + " cannot be found on the device");
-            }
-
-            return new PlatformAconfigPackageInternal(
-                    fileProvider.getFlagValueList(container),
-                    fileProvider.getFlagTable(container),
-                    pNode.getBooleanStartIndex(),
-                    pNode.getPackageId(),
-                    null);
-
-        } catch (AconfigStorageException e) {
-            return createExceptionInstance(e.getErrorCode(), e.getMessage());
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
     }
 
     /**
@@ -118,9 +55,6 @@
      * <p>This method is intended for internal use only and may be changed or removed without
      * notice.
      *
-     * <p>AconfigStorageException will be stored if there is an error reading from Aconfig Storage.
-     * The specific error code can be got using {@link #getException()}.
-     *
      * @param container The name of the container.
      * @param packageName The name of the Aconfig package.
      * @param packageFingerprint The expected fingerprint of the package.
@@ -145,48 +79,40 @@
             long packageFingerprint,
             StorageFileProvider fileProvider) {
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        PackageTable.Node pNode = null;
+        FlagValueList vList = null;
         try {
-            PackageTable.Node pNode = fileProvider.getPackageTable(container).get(packageName);
-
-            if (pNode == null) {
-                return createExceptionInstance(
-                        AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
-                        "package "
-                                + packageName
-                                + " in container "
-                                + container
-                                + " cannot be found on the device");
-            }
-
-            if (pNode.hasPackageFingerprint()
-                    && packageFingerprint != pNode.getPackageFingerprint()) {
-                return new PlatformAconfigPackageInternal(
-                        fileProvider.getFlagValueList(container),
-                        fileProvider.getFlagTable(container),
-                        pNode.getBooleanStartIndex(),
-                        pNode.getPackageId(),
-                        new AconfigStorageException(
-                                AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
-                                "The fingerprint provided for the Aconfig package "
-                                        + packageName
-                                        + " in container "
-                                        + container
-                                        + " does not match"
-                                        + " the fingerprint of the package found on the device."));
-            }
-
-            return new PlatformAconfigPackageInternal(
-                    fileProvider.getFlagValueList(container),
-                    null,
-                    pNode.getBooleanStartIndex(),
-                    0,
-                    null);
-
+            pNode = fileProvider.getPackageTable(container).get(packageName);
+            vList = fileProvider.getFlagValueList(container);
         } catch (AconfigStorageException e) {
-            return createExceptionInstance(e.getErrorCode(), e.getMessage());
+            throw new AconfigStorageReadException(e.getErrorCode(), e.toString());
         } finally {
             StrictMode.setThreadPolicy(oldPolicy);
         }
+
+        if (pNode == null || vList == null) {
+            throw new AconfigStorageReadException(
+                    AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND,
+                    String.format(
+                            "package "
+                                    + packageName
+                                    + " in container "
+                                    + container
+                                    + " cannot be found on the device"));
+        }
+
+        if (pNode.hasPackageFingerprint() && packageFingerprint != pNode.getPackageFingerprint()) {
+            throw new AconfigStorageReadException(
+                    5, // AconfigStorageReadException.ERROR_FILE_FINGERPRINT_MISMATCH,
+                    String.format(
+                            "package "
+                                    + packageName
+                                    + " in container "
+                                    + container
+                                    + " cannot be found on the device"));
+        }
+
+        return new PlatformAconfigPackageInternal(vList, pNode.getBooleanStartIndex());
     }
 
     /**
@@ -198,10 +124,6 @@
      * <p>This method retrieves the value of a flag within the loaded Aconfig package using its
      * index. The index is generated at build time and may vary between builds.
      *
-     * <p>To ensure you are using the correct index, verify that the package's fingerprint matches
-     * the expected fingerprint before calling this method. If the fingerprints do not match, use
-     * {@link #getBooleanFlagValue(String, boolean)} instead.
-     *
      * @param index The index of the flag within the package.
      * @return The boolean value of the flag.
      * @hide
@@ -210,55 +132,4 @@
     public boolean getBooleanFlagValue(int index) {
         return mFlagValueList.getBoolean(index + mPackageBooleanStartOffset);
     }
-
-    /**
-     * Retrieves the value of a boolean flag using its name.
-     *
-     * <p>This method is intended for internal use only and may be changed or removed without
-     * notice.
-     *
-     * <p>This method retrieves the value of a flag within the loaded Aconfig package using its
-     * name.
-     *
-     * @param flagName The name of the flag.
-     * @param defaultValue The default value to return if the flag is not found.
-     * @return The boolean value of the flag.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
-        FlagTable.Node fNode = mFlagTable.get(mPackageId, flagName);
-        if (fNode == null) {
-            return defaultValue;
-        }
-        return mFlagValueList.getBoolean(fNode.getFlagIndex() + mPackageBooleanStartOffset);
-    }
-
-    /**
-     * Returns any exception that occurred during the loading of the Aconfig package.
-     *
-     * <p>This method is intended for internal use only and may be changed or removed without
-     * notice.
-     *
-     * @return The exception that occurred, or {@code null} if no exception occurred.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Exception getException() {
-        return mException;
-    }
-
-    /**
-     * Creates a new {@link PlatformAconfigPackageInternal} instance with an {@link
-     * AconfigStorageException}.
-     *
-     * @param errorCode The error code for the exception.
-     * @param message The error message for the exception.
-     * @return A new {@link PlatformAconfigPackageInternal} instance with the specified exception.
-     */
-    private static PlatformAconfigPackageInternal createExceptionInstance(
-            int errorCode, String message) {
-        return new PlatformAconfigPackageInternal(
-                null, null, 0, 0, new AconfigStorageException(errorCode, message));
-    }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
index fb2fc77..702325d 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
@@ -57,7 +57,6 @@
     static_libs: [
         "aconfig_device_paths_java",
         "aconfig_storage_file_java",
-        "aconfig_storage_reader_java",
         "androidx.test.rules",
         "libaconfig_storage_read_api_java",
         "junit",
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
index 15cfc3b..69e224b 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
@@ -16,18 +16,17 @@
 
 package android.aconfig.storage.test;
 
-import static android.aconfig.nano.Aconfig.ENABLED;
-
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 
 import android.aconfig.DeviceProtos;
+import android.aconfig.nano.Aconfig;
 import android.aconfig.nano.Aconfig.parsed_flag;
-import android.aconfig.storage.AconfigStorageException;
 import android.aconfig.storage.FlagTable;
 import android.aconfig.storage.FlagValueList;
 import android.aconfig.storage.PackageTable;
 import android.aconfig.storage.StorageFileProvider;
+import android.os.flagging.AconfigStorageReadException;
 import android.os.flagging.PlatformAconfigPackageInternal;
 
 import org.junit.Test;
@@ -52,41 +51,9 @@
         StorageFileProvider fp = StorageFileProvider.getDefaultProvider();
 
         for (parsed_flag flag : flags) {
-
-            String container = flag.container;
-            String packageName = flag.package_;
-            String flagName = flag.name;
-            if (!PLATFORM_CONTAINERS.contains(container)) continue;
-
-            PackageTable pTable = fp.getPackageTable(container);
-            PackageTable.Node pNode = pTable.get(packageName);
-            FlagTable fTable = fp.getFlagTable(container);
-            FlagTable.Node fNode = fTable.get(pNode.getPackageId(), flagName);
-            FlagValueList fList = fp.getFlagValueList(container);
-
-            int index = pNode.getBooleanStartIndex() + fNode.getFlagIndex();
-            boolean rVal = fList.getBoolean(index);
-
-            PlatformAconfigPackageInternal reader = readerMap.get(packageName);
-            if (reader == null) {
-                reader = PlatformAconfigPackageInternal.load(container, packageName);
-                assertNull(reader.getException());
-                readerMap.put(packageName, reader);
+            if (flag.permission == Aconfig.READ_ONLY && flag.state == Aconfig.DISABLED) {
+                continue;
             }
-            boolean jVal = reader.getBooleanFlagValue(flagName, !rVal);
-
-            assertEquals(rVal, jVal);
-        }
-    }
-
-    @Test
-    public void testPlatformAconfigPackageInternal_load_with_fingerprint() throws IOException {
-        List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
-        Map<String, PlatformAconfigPackageInternal> readerMap = new HashMap<>();
-        StorageFileProvider fp = StorageFileProvider.getDefaultProvider();
-
-        for (parsed_flag flag : flags) {
-
             String container = flag.container;
             String packageName = flag.package_;
             String flagName = flag.name;
@@ -106,7 +73,6 @@
             PlatformAconfigPackageInternal reader = readerMap.get(packageName);
             if (reader == null) {
                 reader = PlatformAconfigPackageInternal.load(container, packageName, fingerprint);
-                assertNull(reader.getException());
                 readerMap.put(packageName, reader);
             }
             boolean jVal = reader.getBooleanFlagValue(fNode.getFlagIndex());
@@ -118,17 +84,20 @@
     @Test
     public void testAconfigPackage_load_withError() throws IOException {
         // container not found fake_container
-        PlatformAconfigPackageInternal aPackage =
-                PlatformAconfigPackageInternal.load("fake_container", "fake_package", 0);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) aPackage.getException()).getErrorCode());
+        AconfigStorageReadException e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        "fake_container", "fake_package", 0));
+        assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
 
         // package not found
-        aPackage = PlatformAconfigPackageInternal.load("system", "fake_container", 0);
-        assertEquals(
-                AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
-                ((AconfigStorageException) aPackage.getException()).getErrorCode());
+        e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () -> PlatformAconfigPackageInternal.load("system", "fake_container", 0));
+        assertEquals(AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
 
         // fingerprint doesn't match
         List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
@@ -138,18 +107,22 @@
 
         String container = flag.container;
         String packageName = flag.package_;
-        boolean value = flag.state == ENABLED;
+        boolean value = flag.state == Aconfig.ENABLED;
 
         PackageTable pTable = fp.getPackageTable(container);
         PackageTable.Node pNode = pTable.get(packageName);
 
         if (pNode.hasPackageFingerprint()) {
             long fingerprint = pNode.getPackageFingerprint();
-            aPackage = PlatformAconfigPackageInternal.load(container, packageName, fingerprint + 1);
+            e =
+                    assertThrows(
+                            AconfigStorageReadException.class,
+                            () ->
+                                    PlatformAconfigPackageInternal.load(
+                                            container, packageName, fingerprint + 1));
             assertEquals(
                     // AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
-                    5, ((AconfigStorageException) aPackage.getException()).getErrorCode());
-            assertEquals(aPackage.getBooleanFlagValue(flag.name, !value), value);
+                    5, e.getErrorCode());
         }
     }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java b/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
index 392f644..961f0ea 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
@@ -18,12 +18,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
-import android.aconfig.storage.AconfigStorageException;
 import android.aconfig.storage.PackageTable;
 import android.aconfig.storage.StorageFileProvider;
+import android.os.flagging.AconfigStorageReadException;
 import android.os.flagging.PlatformAconfigPackageInternal;
 
 import org.junit.Before;
@@ -46,137 +46,101 @@
 
     @Test
     public void testLoad_container_package() throws Exception {
+        PackageTable packageTable = pr.getPackageTable("mockup");
+
+        PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
+
+        long fingerprint = node1.getPackageFingerprint();
         PlatformAconfigPackageInternal p =
                 PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_1", pr);
-        assertNull(p.getException());
+                        "mockup", "com.android.aconfig.storage.test_1", fingerprint, pr);
     }
 
     @Test
     public void testLoad_container_package_error() throws Exception {
+        PackageTable packageTable = pr.getPackageTable("mockup");
+        PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
+        long fingerprint = node1.getPackageFingerprint();
         // cannot find package
-        PlatformAconfigPackageInternal p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_10", pr);
-
-        assertEquals(
-                AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
-                ((AconfigStorageException) p.getException()).getErrorCode());
+        AconfigStorageReadException e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        "mockup",
+                                        "com.android.aconfig.storage.test_10",
+                                        fingerprint,
+                                        pr));
+        assertEquals(AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
 
         // cannot find container
-        p = PlatformAconfigPackageInternal.load(null, "com.android.aconfig.storage.test_1", pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
-        p = PlatformAconfigPackageInternal.load("test", "com.android.aconfig.storage.test_1", pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
+        e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        null,
+                                        "com.android.aconfig.storage.test_1",
+                                        fingerprint,
+                                        pr));
+        assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
 
-        // new storage doesn't exist
-        pr = new StorageFileProvider("fake/path/", "fake/path/");
-        p = PlatformAconfigPackageInternal.load("mockup", "com.android.aconfig.storage.test_1", pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
+        e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        "test",
+                                        "com.android.aconfig.storage.test_1",
+                                        fingerprint,
+                                        pr));
+        assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
 
-        // file read issue
-        pr = new StorageFileProvider(TESTDATA_PATH, "fake/path/");
-        p = PlatformAconfigPackageInternal.load("mockup", "com.android.aconfig.storage.test_1", pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
-    }
-
-    @Test
-    public void testLoad_container_package_fingerprint() throws Exception {
-        PackageTable packageTable = pr.getPackageTable("mockup");
-
-        PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
-
-        long fingerprint = node1.getPackageFingerprint();
-        PlatformAconfigPackageInternal p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_1", fingerprint, pr);
-        assertNull(p.getException());
-    }
-
-    @Test
-    public void testLoad_container_package_fingerprint_error() throws Exception {
-
-        PackageTable packageTable = pr.getPackageTable("mockup");
-
-        PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
-
-        long fingerprint = node1.getPackageFingerprint();
-
-        // cannot find package
-        PlatformAconfigPackageInternal p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_10", fingerprint, pr);
-
-        assertEquals(
-                AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
-                ((AconfigStorageException) p.getException()).getErrorCode());
-
-        // cannot find container
-        p =
-                PlatformAconfigPackageInternal.load(
-                        null, "com.android.aconfig.storage.test_1", fingerprint, pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
-        p =
-                PlatformAconfigPackageInternal.load(
-                        "test", "com.android.aconfig.storage.test_1", fingerprint, pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
         // fingerprint doesn't match
-        p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_1", fingerprint + 1, pr);
+        e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        "mockup",
+                                        "com.android.aconfig.storage.test_1",
+                                        fingerprint + 1,
+                                        pr));
         assertEquals(
                 // AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
-                5, ((AconfigStorageException) p.getException()).getErrorCode());
+                5, e.getErrorCode());
 
         // new storage doesn't exist
         pr = new StorageFileProvider("fake/path/", "fake/path/");
-        p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_1", fingerprint, pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
+        e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        "mockup",
+                                        "com.android.aconfig.storage.test_1",
+                                        fingerprint,
+                                        pr));
+        assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
 
         // file read issue
         pr = new StorageFileProvider(TESTDATA_PATH, "fake/path/");
-        p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_1", fingerprint, pr);
-        assertEquals(
-                AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
-                ((AconfigStorageException) p.getException()).getErrorCode());
-    }
-
-    @Test
-    public void testGetBooleanFlagValue_flagName() throws Exception {
-        PlatformAconfigPackageInternal p =
-                PlatformAconfigPackageInternal.load(
-                        "mockup", "com.android.aconfig.storage.test_1", pr);
-        assertFalse(p.getBooleanFlagValue("disabled_rw", true));
-        assertTrue(p.getBooleanFlagValue("enabled_ro", false));
-        assertTrue(p.getBooleanFlagValue("enabled_rw", false));
-        assertFalse(p.getBooleanFlagValue("fake", false));
+        e =
+                assertThrows(
+                        AconfigStorageReadException.class,
+                        () ->
+                                PlatformAconfigPackageInternal.load(
+                                        "mockup",
+                                        "com.android.aconfig.storage.test_1",
+                                        fingerprint,
+                                        pr));
+        assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
     }
 
     @Test
     public void testGetBooleanFlagValue_index() throws Exception {
-
         PackageTable packageTable = pr.getPackageTable("mockup");
-
         PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
-
         long fingerprint = node1.getPackageFingerprint();
         PlatformAconfigPackageInternal p =
                 PlatformAconfigPackageInternal.load(
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index 3f593fe..aef7d7e 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -93,11 +93,7 @@
         special_fields: SpecialFields::new(),
     };
 
-    let socket_name = if aconfig_flags::auto_generated::enable_system_aconfigd_rust() {
-        "/dev/socket/aconfigd_system"
-    } else {
-        "/dev/socket/aconfigd"
-    };
+    let socket_name = "/dev/socket/aconfigd_system";
     let mut socket = UnixStream::connect(socket_name)?;
 
     let message_buffer = messages.write_to_bytes()?;
diff --git a/tools/aconfig/fake_device_config/src/android/os/Build.java b/tools/aconfig/fake_device_config/src/android/os/Build.java
new file mode 100644
index 0000000..8ec72fb
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/os/Build.java
@@ -0,0 +1,23 @@
+/*
+ * 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.os;
+
+public class Build {
+    public static class VERSION {
+        public static final int SDK_INT = 0;
+    }
+}
diff --git a/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigPackageInternal.java b/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigPackageInternal.java
index 5f066a8..d084048 100644
--- a/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigPackageInternal.java
+++ b/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigPackageInternal.java
@@ -21,10 +21,6 @@
  */
 public class AconfigPackageInternal {
 
-    public static AconfigPackageInternal load(String container, String packageName) {
-        throw new UnsupportedOperationException("Stub!");
-    }
-
     public static AconfigPackageInternal load(
             String container, String packageName, long packageFingerprint) {
         throw new UnsupportedOperationException("Stub!");
@@ -33,12 +29,4 @@
     public boolean getBooleanFlagValue(int index) {
         throw new UnsupportedOperationException("Stub!");
     }
-
-    public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
-        throw new UnsupportedOperationException("Stub!");
-    }
-
-    public AconfigStorageReadException getException() {
-        throw new UnsupportedOperationException("Stub!");
-    }
 }
diff --git a/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackageInternal.java b/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackageInternal.java
index c1bc19b..283b251 100644
--- a/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackageInternal.java
+++ b/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackageInternal.java
@@ -21,10 +21,6 @@
  */
 public class PlatformAconfigPackageInternal {
 
-    public static PlatformAconfigPackageInternal load(String container, String packageName) {
-        throw new UnsupportedOperationException("Stub!");
-    }
-
     public static PlatformAconfigPackageInternal load(
             String container, String packageName, long packageFingerprint) {
         throw new UnsupportedOperationException("Stub!");
@@ -33,12 +29,4 @@
     public boolean getBooleanFlagValue(int index) {
         throw new UnsupportedOperationException("Stub!");
     }
-
-    public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
-        throw new UnsupportedOperationException("Stub!");
-    }
-
-    public AconfigStorageReadException getException() {
-        throw new UnsupportedOperationException("Stub!");
-    }
 }
diff --git a/tools/aconfig/fake_device_config/src/android/provider/AconfigPackage.java b/tools/aconfig/fake_device_config/src/android/provider/AconfigPackage.java
deleted file mode 100644
index 2f01b8c..0000000
--- a/tools/aconfig/fake_device_config/src/android/provider/AconfigPackage.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.provider;
-
-/*
- * This class allows generated aconfig code to compile independently of the framework.
- */
-public class AconfigPackage {
-
-    /** Flag value is true */
-    public static final int FLAG_BOOLEAN_VALUE_TRUE = 1;
-
-    /** Flag value is false */
-    public static final int FLAG_BOOLEAN_VALUE_FALSE = 0;
-
-    /** Flag value doesn't exist */
-    public static final int FLAG_BOOLEAN_VALUE_NOT_EXIST = 2;
-
-    public static int getBooleanFlagValue(String packageName, String flagName) {
-        return 0;
-    }
-
-    public AconfigPackage(String packageName) {}
-
-    public int getBooleanFlagValue(String flagName) {
-        return 0;
-    }
-}
\ No newline at end of file
diff --git a/tools/edit_monitor/daemon_manager.py b/tools/edit_monitor/daemon_manager.py
index 0c31ab8..a352e30 100644
--- a/tools/edit_monitor/daemon_manager.py
+++ b/tools/edit_monitor/daemon_manager.py
@@ -149,15 +149,15 @@
             edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE
         )
         logging.error(
-            "Daemon process is consuming too much memory, rebooting...")
+            "Daemon process is consuming too much memory, rebooting..."
+        )
         self.reboot()
 
       if self.max_cpu_usage >= cpu_threshold:
         self._send_error_event_to_clearcut(
             edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_CPU_USAGE
         )
-        logging.error(
-            "Daemon process is consuming too much cpu, killing...")
+        logging.error("Daemon process is consuming too much cpu, killing...")
         self._terminate_process(self.daemon_process.pid)
 
     logging.info(
@@ -179,7 +179,7 @@
         self._wait_for_process_terminate(self.daemon_process.pid, 1)
         if self.daemon_process.is_alive():
           self._terminate_process(self.daemon_process.pid)
-      self._remove_pidfile()
+      self._remove_pidfile(self.pid)
       logging.info("Successfully stopped daemon manager.")
     except Exception as e:
       logging.exception("Failed to stop daemon manager with error %s", e)
@@ -253,11 +253,15 @@
     if ex_pid:
       logging.info("Found another instance with pid %d.", ex_pid)
       self._terminate_process(ex_pid)
-      self._remove_pidfile()
+      self._remove_pidfile(ex_pid)
 
-  def _read_pid_from_pidfile(self):
-    with open(self.pid_file_path, "r") as f:
-      return int(f.read().strip())
+  def _read_pid_from_pidfile(self) -> int | None:
+    try:
+      with open(self.pid_file_path, "r") as f:
+        return int(f.read().strip())
+    except FileNotFoundError as e:
+      logging.warning("pidfile %s does not exist.", self.pid_file_path)
+      return None
 
   def _write_pid_to_pidfile(self):
     """Creates a pidfile and writes the current pid to the file.
@@ -333,7 +337,23 @@
       )
       return True
 
-  def _remove_pidfile(self):
+  def _remove_pidfile(self, expected_pid: int):
+    recorded_pid = self._read_pid_from_pidfile()
+
+    if recorded_pid is None:
+      logging.info("pid file %s already removed.", self.pid_file_path)
+      return
+
+    if recorded_pid != expected_pid:
+      logging.warning(
+          "pid file contains pid from a different process, expected pid: %d,"
+          " actual pid: %d.",
+          expected_pid,
+          recorded_pid,
+      )
+      return
+
+    logging.debug("removing pidfile written by process %s", expected_pid)
     try:
       os.remove(self.pid_file_path)
     except FileNotFoundError:
@@ -378,9 +398,7 @@
       uptime_end = float(f.readline().split()[0])
 
     return (
-        (total_end_time - total_start_time)
-        / (uptime_end - uptime_start)
-        * 100
+        (total_end_time - total_start_time) / (uptime_end - uptime_start) * 100
     )
 
   def _get_total_cpu_time(self, pid: int) -> float:
diff --git a/tools/edit_monitor/edit_monitor_integration_test.py b/tools/edit_monitor/edit_monitor_integration_test.py
index 3d28274..f39b936 100644
--- a/tools/edit_monitor/edit_monitor_integration_test.py
+++ b/tools/edit_monitor/edit_monitor_integration_test.py
@@ -15,6 +15,7 @@
 """Integration tests for Edit Monitor."""
 
 import glob
+from importlib import resources
 import logging
 import os
 import pathlib
@@ -25,8 +26,6 @@
 import tempfile
 import time
 import unittest
-
-from importlib import resources
 from unittest import mock
 
 
@@ -49,7 +48,8 @@
     self.root_monitoring_path.mkdir()
     self.edit_monitor_binary_path = self._import_executable("edit_monitor")
     self.patch = mock.patch.dict(
-        os.environ, {'ENABLE_ANDROID_EDIT_MONITOR': 'true'})
+        os.environ, {"ENABLE_ANDROID_EDIT_MONITOR": "true"}
+    )
     self.patch.start()
 
   def tearDown(self):
@@ -83,7 +83,21 @@
 
     self.assertEqual(self._get_logged_events_num(), 4)
 
-  def _start_edit_monitor_process(self):
+  def test_start_multiple_edit_monitor_only_one_started(self):
+    p1 = self._start_edit_monitor_process(wait_for_observer_start=False)
+    p2 = self._start_edit_monitor_process(wait_for_observer_start=False)
+    p3 = self._start_edit_monitor_process(wait_for_observer_start=False)
+
+    live_processes = self._get_live_processes([p1, p2, p3])
+
+    # Cleanup all live processes.
+    for p in live_processes:
+      os.kill(p.pid, signal.SIGINT)
+      p.communicate()
+
+    self.assertEqual(len(live_processes), 1)
+
+  def _start_edit_monitor_process(self, wait_for_observer_start=True):
     command = f"""
     export TMPDIR="{self.working_dir.name}"
     {self.edit_monitor_binary_path} --path={self.root_monitoring_path} --dry_run"""
@@ -94,7 +108,9 @@
         start_new_session=True,
         executable="/bin/bash",
     )
-    self._wait_for_observer_start(time_out=5)
+    if wait_for_observer_start:
+      self._wait_for_observer_start(time_out=5)
+
     return p
 
   def _wait_for_observer_start(self, time_out):
@@ -125,6 +141,18 @@
 
     return 0
 
+  def _get_live_processes(self, processes):
+    live_processes = []
+    for p in processes:
+      try:
+        p.wait(timeout=5)
+      except subprocess.TimeoutExpired as e:
+        live_processes.append(p)
+        logging.info("process: %d still alive.", p.pid)
+      else:
+        logging.info("process: %d stopped.", p.pid)
+    return live_processes
+
   def _import_executable(self, executable_name: str) -> pathlib.Path:
     binary_dir = pathlib.Path(self.working_dir.name).joinpath("binary")
     binary_dir.mkdir()
diff --git a/tools/edit_monitor/main.py b/tools/edit_monitor/main.py
index 49385f1..7ca0daa 100644
--- a/tools/edit_monitor/main.py
+++ b/tools/edit_monitor/main.py
@@ -72,7 +72,8 @@
   root_logging_dir = tempfile.mkdtemp(prefix='edit_monitor_')
   _, log_path = tempfile.mkstemp(dir=root_logging_dir, suffix='.log')
 
-  log_fmt = '%(asctime)s %(filename)s:%(lineno)s:%(levelname)s: %(message)s'
+
+  log_fmt = '%(asctime)s.%(msecs)03d %(filename)s:%(lineno)s:%(levelname)s: %(message)s'
   date_fmt = '%Y-%m-%d %H:%M:%S'
   log_level = logging.DEBUG if verbose else logging.INFO
 
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index 54df955..08f2b83 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -79,15 +79,10 @@
     Returns:
       The repacked apex file containing the signed apk files.
     """
-    if not os.path.exists(self.debugfs_path):
-      raise ApexSigningError(
-          "Couldn't find location of debugfs_static: " +
-          "Path {} does not exist. ".format(self.debugfs_path) +
-          "Make sure bin/debugfs_static can be found in -p <path>")
-    list_cmd = ['deapexer', '--debugfs_path', self.debugfs_path,
-                'list', self.apex_path]
-    entries_names = common.RunAndCheckOutput(list_cmd).split()
-    apk_entries = [name for name in entries_names if name.endswith('.apk')]
+    payload_dir = self.ExtractApexPayload(self.apex_path)
+    apk_entries = []
+    for base_dir, _, files in os.walk(payload_dir):
+      apk_entries.extend(os.path.join(base_dir, file) for file in files if file.endswith('.apk'))
 
     # No need to sign and repack, return the original apex path.
     if not apk_entries and self.sign_tool is None:
@@ -105,16 +100,16 @@
         logger.warning('Apk path does not contain the intended directory name:'
                        ' %s', entry)
 
-    payload_dir, has_signed_content = self.ExtractApexPayloadAndSignContents(
-        apk_entries, apk_keys, payload_key, signing_args)
+    has_signed_content = self.SignContentsInPayload(
+        payload_dir, apk_entries, apk_keys, payload_key, signing_args)
     if not has_signed_content:
       logger.info('No contents has been signed in %s', self.apex_path)
       return self.apex_path
 
     return self.RepackApexPayload(payload_dir, payload_key, signing_args)
 
-  def ExtractApexPayloadAndSignContents(self, apk_entries, apk_keys, payload_key, signing_args):
-    """Extracts the payload image and signs the containing apk files."""
+  def ExtractApexPayload(self, apex_path):
+    """Extracts the contents of an APEX and returns the directory of the contents"""
     if not os.path.exists(self.debugfs_path):
       raise ApexSigningError(
           "Couldn't find location of debugfs_static: " +
@@ -129,9 +124,12 @@
     extract_cmd = ['deapexer', '--debugfs_path', self.debugfs_path,
                    '--fsckerofs_path', self.fsckerofs_path,
                    'extract',
-                   self.apex_path, payload_dir]
+                   apex_path, payload_dir]
     common.RunAndCheckOutput(extract_cmd)
+    return payload_dir
 
+  def SignContentsInPayload(self, payload_dir, apk_entries, apk_keys, payload_key, signing_args):
+    """Signs the contents in payload."""
     has_signed_content = False
     for entry in apk_entries:
       apk_path = os.path.join(payload_dir, entry)
@@ -163,7 +161,7 @@
       common.RunAndCheckOutput(cmd)
       has_signed_content = True
 
-    return payload_dir, has_signed_content
+    return has_signed_content
 
   def RepackApexPayload(self, payload_dir, payload_key, signing_args=None):
     """Rebuilds the apex file with the updated payload directory."""
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 6446e1f..76d168c 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -1039,6 +1039,9 @@
 
   # Prepare custom images.
   if OPTIONS.custom_images:
+    if source_file is not None:
+      source_file = GetTargetFilesZipForCustomImagesUpdates(
+           source_file, OPTIONS.custom_images)
     target_file = GetTargetFilesZipForCustomImagesUpdates(
         target_file, OPTIONS.custom_images)
 
@@ -1121,17 +1124,18 @@
   additional_args += ["--enable_lz4diff=" +
                       str(OPTIONS.enable_lz4diff).lower()]
 
+  env_override = {}
   if source_file and OPTIONS.enable_lz4diff:
-    input_tmp = common.UnzipTemp(source_file, ["META/liblz4.so"])
-    liblz4_path = os.path.join(input_tmp, "META", "liblz4.so")
+    liblz4_path = os.path.join(source_file, "META", "liblz4.so")
     assert os.path.exists(
         liblz4_path), "liblz4.so not found in META/ dir of target file {}".format(liblz4_path)
     logger.info("Enabling lz4diff %s", liblz4_path)
-    additional_args += ["--liblz4_path", liblz4_path]
     erofs_compression_param = OPTIONS.target_info_dict.get(
         "erofs_default_compressor")
     assert erofs_compression_param is not None, "'erofs_default_compressor' not found in META/misc_info.txt of target build. This is required to enable lz4diff."
     additional_args += ["--erofs_compression_param", erofs_compression_param]
+    env_override["LD_PRELOAD"] = liblz4_path + \
+        ":" + os.environ.get("LD_PRELOAD", "")
 
   if OPTIONS.disable_vabc:
     additional_args += ["--disable_vabc=true"]
@@ -1141,10 +1145,15 @@
     additional_args += ["--compressor_types", OPTIONS.compressor_types]
   additional_args += ["--max_timestamp", max_timestamp]
 
+  env = dict(os.environ)
+  if env_override:
+    logger.info("Using environment variables %s", env_override)
+    env.update(env_override)
   payload.Generate(
       target_file,
       source_file,
-      additional_args + partition_timestamps_flags
+      additional_args + partition_timestamps_flags,
+      env=env
   )
 
   # Sign the payload.
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 81b53dc..852d62b 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -845,16 +845,16 @@
     self.is_partial_update = is_partial_update
     self.spl_downgrade = spl_downgrade
 
-  def _Run(self, cmd):  # pylint: disable=no-self-use
+  def _Run(self, cmd, **kwargs):  # pylint: disable=no-self-use
     # Don't pipe (buffer) the output if verbose is set. Let
     # brillo_update_payload write to stdout/stderr directly, so its progress can
     # be monitored.
     if OPTIONS.verbose:
-      common.RunAndCheckOutput(cmd, stdout=None, stderr=None)
+      common.RunAndCheckOutput(cmd, stdout=None, stderr=None, **kwargs)
     else:
-      common.RunAndCheckOutput(cmd)
+      common.RunAndCheckOutput(cmd, **kwargs)
 
-  def Generate(self, target_file, source_file=None, additional_args=None):
+  def Generate(self, target_file, source_file=None, additional_args=None, **kwargs):
     """Generates a payload from the given target-files zip(s).
 
     Args:
@@ -863,6 +863,7 @@
           generating a full OTA.
       additional_args: A list of additional args that should be passed to
           delta_generator binary; or None.
+      kwargs: Any additional args to pass to subprocess.Popen
     """
     if additional_args is None:
       additional_args = []
@@ -918,7 +919,7 @@
     if self.is_partial_update:
       cmd.extend(["--is_partial_update=true"])
     cmd.extend(additional_args)
-    self._Run(cmd)
+    self._Run(cmd, **kwargs)
 
     self.payload_file = payload_file
     self.payload_properties = None