Merge "aflags: only permit enable/disable with root access." into main
diff --git a/core/Makefile b/core/Makefile
index f132db3..93f88c0 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -5061,9 +5061,12 @@
 check_vintf_all_deps :=
 
 # -----------------------------------------------------------------
-# Activate vendor APEXes for checkvintf
+# Activate APEXes for checkvintf
 
 apex_dirs := \
+  $(TARGET_OUT)/apex/% \
+  $(TARGET_OUT_PRODUCT)/apex/% \
+  $(TARGET_OUT_SYSTEM_EXT)/apex/% \
   $(TARGET_OUT_VENDOR)/apex/% \
 
 apex_files := $(sort $(filter $(apex_dirs), $(INTERNAL_ALLIMAGES_FILES)))
@@ -5079,7 +5082,10 @@
 	@echo $(PRIVATE_APEX_FILES) > /dev/null
 	@rm -rf $(APEX_OUT)
 	@mkdir -p $(APEX_OUT)
-	$< --vendor_path $(TARGET_OUT_VENDOR) \
+	$< --system_path $(TARGET_OUT) \
+	   --system_ext_path $(TARGET_OUT_SYSTEM_EXT) \
+	   --product_path $(TARGET_OUT_PRODUCT) \
+	   --vendor_path $(TARGET_OUT_VENDOR) \
 	   --apex_path $(APEX_OUT)
 
 apex_files :=
@@ -5087,14 +5093,14 @@
 
 # The build system only writes VINTF metadata to */etc/vintf paths. Legacy paths aren't needed here
 # because they are only used for prebuilt images.
-# APEX files in /vendor/apex can have VINTF fragments as well.
+# APEX files in /$partition/apex can have VINTF fragments as well.
 check_vintf_common_srcs_patterns := \
   $(TARGET_OUT)/etc/vintf/% \
   $(TARGET_OUT_VENDOR)/etc/vintf/% \
   $(TARGET_OUT_ODM)/etc/vintf/% \
   $(TARGET_OUT_PRODUCT)/etc/vintf/% \
   $(TARGET_OUT_SYSTEM_EXT)/etc/vintf/% \
-  $(TARGET_OUT_VENDOR)/apex/% \
+  $(apex_dirs)
 
 check_vintf_common_srcs := $(sort $(filter $(check_vintf_common_srcs_patterns),$(INTERNAL_ALLIMAGES_FILES)))
 check_vintf_common_srcs_patterns :=
@@ -5112,15 +5118,17 @@
 # -- Check system and system_ext manifests / matrices including fragments (excluding other framework manifests / matrices, e.g. product);
 ifdef BUILDING_SYSTEM_IMAGE
 check_vintf_system_deps := $(filter $(TARGET_OUT)/etc/vintf/% \
-                                    $(TARGET_OUT_SYSTEM_EXT)/etc/vintf/%, \
+                                    $(TARGET_OUT_SYSTEM_EXT)/etc/vintf/% \
+                                    $(TARGET_OUT)/apex/% \
+                                    $(TARGET_OUT_SYSTEM_EXT)/apex/%, \
                                     $(check_vintf_common_srcs))
 ifneq ($(check_vintf_system_deps),)
 check_vintf_has_system := true
 
 check_vintf_system_log := $(intermediates)/check_vintf_system.log
 check_vintf_all_deps += $(check_vintf_system_log)
-$(check_vintf_system_log): $(HOST_OUT_EXECUTABLES)/checkvintf $(check_vintf_system_deps)
-	@( $< --check-one --dirmap /system:$(TARGET_OUT) > $@ 2>&1 ) || ( cat $@ && exit 1 )
+$(check_vintf_system_log): $(HOST_OUT_EXECUTABLES)/checkvintf $(check_vintf_system_deps) $(APEX_INFO_FILE)
+	@( $< --check-one --dirmap /system:$(TARGET_OUT) --dirmap /apex:$(APEX_OUT) > $@ 2>&1 ) || ( cat $@ && exit 1 )
 $(call declare-1p-target,$(check_vintf_system_log))
 check_vintf_system_log :=
 
@@ -5129,10 +5137,11 @@
     vintffm_log := $(intermediates)/vintffm.log
 endif
 check_vintf_all_deps += $(vintffm_log)
-$(vintffm_log): $(HOST_OUT_EXECUTABLES)/vintffm $(check_vintf_system_deps)
+$(vintffm_log): $(HOST_OUT_EXECUTABLES)/vintffm $(check_vintf_system_deps) $(APEX_INFO_FILE)
 	@( $< --check --dirmap /system:$(TARGET_OUT) \
 	  --dirmap /system_ext:$(TARGET_OUT_SYSTEM_EXT) \
 	  --dirmap /product:$(TARGET_OUT_PRODUCT) \
+	  --dirmap /apex:$(APEX_OUT) \
 	  $(VINTF_FRAMEWORK_MANIFEST_FROZEN_DIR) > $@ 2>&1 ) || ( cat $@ && exit 1 )
 
 $(call declare-1p-target,$(vintffm_log))
@@ -5922,6 +5931,9 @@
 ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
 	$(hide) echo "allow_non_ab=true" >> $@
 endif
+ifeq ($(BOARD_NON_AB_OTA_DISABLE_COMPRESSION),true)
+	$(hide) echo "board_non_ab_ota_disable_compression=true" >> $@
+endif
 ifdef BOARD_PREBUILT_DTBOIMAGE
 	$(hide) echo "has_dtbo=true" >> $@
 ifeq ($(BOARD_AVB_ENABLE),true)
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 82e8baa..ac586c5 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -37,7 +37,12 @@
 # Default behavior for the tree wrt building modules or using prebuilts. This
 # can always be overridden by setting the environment variable
 # MODULE_BUILD_FROM_SOURCE.
-BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
+BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := $(RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE)
+# TODO(b/301454934): The value from build flag is set to empty when use `False`
+# The condition below can be removed after the issue get sorted.
+ifeq (,$(BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE))
+  BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := false
+endif
 
 ifneq ($(SANITIZE_TARGET)$(EMMA_INSTRUMENT_FRAMEWORK),)
   # Always use sources when building the framework with Java coverage or
@@ -46,6 +51,18 @@
   BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
 endif
 
+ifneq ($(CLANG_COVERAGE)$(NATIVE_COVERAGE_PATHS),)
+  # Always use sources when building with clang coverage and native coverage.
+  # It is possible that there are certain situations when building with coverage
+  # would work with prebuilts, e.g. when the coverage is not being applied to
+  # modules for which we provide prebuilts. Unfortunately, determining that
+  # would require embedding knowledge of which coverage paths affect which
+  # modules here. That would duplicate a lot of information, add yet another
+  # location  module authors have to update and complicate the logic here.
+  # For nowe we will just always build from sources when doing coverage builds.
+  BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
+endif
+
 # ART does not provide linux_bionic variants needed for products that
 # set HOST_CROSS_OS=linux_bionic.
 ifeq (linux_bionic,${HOST_CROSS_OS})
@@ -117,6 +134,7 @@
   rkpd \
   uwb \
   wifi \
+  mediaprovider \
 
 $(foreach m, $(INDIVIDUALLY_TOGGLEABLE_PREBUILT_MODULES),\
   $(if $(call soong_config_get,$(m)_module,source_build),,\
@@ -144,8 +162,8 @@
 SYSTEMUI_OPTIMIZE_JAVA ?= true
 $(call add_soong_config_var,ANDROID,SYSTEMUI_OPTIMIZE_JAVA)
 
-# Disable Compose in SystemUI by default.
-SYSTEMUI_USE_COMPOSE ?= false
+# Enable Compose in SystemUI by default.
+SYSTEMUI_USE_COMPOSE ?= true
 $(call add_soong_config_var,ANDROID,SYSTEMUI_USE_COMPOSE)
 
 ifdef PRODUCT_AVF_ENABLED
diff --git a/core/board_config.mk b/core/board_config.mk
index 77489c6..25e0643 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -949,6 +949,11 @@
   endif
 endif
 
+# For Non A/B full OTA, disable brotli compression.
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
+  BOARD_NON_AB_OTA_DISABLE_COMPRESSION := true
+endif
+
 # Quick check for building generic OTA packages. Currently it only supports A/B OTAs.
 ifeq ($(PRODUCT_BUILD_GENERIC_OTA_PACKAGE),true)
   ifneq ($(AB_OTA_UPDATER),true)
diff --git a/core/config.mk b/core/config.mk
index dbee0a0..546858a 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1273,7 +1273,7 @@
 endif
 
 ifeq (true,$(FULL_SYSTEM_OPTIMIZE_JAVA))
-ifeq (,$(SYSTEM_OPTIMIZE_JAVA))
+ifeq (false,$(SYSTEM_OPTIMIZE_JAVA))
 $(error SYSTEM_OPTIMIZE_JAVA must be enabled when FULL_SYSTEM_OPTIMIZE_JAVA is enabled)
 endif
 endif
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 91cb2c9..b9f0988 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -144,30 +144,30 @@
 	$(call generate-coverage-report-cts,"CTS System API Coverage Report - XML",\
 			$(PRIVATE_TEST_CASES),xml)
 
-$(cts-verifier-coverage-report): PRIVATE_TEST_CASES := $(cts_verifier_apk)
+$(cts-verifier-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(verifier-dir), $(c))
 $(cts-verifier-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
 $(cts-verifier-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
 $(cts-verifier-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
 $(cts-verifier-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
-$(cts-verifier-coverage-report) : $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-verifier-coverage-report) : $(cts_verifier_apk) $(verifier-zip) $(cts_api_coverage_dependencies) | $(ACP)
 	$(call generate-coverage-report-cts,"CTS Verifier API Coverage Report",\
 			$(PRIVATE_TEST_CASES),html)
 
-$(cts-combined-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts), $(c))
+$(cts-combined-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts) $(verifier-dir), $(c))
 $(cts-combined-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
 $(cts-combined-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
 $(cts-combined-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
 $(cts-combined-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
-$(cts-combined-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-combined-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(verifier-zip) $(cts_api_coverage_dependencies) | $(ACP)
 	$(call generate-coverage-report-cts,"CTS Combined API Coverage Report",\
 			$(PRIVATE_TEST_CASES),html)
 
-$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts), $(c))
+$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts) $(verifier-dir), $(c))
 $(cts-combined-xml-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
 $(cts-combined-xml-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
 $(cts-combined-xml-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
 $(cts-combined-xml-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
-$(cts-combined-xml-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-combined-xml-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(verifier-zip) $(cts_api_coverage_dependencies) | $(ACP)
 	$(call generate-coverage-report-cts,"CTS Combined API Coverage Report - XML",\
 			$(PRIVATE_TEST_CASES),xml)
 
@@ -236,3 +236,8 @@
 cts_api_coverage_exe :=
 cts_verifier_apk :=
 android_cts_zip :=
+cts-dir :=
+verifier-dir-name :=
+verifier-dir :=
+verifier-zip-name :=
+verifier-zip :=
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index b8aeb38..3d057e2 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -94,15 +94,16 @@
     ExtShared \
     flags_health_check \
     framework-graphics \
+    framework-location \
     framework-minus-apex \
     framework-minus-apex-install-dependencies \
-    framework-res \
     framework-sysconfig.xml \
     fsck.erofs \
     fsck_msdos \
     fsverity-release-cert-der \
     fs_config_files_system \
     fs_config_dirs_system \
+    gpu_counter_producer \
     group_system \
     gsid \
     gsi_tool \
@@ -238,10 +239,12 @@
     perfetto \
     ping \
     ping6 \
+    pintool \
     platform.xml \
     pm \
     preinstalled-packages-asl-files.xml \
     preinstalled-packages-platform.xml \
+    preinstalled-packages-strict-signature.xml \
     printflags \
     privapp-permissions-platform.xml \
     prng_seeder \
@@ -262,6 +265,7 @@
     services \
     settings \
     SettingsProvider \
+    sfdo \
     sgdisk \
     Shell \
     shell_and_utilities_system \
@@ -284,7 +288,6 @@
     uncrypt \
     usbd \
     vdc \
-    viewcompiler \
     voip-common \
     vold \
     watchdogd \
@@ -415,7 +418,6 @@
     unwind_info \
     unwind_reg_info \
     unwind_symbols \
-    viewcompiler \
     tzdata_host \
     tzdata_host_tzdata_apex \
     tzlookup.xml_host_tzdata_apex \
@@ -440,6 +442,7 @@
     adevice_fingerprint \
     arping \
     dmuserd \
+    evemu-record \
     idlcli \
     init-debug.rc \
     iotop \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index a0c5929..ec3de75 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -51,7 +51,6 @@
     dumpsys_vendor \
     fs_config_files_nonsystem \
     fs_config_dirs_nonsystem \
-    gpu_counter_producer \
     gralloc.default \
     group_odm \
     group_vendor \
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index d13a4c4..4a968d7 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -50,6 +50,7 @@
 PRODUCT_BOOT_JARS += \
     framework-minus-apex \
     framework-graphics \
+    framework-location \
     ext \
     telephony-common \
     voip-common \
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 80aecb7..f771916 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -24,7 +24,7 @@
 VNDK-SP: android.hardware.common-V2-ndk.so
 VNDK-SP: android.hardware.common.fmq-V1-ndk.so
 VNDK-SP: android.hardware.graphics.allocator-V2-ndk.so
-VNDK-SP: android.hardware.graphics.common-V4-ndk.so
+VNDK-SP: android.hardware.graphics.common-V5-ndk.so
 VNDK-SP: android.hardware.graphics.common@1.0.so
 VNDK-SP: android.hardware.graphics.common@1.1.so
 VNDK-SP: android.hardware.graphics.common@1.2.so
@@ -60,8 +60,8 @@
 VNDK-SP: libutilscallstack.so
 VNDK-SP: libz.so
 VNDK-core: android.frameworks.cameraservice.common-V1-ndk.so
-VNDK-core: android.frameworks.cameraservice.device-V1-ndk.so
-VNDK-core: android.frameworks.cameraservice.service-V1-ndk.so
+VNDK-core: android.frameworks.cameraservice.device-V2-ndk.so
+VNDK-core: android.frameworks.cameraservice.service-V2-ndk.so
 VNDK-core: android.hardware.audio.common@2.0.so
 VNDK-core: android.hardware.configstore-utils.so
 VNDK-core: android.hardware.configstore@1.0.so
@@ -138,6 +138,7 @@
 VNDK-core: libxml2.so
 VNDK-core: libyuv.so
 VNDK-core: libziparchive.so
+VNDK-core: server_configurable_flags.so
 VNDK-private: libblas.so
 VNDK-private: libcompiler_rt.so
 VNDK-private: libft2.so
@@ -208,3 +209,4 @@
 VNDK-product: libyuv.so
 VNDK-product: libz.so
 VNDK-product: libziparchive.so
+VNDK-product: server_configurable_flags.so
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index a581324..2e37366 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -31,11 +31,7 @@
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
     system/etc/init/config \
     system/product/% \
-    system/system_ext/% \
-    system/lib/vndk-29 \
-    system/lib/vndk-sp-29 \
-    system/lib64/vndk-29 \
-    system/lib64/vndk-sp-29
+    system/system_ext/%
 
 # GSI should always support up-to-date platform features.
 # Keep this value at the latest API level to ensure latest build system
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index b5292d2..bf9aa41 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -74,6 +74,7 @@
     VpnDialogs \
     vr \
 
+PRODUCT_PACKAGES += $(RELEASE_PACKAGE_VIRTUAL_CAMERA)
 
 PRODUCT_SYSTEM_SERVER_APPS += \
     FusedLocation \
diff --git a/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml b/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml
index 1295e1c..d3e2808 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml
@@ -27,5 +27,6 @@
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 </config>
diff --git a/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml b/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml
index e2482e1..ef8056f 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml
@@ -24,6 +24,7 @@
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 </config>
 
diff --git a/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml b/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml
index 54add22..536c35b 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml
@@ -29,6 +29,7 @@
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 
     <!--  Camera (Camera2) -->
@@ -42,6 +43,7 @@
     <install-in-user-type package="com.android.deskclock">
         <install-in user-type="FULL" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 
     <!--  Contacts -->
@@ -56,6 +58,7 @@
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 
     <!--  Search (QuickSearchBox) TODO(b/258055479) -->
@@ -64,6 +67,7 @@
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 
     <!-- WallpaperCropper -->
diff --git a/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml b/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml
index cc1c135..67a2a01 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml
@@ -24,6 +24,7 @@
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
         <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+        <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
     </install-in-user-type>
 </config>
 
diff --git a/tools/aconfig/aconfig_protos/protos/aconfig.proto b/tools/aconfig/aconfig_protos/protos/aconfig.proto
index 8833722..9d1b8cb 100644
--- a/tools/aconfig/aconfig_protos/protos/aconfig.proto
+++ b/tools/aconfig/aconfig_protos/protos/aconfig.proto
@@ -22,16 +22,38 @@
 
 // This protobuf file defines messages used to represent and manage flags in the "aconfig" system
 // The following format requirements apply across various message fields:
-// # name: a lowercase string in snake_case format, no consecutive underscores, and no leading digit
-//    For example adjust_rate is a valid name, while AdjustRate, adjust__rate, and
-//    2adjust_rate are invalid
 //
-// # namespace: a lowercase string in snake_case format, no consecutive underscores, and no leading
-//    digit. For example android_bar_system
+// # name: name of the flag
 //
-// # package: lowercase strings in snake_case format, delimited by dots, no consecutive underscores
-//    and no leading digit in each string. For example com.android.mypackage is a valid name
-//    while com.android.myPackage, com.android.1mypackage are invalid
+//    format: a lowercase string in snake_case format, no consecutive underscores, and no leading
+//      digit. For example adjust_rate is a valid name, while AdjustRate, adjust__rate, and
+//      adjust_rate are invalid
+//
+// # namespace: namespace the flag belongs to
+//
+//    format: a lowercase string in snake_case format, no consecutive underscores, and no leading
+//      digit. For example android_bar_system
+//
+// # package: package to which the flag belongs
+//
+//    format: lowercase strings in snake_case format, delimited by dots, no consecutive underscores
+//      and no leading digit in each string. For example com.android.mypackage is a valid name
+//      while com.android.myPackage, com.android.1mypackage are invalid
+//
+// # container: container as software built in its entirety using the same build environment and
+//    always installed as a single unit
+//
+//    For example the following are all separate containers:
+//        * the system partition
+//        * the vendor partition
+//        * apexes: each APEX is its own container
+//        * APKs: for APKs which are released independently via Play, each APK is its own container.
+//            If an APK is released as part of a Mainline module, or as part of the system partition
+//            via OTA, then they are part of the apex or the system partition container
+//
+//    format: lowercase strings in snake_case format, delimited by dots if multiple, no consecutive
+//      underscores or leading digits in each string. The recommended container values are the
+//      partition names or the module names
 
 // messages used in both aconfig input and output
 
@@ -98,6 +120,7 @@
   repeated flag_declaration flag = 2;
 
   // Container the flag belongs to (optional)
+  // See # container for format detail
   optional string container = 3;
 };
 
@@ -160,6 +183,7 @@
   optional bool is_exported = 10;
 
   // Container the flag belongs to (optional)
+  // See # container for format detail
   optional string container = 11;
 
   // Additional information about the flag, including its purpose and form factors (optional)
diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp
index 6be3c19..2a606bf 100644
--- a/tools/aconfig/aconfig_storage_file/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/Android.bp
@@ -6,10 +6,13 @@
     name: "aconfig_storage_file.defaults",
     edition: "2021",
     lints: "none",
-    srcs: ["src/lib.rs"],
     rustlibs: [
         "libanyhow",
         "libthiserror",
+        "libtempfile",
+        "libprotobuf",
+        "libclap",
+        "libaconfig_storage_protos",
     ],
 }
 
@@ -18,10 +21,41 @@
     crate_name: "aconfig_storage_file",
     host_supported: true,
     defaults: ["aconfig_storage_file.defaults"],
+    srcs: ["src/lib.rs"],
+}
+
+rust_binary_host {
+    name: "aconfig-storage",
+    defaults: ["aconfig_storage_file.defaults"],
+    srcs: ["src/main.rs"],
+    rustlibs: ["libaconfig_storage_file"],
 }
 
 rust_test_host {
     name: "aconfig_storage_file.test",
     test_suites: ["general-tests"],
     defaults: ["aconfig_storage_file.defaults"],
+    srcs: ["src/lib.rs"],
+}
+
+rust_protobuf {
+    name: "libaconfig_storage_protos",
+    protos: ["protos/aconfig_storage_metadata.proto"],
+    crate_name: "aconfig_storage_protos",
+    source_stem: "aconfig_storage_protos",
+    host_supported: true,
+}
+
+cc_library_static {
+    name: "libaconfig_storage_protos_cc",
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    srcs: ["protos/aconfig_storage_metadata.proto"],
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    host_supported: true,
 }
diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml
index c4e2670..641f481 100644
--- a/tools/aconfig/aconfig_storage_file/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_file/Cargo.toml
@@ -9,12 +9,14 @@
 
 [dependencies]
 anyhow = "1.0.69"
-memmap2 = "0.8.0"
 protobuf = "3.2.0"
-once_cell = "1.19.0"
 tempfile = "3.9.0"
-cxx = "1.0"
 thiserror = "1.0.56"
+clap = { version = "4.1.8", features = ["derive"] }
+
+[[bin]]
+name = "aconfig-storage"
+path = "src/main.rs"
 
 [build-dependencies]
 protobuf-codegen = "3.2.0"
diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs
new file mode 100644
index 0000000..1feeb60
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/build.rs
@@ -0,0 +1,17 @@
+use protobuf_codegen::Codegen;
+
+fn main() {
+    let proto_files = vec!["protos/aconfig_storage_metadata.proto"];
+
+    // tell cargo to only re-run the build script if any of the proto files has changed
+    for path in &proto_files {
+        println!("cargo:rerun-if-changed={}", path);
+    }
+
+    Codegen::new()
+        .pure()
+        .include("protos")
+        .inputs(proto_files)
+        .cargo_out_dir("aconfig_storage_protos")
+        .run_from_script();
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/protos/aconfig_storage_metadata.proto b/tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto
similarity index 100%
rename from tools/aconfig/aconfig_storage_read_api/protos/aconfig_storage_metadata.proto
rename to tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_table.rs b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
index 61cf371..d6e5c62 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
@@ -20,9 +20,10 @@
 use crate::AconfigStorageError::{self, BytesParseFail};
 use crate::{get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes};
 use anyhow::anyhow;
+use std::fmt;
 
 /// Flag table header struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct FlagTableHeader {
     pub version: u32,
     pub container: String,
@@ -32,6 +33,23 @@
     pub node_offset: u32,
 }
 
+/// Implement debug print trait for header
+impl fmt::Debug for FlagTableHeader {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "Version: {}, Container: {}, File Size: {}",
+            self.version, self.container, self.file_size
+        )?;
+        writeln!(
+            f,
+            "Num of Flags: {}, Bucket Offset:{}, Node Offset: {}",
+            self.num_flags, self.bucket_offset, self.node_offset
+        )?;
+        Ok(())
+    }
+}
+
 impl FlagTableHeader {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -62,7 +80,7 @@
 }
 
 /// Flag table node struct
-#[derive(PartialEq, Debug, Clone)]
+#[derive(PartialEq, Clone)]
 pub struct FlagTableNode {
     pub package_id: u32,
     pub flag_name: String,
@@ -71,6 +89,18 @@
     pub next_offset: Option<u32>,
 }
 
+/// Implement debug print trait for node
+impl fmt::Debug for FlagTableNode {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "Package Id: {}, Flag: {}, Type: {}, Offset: {}, Next: {:?}",
+            self.package_id, self.flag_name, self.flag_type, self.flag_id, self.next_offset
+        )?;
+        Ok(())
+    }
+}
+
 impl FlagTableNode {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -108,13 +138,28 @@
     }
 }
 
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct FlagTable {
     pub header: FlagTableHeader,
     pub buckets: Vec<Option<u32>>,
     pub nodes: Vec<FlagTableNode>,
 }
 
+/// Implement debug print trait for flag table
+impl fmt::Debug for FlagTable {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Header:")?;
+        write!(f, "{:?}", self.header)?;
+        writeln!(f, "Buckets:")?;
+        writeln!(f, "{:?}", self.buckets)?;
+        writeln!(f, "Nodes:")?;
+        for node in self.nodes.iter() {
+            write!(f, "{:?}", node)?;
+        }
+        Ok(())
+    }
+}
+
 /// Flag table struct
 impl FlagTable {
     /// Serialize to bytes
@@ -156,60 +201,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-
-    impl FlagTableNode {
-        // create test baseline, syntactic sugar
-        fn new_expected(
-            package_id: u32,
-            flag_name: &str,
-            flag_type: u16,
-            flag_id: u16,
-            next_offset: Option<u32>,
-        ) -> Self {
-            Self { package_id, flag_name: flag_name.to_string(), flag_type, flag_id, next_offset }
-        }
-    }
-
-    pub fn create_test_flag_table() -> FlagTable {
-        let header = FlagTableHeader {
-            version: 1234,
-            container: String::from("system"),
-            file_size: 320,
-            num_flags: 8,
-            bucket_offset: 30,
-            node_offset: 98,
-        };
-        let buckets: Vec<Option<u32>> = vec![
-            Some(98),
-            Some(124),
-            None,
-            None,
-            None,
-            Some(177),
-            None,
-            Some(203),
-            None,
-            Some(261),
-            None,
-            None,
-            None,
-            None,
-            None,
-            Some(293),
-            None,
-        ];
-        let nodes = vec![
-            FlagTableNode::new_expected(0, "enabled_ro", 1, 1, None),
-            FlagTableNode::new_expected(0, "enabled_rw", 1, 2, Some(150)),
-            FlagTableNode::new_expected(1, "disabled_ro", 1, 0, None),
-            FlagTableNode::new_expected(2, "enabled_ro", 1, 1, None),
-            FlagTableNode::new_expected(1, "enabled_fixed_ro", 1, 1, Some(235)),
-            FlagTableNode::new_expected(1, "enabled_ro", 1, 2, None),
-            FlagTableNode::new_expected(2, "enabled_fixed_ro", 1, 0, None),
-            FlagTableNode::new_expected(0, "disabled_rw", 1, 0, None),
-        ];
-        FlagTable { header, buckets, nodes }
-    }
+    use crate::test_utils::create_test_flag_table;
 
     #[test]
     // this test point locks down the table serialization
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_value.rs b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
index 62e94ef..021546c 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_value.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
@@ -19,9 +19,10 @@
 
 use crate::AconfigStorageError;
 use crate::{read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes};
+use std::fmt;
 
 /// Flag value header struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct FlagValueHeader {
     pub version: u32,
     pub container: String,
@@ -30,6 +31,23 @@
     pub boolean_value_offset: u32,
 }
 
+/// Implement debug print trait for header
+impl fmt::Debug for FlagValueHeader {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "Version: {}, Container: {}, File Size: {}",
+            self.version, self.container, self.file_size
+        )?;
+        writeln!(
+            f,
+            "Num of Flags: {}, Value Offset:{}",
+            self.num_flags, self.boolean_value_offset
+        )?;
+        Ok(())
+    }
+}
+
 impl FlagValueHeader {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -58,12 +76,23 @@
 }
 
 /// Flag value list struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct FlagValueList {
     pub header: FlagValueHeader,
     pub booleans: Vec<bool>,
 }
 
+/// Implement debug print trait for flag value
+impl fmt::Debug for FlagValueList {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Header:")?;
+        write!(f, "{:?}", self.header)?;
+        writeln!(f, "Values:")?;
+        writeln!(f, "{:?}", self.booleans)?;
+        Ok(())
+    }
+}
+
 impl FlagValueList {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -89,18 +118,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-
-    pub fn create_test_flag_value_list() -> FlagValueList {
-        let header = FlagValueHeader {
-            version: 1234,
-            container: String::from("system"),
-            file_size: 34,
-            num_flags: 8,
-            boolean_value_offset: 26,
-        };
-        let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
-        FlagValueList { header, booleans }
-    }
+    use crate::test_utils::create_test_flag_value_list;
 
     #[test]
     // this test point locks down the value list serialization
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index e06e149..202f6a4 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -35,10 +35,16 @@
 pub mod flag_table;
 pub mod flag_value;
 pub mod package_table;
+pub mod protos;
+
+#[cfg(test)]
+mod test_utils;
 
 use anyhow::anyhow;
 use std::collections::hash_map::DefaultHasher;
+use std::fs::File;
 use std::hash::{Hash, Hasher};
+use std::io::Read;
 
 pub use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
 pub use crate::flag_value::{FlagValueHeader, FlagValueList};
@@ -72,7 +78,9 @@
             "package_map" => Ok(Self::PackageMap),
             "flag_map" => Ok(Self::FlagMap),
             "flag_val" => Ok(Self::FlagVal),
-            _ => Err(anyhow!("Invalid storage file to create")),
+            _ => Err(anyhow!(
+                "Invalid storage file type, valid types are package_map|flag_map|flag_val]"
+            )),
         }
     }
 }
@@ -166,4 +174,88 @@
 
     #[error("invalid storage file byte offset")]
     InvalidStorageFileOffset(#[source] anyhow::Error),
+
+    #[error("failed to create file")]
+    FileCreationFail(#[source] anyhow::Error),
+}
+
+/// Read in storage file as bytes
+pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageError> {
+    let mut file = File::open(file_path).map_err(|errmsg| {
+        AconfigStorageError::FileReadFail(anyhow!("Failed to open file {}: {}", file_path, errmsg))
+    })?;
+    let mut buffer = Vec::new();
+    file.read_to_end(&mut buffer).map_err(|errmsg| {
+        AconfigStorageError::FileReadFail(anyhow!(
+            "Failed to read 4 bytes from file {}: {}",
+            file_path,
+            errmsg
+        ))
+    })?;
+    Ok(buffer)
+}
+
+/// List flag values from storage files
+pub fn list_flags(
+    package_map: &str,
+    flag_map: &str,
+    flag_val: &str,
+) -> Result<Vec<(String, bool)>, AconfigStorageError> {
+    let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?;
+    let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?;
+    let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?;
+
+    let mut package_info = vec![("", 0); package_table.header.num_packages as usize];
+    for node in package_table.nodes.iter() {
+        package_info[node.package_id as usize] = (&node.package_name, node.boolean_offset);
+    }
+
+    let mut flags = Vec::new();
+    for node in flag_table.nodes.iter() {
+        let (package_name, package_offset) = package_info[node.package_id as usize];
+        let full_flag_name = String::from(package_name) + "/" + &node.flag_name;
+        let flag_offset = package_offset + node.flag_id as u32;
+        let flag_value = flag_value_list.booleans[flag_offset as usize];
+        flags.push((full_flag_name, flag_value));
+    }
+
+    flags.sort_by(|v1, v2| v1.0.cmp(&v2.0));
+    Ok(flags)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::test_utils::{
+        create_test_flag_table, create_test_flag_value_list, create_test_package_table,
+        write_bytes_to_temp_file,
+    };
+
+    #[test]
+    // this test point locks down the flag list api
+    fn test_list_flag() {
+        let package_table =
+            write_bytes_to_temp_file(&create_test_package_table().as_bytes()).unwrap();
+        let flag_table = write_bytes_to_temp_file(&create_test_flag_table().as_bytes()).unwrap();
+        let flag_value_list =
+            write_bytes_to_temp_file(&create_test_flag_value_list().as_bytes()).unwrap();
+
+        let package_table_path = package_table.path().display().to_string();
+        let flag_table_path = flag_table.path().display().to_string();
+        let flag_value_list_path = flag_value_list.path().display().to_string();
+
+        let flags =
+            list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap();
+        let expected = [
+            (String::from("com.android.aconfig.storage.test_1/disabled_rw"), false),
+            (String::from("com.android.aconfig.storage.test_1/enabled_ro"), true),
+            (String::from("com.android.aconfig.storage.test_1/enabled_rw"), false),
+            (String::from("com.android.aconfig.storage.test_2/disabled_ro"), false),
+            (String::from("com.android.aconfig.storage.test_2/enabled_fixed_ro"), true),
+            (String::from("com.android.aconfig.storage.test_2/enabled_ro"), true),
+            (String::from("com.android.aconfig.storage.test_4/enabled_fixed_ro"), false),
+            (String::from("com.android.aconfig.storage.test_4/enabled_ro"), true),
+        ];
+        assert_eq!(flags, expected);
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/main.rs b/tools/aconfig/aconfig_storage_file/src/main.rs
new file mode 100644
index 0000000..b5e6158
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/src/main.rs
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+//! `aconfig-storage` is a debugging tool to parse storage files
+
+use aconfig_storage_file::{
+    list_flags, read_file_to_bytes, AconfigStorageError, FlagTable, FlagValueList, PackageTable,
+    StorageFileSelection,
+};
+
+use clap::{builder::ArgAction, Arg, Command};
+
+fn cli() -> Command {
+    Command::new("aconfig-storage")
+        .subcommand_required(true)
+        .subcommand(
+            Command::new("print")
+                .arg(Arg::new("file").long("file").required(true).action(ArgAction::Set))
+                .arg(
+                    Arg::new("type")
+                        .long("type")
+                        .required(true)
+                        .value_parser(|s: &str| StorageFileSelection::try_from(s)),
+                ),
+        )
+        .subcommand(
+            Command::new("list")
+                .arg(
+                    Arg::new("package-map")
+                        .long("package-map")
+                        .required(true)
+                        .action(ArgAction::Set),
+                )
+                .arg(Arg::new("flag-map").long("flag-map").required(true).action(ArgAction::Set))
+                .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set)),
+        )
+}
+
+fn print_storage_file(
+    file_path: &str,
+    file_type: &StorageFileSelection,
+) -> Result<(), AconfigStorageError> {
+    let bytes = read_file_to_bytes(file_path)?;
+    match file_type {
+        StorageFileSelection::PackageMap => {
+            let package_table = PackageTable::from_bytes(&bytes)?;
+            println!("{:?}", package_table);
+        }
+        StorageFileSelection::FlagMap => {
+            let flag_table = FlagTable::from_bytes(&bytes)?;
+            println!("{:?}", flag_table);
+        }
+        StorageFileSelection::FlagVal => {
+            let flag_value = FlagValueList::from_bytes(&bytes)?;
+            println!("{:?}", flag_value);
+        }
+    }
+    Ok(())
+}
+
+fn main() -> Result<(), AconfigStorageError> {
+    let matches = cli().get_matches();
+    match matches.subcommand() {
+        Some(("print", sub_matches)) => {
+            let file_path = sub_matches.get_one::<String>("file").unwrap();
+            let file_type = sub_matches.get_one::<StorageFileSelection>("type").unwrap();
+            print_storage_file(file_path, file_type)?
+        }
+        Some(("list", sub_matches)) => {
+            let package_map = sub_matches.get_one::<String>("package-map").unwrap();
+            let flag_map = sub_matches.get_one::<String>("flag-map").unwrap();
+            let flag_val = sub_matches.get_one::<String>("flag-val").unwrap();
+            let flags = list_flags(package_map, flag_map, flag_val)?;
+            for flag in flags.iter() {
+                println!("{}: {}", flag.0, flag.1);
+            }
+        }
+        _ => unreachable!(),
+    }
+    Ok(())
+}
diff --git a/tools/aconfig/aconfig_storage_file/src/package_table.rs b/tools/aconfig/aconfig_storage_file/src/package_table.rs
index 1c21179..f7435b0 100644
--- a/tools/aconfig/aconfig_storage_file/src/package_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/package_table.rs
@@ -20,9 +20,10 @@
 use crate::AconfigStorageError::{self, BytesParseFail};
 use crate::{get_bucket_index, read_str_from_bytes, read_u32_from_bytes};
 use anyhow::anyhow;
+use std::fmt;
 
 /// Package table header struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct PackageTableHeader {
     pub version: u32,
     pub container: String,
@@ -32,6 +33,23 @@
     pub node_offset: u32,
 }
 
+/// Implement debug print trait for header
+impl fmt::Debug for PackageTableHeader {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "Version: {}, Container: {}, File Size: {}",
+            self.version, self.container, self.file_size
+        )?;
+        writeln!(
+            f,
+            "Num of Packages: {}, Bucket Offset:{}, Node Offset: {}",
+            self.num_packages, self.bucket_offset, self.node_offset
+        )?;
+        Ok(())
+    }
+}
+
 impl PackageTableHeader {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -62,7 +80,7 @@
 }
 
 /// Package table node struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct PackageTableNode {
     pub package_name: String,
     pub package_id: u32,
@@ -72,6 +90,18 @@
     pub next_offset: Option<u32>,
 }
 
+/// Implement debug print trait for node
+impl fmt::Debug for PackageTableNode {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(
+            f,
+            "Package: {}, Id: {}, Offset: {}, Next: {:?}",
+            self.package_name, self.package_id, self.boolean_offset, self.next_offset
+        )?;
+        Ok(())
+    }
+}
+
 impl PackageTableNode {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -109,13 +139,28 @@
 }
 
 /// Package table struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
 pub struct PackageTable {
     pub header: PackageTableHeader,
     pub buckets: Vec<Option<u32>>,
     pub nodes: Vec<PackageTableNode>,
 }
 
+/// Implement debug print trait for package table
+impl fmt::Debug for PackageTable {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        writeln!(f, "Header:")?;
+        write!(f, "{:?}", self.header)?;
+        writeln!(f, "Buckets:")?;
+        writeln!(f, "{:?}", self.buckets)?;
+        writeln!(f, "Nodes:")?;
+        for node in self.nodes.iter() {
+            write!(f, "{:?}", node)?;
+        }
+        Ok(())
+    }
+}
+
 impl PackageTable {
     /// Serialize to bytes
     pub fn as_bytes(&self) -> Vec<u8> {
@@ -156,38 +201,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-
-    pub fn create_test_package_table() -> PackageTable {
-        let header = PackageTableHeader {
-            version: 1234,
-            container: String::from("system"),
-            file_size: 208,
-            num_packages: 3,
-            bucket_offset: 30,
-            node_offset: 58,
-        };
-        let buckets: Vec<Option<u32>> = vec![Some(58), None, None, Some(108), None, None, None];
-        let first_node = PackageTableNode {
-            package_name: String::from("com.android.aconfig.storage.test_2"),
-            package_id: 1,
-            boolean_offset: 3,
-            next_offset: None,
-        };
-        let second_node = PackageTableNode {
-            package_name: String::from("com.android.aconfig.storage.test_1"),
-            package_id: 0,
-            boolean_offset: 0,
-            next_offset: Some(158),
-        };
-        let third_node = PackageTableNode {
-            package_name: String::from("com.android.aconfig.storage.test_4"),
-            package_id: 2,
-            boolean_offset: 6,
-            next_offset: None,
-        };
-        let nodes = vec![first_node, second_node, third_node];
-        PackageTable { header, buckets, nodes }
-    }
+    use crate::test_utils::create_test_package_table;
 
     #[test]
     // this test point locks down the table serialization
diff --git a/tools/aconfig/aconfig_storage_read_api/src/protos.rs b/tools/aconfig/aconfig_storage_file/src/protos.rs
similarity index 78%
rename from tools/aconfig/aconfig_storage_read_api/src/protos.rs
rename to tools/aconfig/aconfig_storage_file/src/protos.rs
index 37df3e1..8b86205 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/protos.rs
+++ b/tools/aconfig/aconfig_storage_file/src/protos.rs
@@ -49,8 +49,11 @@
 pub use auto_generated::*;
 
 use anyhow::Result;
+use protobuf::Message;
+use std::io::Write;
+use tempfile::NamedTempFile;
 
-pub mod storage_files {
+pub mod storage_record_pb {
     use super::*;
     use anyhow::ensure;
 
@@ -80,15 +83,28 @@
         }
         Ok(())
     }
+
+    pub fn get_binary_proto_from_text_proto(text_proto: &str) -> Result<Vec<u8>> {
+        let storage_files: ProtoStorageFiles = protobuf::text_format::parse_from_str(text_proto)?;
+        let mut binary_proto = Vec::new();
+        storage_files.write_to_vec(&mut binary_proto)?;
+        Ok(binary_proto)
+    }
+
+    pub fn write_proto_to_temp_file(text_proto: &str) -> Result<NamedTempFile> {
+        let bytes = get_binary_proto_from_text_proto(text_proto).unwrap();
+        let mut file = NamedTempFile::new()?;
+        let _ = file.write_all(&bytes);
+        Ok(file)
+    }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::get_binary_storage_proto_bytes;
 
     #[test]
-    fn test_parse_storage_files() {
+    fn test_parse_storage_record_pb() {
         let text_proto = r#"
 files {
     version: 0
@@ -107,8 +123,9 @@
     timestamp: 54321
 }
 "#;
-        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
-        let storage_files = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap();
+        let binary_proto_bytes =
+            storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+        let storage_files = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap();
         assert_eq!(storage_files.files.len(), 2);
         let system_file = &storage_files.files[0];
         assert_eq!(system_file.version(), 0);
@@ -127,7 +144,7 @@
     }
 
     #[test]
-    fn test_parse_invalid_storage_files() {
+    fn test_parse_invalid_storage_record_pb() {
         let text_proto = r#"
 files {
     version: 0
@@ -138,8 +155,9 @@
     timestamp: 12345
 }
 "#;
-        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
-        let err = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
+        let binary_proto_bytes =
+            storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+        let err = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
         assert_eq!(
             format!("{:?}", err),
             "invalid storage file record: missing package map file for container system"
@@ -155,8 +173,9 @@
     timestamp: 12345
 }
 "#;
-        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
-        let err = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
+        let binary_proto_bytes =
+            storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+        let err = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
         assert_eq!(
             format!("{:?}", err),
             "invalid storage file record: missing flag map file for container system"
@@ -172,8 +191,9 @@
     timestamp: 12345
 }
 "#;
-        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
-        let err = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
+        let binary_proto_bytes =
+            storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+        let err = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
         assert_eq!(
             format!("{:?}", err),
             "invalid storage file record: missing flag val file for container system"
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
new file mode 100644
index 0000000..7780044
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
+use crate::flag_value::{FlagValueHeader, FlagValueList};
+use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
+use crate::AconfigStorageError;
+
+use anyhow::anyhow;
+use std::io::Write;
+use tempfile::NamedTempFile;
+
+pub(crate) fn create_test_package_table() -> PackageTable {
+    let header = PackageTableHeader {
+        version: 1234,
+        container: String::from("system"),
+        file_size: 208,
+        num_packages: 3,
+        bucket_offset: 30,
+        node_offset: 58,
+    };
+    let buckets: Vec<Option<u32>> = vec![Some(58), None, None, Some(108), None, None, None];
+    let first_node = PackageTableNode {
+        package_name: String::from("com.android.aconfig.storage.test_2"),
+        package_id: 1,
+        boolean_offset: 3,
+        next_offset: None,
+    };
+    let second_node = PackageTableNode {
+        package_name: String::from("com.android.aconfig.storage.test_1"),
+        package_id: 0,
+        boolean_offset: 0,
+        next_offset: Some(158),
+    };
+    let third_node = PackageTableNode {
+        package_name: String::from("com.android.aconfig.storage.test_4"),
+        package_id: 2,
+        boolean_offset: 6,
+        next_offset: None,
+    };
+    let nodes = vec![first_node, second_node, third_node];
+    PackageTable { header, buckets, nodes }
+}
+
+impl FlagTableNode {
+    // create test baseline, syntactic sugar
+    fn new_expected(
+        package_id: u32,
+        flag_name: &str,
+        flag_type: u16,
+        flag_id: u16,
+        next_offset: Option<u32>,
+    ) -> Self {
+        Self { package_id, flag_name: flag_name.to_string(), flag_type, flag_id, next_offset }
+    }
+}
+
+pub(crate) fn create_test_flag_table() -> FlagTable {
+    let header = FlagTableHeader {
+        version: 1234,
+        container: String::from("system"),
+        file_size: 320,
+        num_flags: 8,
+        bucket_offset: 30,
+        node_offset: 98,
+    };
+    let buckets: Vec<Option<u32>> = vec![
+        Some(98),
+        Some(124),
+        None,
+        None,
+        None,
+        Some(177),
+        None,
+        Some(203),
+        None,
+        Some(261),
+        None,
+        None,
+        None,
+        None,
+        None,
+        Some(293),
+        None,
+    ];
+    let nodes = vec![
+        FlagTableNode::new_expected(0, "enabled_ro", 1, 1, None),
+        FlagTableNode::new_expected(0, "enabled_rw", 1, 2, Some(150)),
+        FlagTableNode::new_expected(1, "disabled_ro", 1, 0, None),
+        FlagTableNode::new_expected(2, "enabled_ro", 1, 1, None),
+        FlagTableNode::new_expected(1, "enabled_fixed_ro", 1, 1, Some(235)),
+        FlagTableNode::new_expected(1, "enabled_ro", 1, 2, None),
+        FlagTableNode::new_expected(2, "enabled_fixed_ro", 1, 0, None),
+        FlagTableNode::new_expected(0, "disabled_rw", 1, 0, None),
+    ];
+    FlagTable { header, buckets, nodes }
+}
+
+pub(crate) fn create_test_flag_value_list() -> FlagValueList {
+    let header = FlagValueHeader {
+        version: 1234,
+        container: String::from("system"),
+        file_size: 34,
+        num_flags: 8,
+        boolean_value_offset: 26,
+    };
+    let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
+    FlagValueList { header, booleans }
+}
+
+pub(crate) fn write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile, AconfigStorageError> {
+    let mut file = NamedTempFile::new().map_err(|_| {
+        AconfigStorageError::FileCreationFail(anyhow!("Failed to create temp file"))
+    })?;
+    let _ = file.write_all(&bytes);
+    Ok(file)
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 5f4329c..721f9a5 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -9,9 +9,7 @@
     srcs: ["src/lib.rs"],
     rustlibs: [
         "libanyhow",
-        "libaconfig_storage_protos",
         "libonce_cell",
-        "libprotobuf",
         "libtempfile",
         "libmemmap2",
         "libcxx",
@@ -38,28 +36,6 @@
     ],
 }
 
-rust_protobuf {
-    name: "libaconfig_storage_protos",
-    protos: ["protos/aconfig_storage_metadata.proto"],
-    crate_name: "aconfig_storage_protos",
-    source_stem: "aconfig_storage_protos",
-    host_supported: true,
-}
-
-cc_library_static {
-    name: "libaconfig_storage_protos_cc",
-    proto: {
-        export_proto_headers: true,
-        type: "lite",
-    },
-    srcs: ["protos/aconfig_storage_metadata.proto"],
-    apex_available: [
-        "//apex_available:platform",
-        "//apex_available:anyapex",
-    ],
-    host_supported: true,
-}
-
 // cxx source codegen from rust api
 genrule {
     name: "libcxx_aconfig_storage_read_api_bridge_code",
diff --git a/tools/aconfig/aconfig_storage_read_api/Cargo.toml b/tools/aconfig/aconfig_storage_read_api/Cargo.toml
index 4c65d40..30a4298 100644
--- a/tools/aconfig/aconfig_storage_read_api/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_read_api/Cargo.toml
@@ -10,7 +10,6 @@
 [dependencies]
 anyhow = "1.0.69"
 memmap2 = "0.8.0"
-protobuf = "3.2.0"
 once_cell = "1.19.0"
 tempfile = "3.9.0"
 cxx = "1.0"
diff --git a/tools/aconfig/aconfig_storage_read_api/build.rs b/tools/aconfig/aconfig_storage_read_api/build.rs
index 894b71c..7b1aa53 100644
--- a/tools/aconfig/aconfig_storage_read_api/build.rs
+++ b/tools/aconfig/aconfig_storage_read_api/build.rs
@@ -1,20 +1,4 @@
-use protobuf_codegen::Codegen;
-
 fn main() {
-    let proto_files = vec!["protos/aconfig_storage_metadata.proto"];
-
-    // tell cargo to only re-run the build script if any of the proto files has changed
-    for path in &proto_files {
-        println!("cargo:rerun-if-changed={}", path);
-    }
-
-    Codegen::new()
-        .pure()
-        .include("protos")
-        .inputs(proto_files)
-        .cargo_out_dir("aconfig_storage_protos")
-        .run_from_script();
-
     let _ = cxx_build::bridge("src/lib.rs");
     println!("cargo:rerun-if-changed=src/lib.rs");
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index 0da81dd..3958b2e 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -38,14 +38,13 @@
 pub mod flag_value_query;
 pub mod mapped_file;
 pub mod package_table_query;
-pub mod protos;
 
 #[cfg(test)]
 mod test_utils;
 
-pub use crate::protos::ProtoStorageFiles;
 pub use aconfig_storage_file::{
-    read_u32_from_bytes, AconfigStorageError, StorageFileSelection, FILE_VERSION,
+    protos::ProtoStorageFiles, read_u32_from_bytes, AconfigStorageError, StorageFileSelection,
+    FILE_VERSION,
 };
 pub use flag_table_query::FlagOffset;
 pub use package_table_query::PackageOffset;
@@ -380,7 +379,8 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::{write_storage_text_to_temp_file, TestStorageFileSet};
+    use crate::test_utils::TestStorageFileSet;
+    use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
 
     fn create_test_storage_files(read_only: bool) -> TestStorageFileSet {
         TestStorageFileSet::new(
@@ -410,7 +410,7 @@
             ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let package_offset = get_package_offset_impl(
             &file_full_path,
@@ -461,7 +461,7 @@
             ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let baseline = vec![
             (0, "enabled_ro", 1u16),
@@ -500,7 +500,7 @@
             ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let baseline: Vec<bool> = vec![false; 8];
         for (offset, expected_value) in baseline.into_iter().enumerate() {
diff --git a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
index d8f2570..e94c56f 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
@@ -23,13 +23,13 @@
 use memmap2::Mmap;
 use once_cell::sync::Lazy;
 
-use crate::protos::{
-    storage_files::try_from_binary_proto, ProtoStorageFileInfo, ProtoStorageFiles,
-};
 use crate::AconfigStorageError::{
     self, FileReadFail, MapFileFail, ProtobufParseFail, StorageFileNotFound,
 };
 use crate::StorageFileSelection;
+use aconfig_storage_file::protos::{
+    storage_record_pb::try_from_binary_proto, ProtoStorageFileInfo, ProtoStorageFiles,
+};
 
 /// Cache for already mapped files
 static ALL_MAPPED_FILES: Lazy<Mutex<HashMap<String, MappedStorageFileSet>>> = Lazy::new(|| {
@@ -148,7 +148,8 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::{write_storage_text_to_temp_file, TestStorageFileSet};
+    use crate::test_utils::TestStorageFileSet;
+    use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
 
     #[test]
     fn test_find_storage_file_location() {
@@ -170,7 +171,7 @@
     timestamp: 54321
 }
 "#;
-        let file = write_storage_text_to_temp_file(text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let file_info = find_container_storage_location(&file_full_path, "system").unwrap();
         assert_eq!(file_info.version(), 0);
@@ -235,7 +236,7 @@
             ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         map_and_verify(
             &file_full_path,
@@ -264,7 +265,7 @@
             rw_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
         assert_eq!(
@@ -289,7 +290,7 @@
             ro_files.package_map.name, rw_files.flag_map.name, ro_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
         assert_eq!(
@@ -314,7 +315,7 @@
             ro_files.package_map.name, ro_files.flag_map.name, rw_files.flag_val.name
         );
 
-        let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+        let file = write_proto_to_temp_file(&text_proto).unwrap();
         let file_full_path = file.path().display().to_string();
         let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
         assert_eq!(
diff --git a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs b/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
index 588ecba..cc5938d 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
@@ -14,27 +14,10 @@
  * limitations under the License.
  */
 
-use crate::protos::ProtoStorageFiles;
 use anyhow::Result;
-use protobuf::Message;
 use std::fs;
-use std::io::Write;
 use tempfile::NamedTempFile;
 
-pub(crate) fn get_binary_storage_proto_bytes(text_proto: &str) -> Result<Vec<u8>> {
-    let storage_files: ProtoStorageFiles = protobuf::text_format::parse_from_str(text_proto)?;
-    let mut binary_proto = Vec::new();
-    storage_files.write_to_vec(&mut binary_proto)?;
-    Ok(binary_proto)
-}
-
-pub(crate) fn write_storage_text_to_temp_file(text_proto: &str) -> Result<NamedTempFile> {
-    let bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
-    let mut file = NamedTempFile::new()?;
-    let _ = file.write_all(&bytes);
-    Ok(file)
-}
-
 fn set_file_read_only(file: &NamedTempFile) {
     let mut perms = fs::metadata(file.path()).unwrap().permissions();
     if !perms.readonly() {
diff --git a/tools/aconfig/aflags/src/device_config_source.rs b/tools/aconfig/aflags/src/device_config_source.rs
index 1cea6ed..2589f3d 100644
--- a/tools/aconfig/aflags/src/device_config_source.rs
+++ b/tools/aconfig/aflags/src/device_config_source.rs
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-use crate::{Flag, FlagPermission, FlagSource, ValuePickedFrom};
+use crate::{Flag, FlagPermission, FlagSource, FlagValue, ValuePickedFrom};
 use aconfig_protos::ProtoFlagPermission as ProtoPermission;
 use aconfig_protos::ProtoFlagState as ProtoState;
 use aconfig_protos::ProtoParsedFlag;
@@ -40,10 +40,9 @@
     };
 
     let value = match flag.state() {
-        ProtoState::ENABLED => "true",
-        ProtoState::DISABLED => "false",
-    }
-    .to_string();
+        ProtoState::ENABLED => FlagValue::Enabled,
+        ProtoState::DISABLED => FlagValue::Disabled,
+    };
 
     let permission = match flag.permission() {
         ProtoPermission::READ_ONLY => FlagPermission::ReadOnly,
@@ -86,14 +85,16 @@
     Ok(flags.values().cloned().collect())
 }
 
-fn parse_device_config(raw: &str) -> Result<HashMap<String, String>> {
+fn parse_device_config(raw: &str) -> Result<HashMap<String, FlagValue>> {
     let mut flags = HashMap::new();
     let regex = Regex::new(r"(?m)^([[[:alnum:]]_]+/[[[:alnum:]]_\.]+)=(true|false)$")?;
     for capture in regex.captures_iter(raw) {
         let key =
             capture.get(1).ok_or(anyhow!("invalid device_config output"))?.as_str().to_string();
-        let value = capture.get(2).ok_or(anyhow!("invalid device_config output"))?.as_str();
-        flags.insert(key, value.to_string());
+        let value = FlagValue::try_from(
+            capture.get(2).ok_or(anyhow!("invalid device_config output"))?.as_str(),
+        )?;
+        flags.insert(key, value);
     }
     Ok(flags)
 }
@@ -112,24 +113,24 @@
     Ok(str::from_utf8(&output.stdout)?.to_string())
 }
 
-fn read_device_config_flags() -> Result<HashMap<String, String>> {
+fn read_device_config_flags() -> Result<HashMap<String, FlagValue>> {
     let list_output = read_device_config_output(&["list"])?;
     parse_device_config(&list_output)
 }
 
-fn reconcile(pb_flags: &[Flag], dc_flags: HashMap<String, String>) -> Vec<Flag> {
+fn reconcile(pb_flags: &[Flag], dc_flags: HashMap<String, FlagValue>) -> Vec<Flag> {
     pb_flags
         .iter()
         .map(|f| {
             dc_flags
                 .get(&format!("{}/{}.{}", f.namespace, f.package, f.name))
                 .map(|value| {
-                    if value.eq(&f.value) {
+                    if *value == f.value {
                         Flag { value_picked_from: ValuePickedFrom::Default, ..f.clone() }
                     } else {
                         Flag {
                             value_picked_from: ValuePickedFrom::Server,
-                            value: value.to_string(),
+                            value: *value,
                             ..f.clone()
                         }
                     }
@@ -167,9 +168,9 @@
 namespace_two/android.flag_two=nonsense
 "#;
         let expected = HashMap::from([
-            ("namespace_one/com.foo.bar.flag_one".to_string(), "true".to_string()),
-            ("namespace_one/com.foo.bar.flag_two".to_string(), "false".to_string()),
-            ("namespace_two/android.flag_one".to_string(), "true".to_string()),
+            ("namespace_one/com.foo.bar.flag_one".to_string(), FlagValue::Enabled),
+            ("namespace_one/com.foo.bar.flag_two".to_string(), FlagValue::Disabled),
+            ("namespace_two/android.flag_one".to_string(), FlagValue::Enabled),
         ]);
         let actual = parse_device_config(input).unwrap();
         assert_eq!(expected, actual);
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
index 037bbd0..febd567 100644
--- a/tools/aconfig/aflags/src/main.rs
+++ b/tools/aconfig/aflags/src/main.rs
@@ -52,13 +52,40 @@
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+enum FlagValue {
+    Enabled,
+    Disabled,
+}
+
+impl TryFrom<&str> for FlagValue {
+    type Error = anyhow::Error;
+
+    fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
+        match value {
+            "true" | "enabled" => Ok(Self::Enabled),
+            "false" | "disabled" => Ok(Self::Disabled),
+            _ => Err(anyhow!("cannot convert string '{}' to FlagValue", value)),
+        }
+    }
+}
+
+impl ToString for FlagValue {
+    fn to_string(&self) -> String {
+        match &self {
+            Self::Enabled => "enabled".into(),
+            Self::Disabled => "disabled".into(),
+        }
+    }
+}
+
 #[derive(Clone)]
 struct Flag {
     namespace: String,
     name: String,
     package: String,
     container: String,
-    value: String,
+    value: FlagValue,
     permission: FlagPermission,
     value_picked_from: ValuePickedFrom,
 }
@@ -116,32 +143,28 @@
 }
 
 struct PaddingInfo {
-    longest_package_col: usize,
-    longest_name_col: usize,
+    longest_flag_col: usize,
     longest_val_col: usize,
     longest_value_picked_from_col: usize,
     longest_permission_col: usize,
 }
 
 fn format_flag_row(flag: &Flag, info: &PaddingInfo) -> String {
-    let pkg = &flag.package;
-    let p0 = info.longest_package_col + 1;
-
-    let name = &flag.name;
-    let p1 = info.longest_name_col + 1;
+    let full_name = flag.qualified_name();
+    let p0 = info.longest_flag_col + 1;
 
     let val = flag.value.to_string();
-    let p2 = info.longest_val_col + 1;
+    let p1 = info.longest_val_col + 1;
 
     let value_picked_from = flag.value_picked_from.to_string();
-    let p3 = info.longest_value_picked_from_col + 1;
+    let p2 = info.longest_value_picked_from_col + 1;
 
     let perm = flag.permission.to_string();
-    let p4 = info.longest_permission_col + 1;
+    let p3 = info.longest_permission_col + 1;
 
     let container = &flag.container;
 
-    format!("{pkg:p0$}{name:p1$}{val:p2$}{value_picked_from:p3$}{perm:p4$}{container}\n")
+    format!("{full_name:p0$}{val:p1$}{value_picked_from:p2$}{perm:p3$}{container}\n")
 }
 
 fn set_flag(qualified_name: &str, value: &str) -> Result<()> {
@@ -163,8 +186,7 @@
 fn list() -> Result<String> {
     let flags = DeviceConfigSource::list_flags()?;
     let padding_info = PaddingInfo {
-        longest_package_col: flags.iter().map(|f| f.package.len()).max().unwrap_or(0),
-        longest_name_col: flags.iter().map(|f| f.name.len()).max().unwrap_or(0),
+        longest_flag_col: flags.iter().map(|f| f.qualified_name().len()).max().unwrap_or(0),
         longest_val_col: flags.iter().map(|f| f.value.to_string().len()).max().unwrap_or(0),
         longest_value_picked_from_col: flags
             .iter()
diff --git a/tools/finalization/finalize-aidl-vndk-sdk-resources.sh b/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
index 37c0011..671b036 100755
--- a/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
+++ b/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
@@ -69,6 +69,33 @@
     rm "$tmpfile"
 }
 
+function bumpSdkExtensionsVersion() {
+    local SDKEXT="packages/modules/SdkExtensions/"
+
+    # This used to call bump_sdk.sh utility.
+    # However due to TS, we have to build the gen_sdk with a correct set of settings.
+
+    # "$top/packages/modules/SdkExtensions/gen_sdk/bump_sdk.sh" ${FINAL_MAINLINE_EXTENSION}
+    # Leave the last commit as a set of modified files.
+    # The code to create a finalization topic will pick it up later.
+    # git -C ${SDKEXT} reset HEAD~1
+
+    local sdk="${FINAL_MAINLINE_EXTENSION}"
+    local modules_arg=
+
+    TARGET_PRODUCT=aosp_arm64 \
+        TARGET_RELEASE=fina_1 \
+        TARGET_BUILD_VARIANT=userdebug \
+        DIST_DIR=out/dist \
+        $top/build/soong/soong_ui.bash --make-mode --soong-only gen_sdk
+
+    ANDROID_BUILD_TOP="$top" out/soong/host/linux-x86/bin/gen_sdk \
+        --database ${SDKEXT}/gen_sdk/extensions_db.textpb \
+        --action new_sdk \
+        --sdk "$sdk" \
+        $modules_arg
+}
+
 function finalize_aidl_vndk_sdk_resources() {
     local top="$(dirname "$0")"/../../../..
     source $top/build/make/tools/finalization/environment.sh
@@ -76,9 +103,6 @@
     local SDK_CODENAME="public static final int $FINAL_PLATFORM_CODENAME_JAVA = CUR_DEVELOPMENT;"
     local SDK_VERSION="public static final int $FINAL_PLATFORM_CODENAME_JAVA = $FINAL_PLATFORM_SDK_VERSION;"
 
-    # default target to modify tree and build SDK
-    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
-
     # The full process can be found at (INTERNAL) go/android-sdk-finalization.
 
     # apply droidstubs hack to prevent tools from incrementing an API version
@@ -87,20 +111,12 @@
     # bionic/NDK
     finalize_bionic_ndk
 
-    # VNDK definitions for new SDK version
-    cp "$top/development/vndk/tools/definition-tool/datasets/vndk-lib-extra-list-current.txt" \
-       "$top/development/vndk/tools/definition-tool/datasets/vndk-lib-extra-list-$FINAL_PLATFORM_SDK_VERSION.txt"
+    # pre-finalization build target (trunk)
+    local aidl_m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=trunk TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
+    AIDL_TRANSITIVE_FREEZE=true $aidl_m aidl-freeze-api
 
-    AIDL_TRANSITIVE_FREEZE=true $m aidl-freeze-api create_reference_dumps
-
-    # Generate ABI dumps
-    ANDROID_BUILD_TOP="$top" out/host/linux-x86/bin/create_reference_dumps
-
-    echo "NOTE: THIS INTENTIONALLY MAY FAIL AND REPAIR ITSELF (until 'DONE')"
-    # Update new versions of files. See update-vndk-list.sh (which requires envsetup.sh)
-    $m check-vndk-list || \
-        { cp $top/out/soong/vndk/vndk.libraries.txt $top/build/make/target/product/gsi/current.txt; }
-    echo "DONE: THIS INTENTIONALLY MAY FAIL AND REPAIR ITSELF"
+    # TODO(b/309880485)
+    # Add back create_reference_dumps and $top/build/make/target/product/gsi/current.txt
 
     # Finalize SDK
 
@@ -114,9 +130,6 @@
     sed -i -e 's/Pkg\.Revision.*/Pkg\.Revision=${PLATFORM_SDK_VERSION}.0.0/g' $build_tools_source
 
     # build/make
-    local version_defaults="$top/build/make/core/version_defaults.mk"
-    sed -i -e "s/PLATFORM_SDK_VERSION := .*/PLATFORM_SDK_VERSION := ${FINAL_PLATFORM_SDK_VERSION}/g" $version_defaults
-    sed -i -e "s/PLATFORM_VERSION_LAST_STABLE := .*/PLATFORM_VERSION_LAST_STABLE := ${FINAL_PLATFORM_VERSION}/g" $version_defaults
     sed -i -e "s/sepolicy_major_vers := .*/sepolicy_major_vers := ${FINAL_PLATFORM_SDK_VERSION}/g" "$top/build/make/core/config.mk"
     cp "$top/build/make/target/product/gsi/current.txt" "$top/build/make/target/product/gsi/$FINAL_PLATFORM_SDK_VERSION.txt"
 
@@ -156,18 +169,14 @@
     sed -i -e "/=.*$((${FINAL_PLATFORM_SDK_VERSION}-1)),/a \\  SDK_${FINAL_PLATFORM_CODENAME_JAVA} = ${FINAL_PLATFORM_SDK_VERSION}," "$top/frameworks/base/tools/aapt2/SdkConstants.h"
 
     # Bump Mainline SDK extension version.
-    local SDKEXT="packages/modules/SdkExtensions/"
-    "$top/packages/modules/SdkExtensions/gen_sdk/bump_sdk.sh" ${FINAL_MAINLINE_EXTENSION}
-    # Leave the last commit as a set of modified files.
-    # The code to create a finalization topic will pick it up later.
-    git -C ${SDKEXT} reset HEAD~1
+    bumpSdkExtensionsVersion
 
-    local version_defaults="$top/build/make/core/version_defaults.mk"
-    sed -i -e "s/PLATFORM_SDK_EXTENSION_VERSION := .*/PLATFORM_SDK_EXTENSION_VERSION := ${FINAL_MAINLINE_EXTENSION}/g" $version_defaults
+    # target to build SDK
+    local sdk_m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
 
     # Force update current.txt
-    $m clobber
-    $m update-api
+    $sdk_m clobber
+    $sdk_m update-api
 }
 
 finalize_aidl_vndk_sdk_resources
diff --git a/tools/finalization/finalize-sdk-rel.sh b/tools/finalization/finalize-sdk-rel.sh
index d4ed380..245305b 100755
--- a/tools/finalization/finalize-sdk-rel.sh
+++ b/tools/finalization/finalize-sdk-rel.sh
@@ -33,10 +33,6 @@
     # in REL mode, resources would correctly set the resources_sdk_int, no fix required
     revert_resources_sdk_int_fix
 
-    # build/make/core/version_defaults.mk
-    # Mark all versions "released".
-    sed -i 's/\(PLATFORM_VERSION_CODENAME\.[^[:space:]]*\) := [^[:space:]]*/\1 := REL/g' "$top/build/make/core/version_defaults.mk"
-
     # cts
     echo "$FINAL_PLATFORM_VERSION" > "$top/cts/tests/tests/os/assets/platform_versions.txt"
     if [ "$FINAL_PLATFORM_CODENAME" != "$CURRENT_PLATFORM_CODENAME" ]; then
@@ -47,18 +43,19 @@
     # system/sepolicy
     system/sepolicy/tools/finalize-sdk-rel.sh "$top" "$FINAL_PLATFORM_SDK_VERSION"
 
-    # prebuilts/abi-dumps/ndk
-    mkdir -p "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION"
-    cp -r "$top/prebuilts/abi-dumps/ndk/current/64/" "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION/"
-
     # prebuilts/abi-dumps/platform
     mkdir -p "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION"
     cp -r "$top/prebuilts/abi-dumps/platform/current/64/" "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION/"
 
-    if [ "$FINAL_STATE" != "sdk" ] || [ "$FINAL_PLATFORM_CODENAME" == "$CURRENT_PLATFORM_CODENAME" ] ; then
+    # TODO(b/309880485)
+    # uncomment and update
+    # prebuilts/abi-dumps/ndk
+    #mkdir -p "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION"
+    #cp -r "$top/prebuilts/abi-dumps/ndk/current/64/" "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION/"
+    #if [ "$FINAL_STATE" != "sdk" ] || [ "$FINAL_PLATFORM_CODENAME" == "$CURRENT_PLATFORM_CODENAME" ] ; then
         # prebuilts/abi-dumps/vndk
-        mv "$top/prebuilts/abi-dumps/vndk/$CURRENT_PLATFORM_CODENAME" "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_SDK_VERSION"
-    fi;
+        #mv "$top/prebuilts/abi-dumps/vndk/$CURRENT_PLATFORM_CODENAME" "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_SDK_VERSION"
+    #fi;
 }
 
 finalize_sdk_rel
diff --git a/tools/finalization/localonly-steps.sh b/tools/finalization/localonly-steps.sh
index 7318ca1..bebd563 100755
--- a/tools/finalization/localonly-steps.sh
+++ b/tools/finalization/localonly-steps.sh
@@ -7,17 +7,17 @@
     source $top/build/make/tools/finalization/environment.sh
 
     # default target to modify tree and build SDK
-    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
+    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
 
     # adb keys
     $m adb
     LOGNAME=android-eng HOSTNAME=google.com "$top/out/host/linux-x86/bin/adb" keygen "$top/vendor/google/security/adb/${FINAL_PLATFORM_VERSION}.adb_key"
 
     # Build Platform SDKs.
-    $top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=sdk TARGET_BUILD_VARIANT=userdebug sdk dist sdk_repo DIST_DIR=out/dist
+    $top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=sdk TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug sdk dist sdk_repo DIST_DIR=out/dist
 
     # Build Modules SDKs.
-    TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true DIST_DIR=out/dist "$top/vendor/google/build/mainline_modules_sdks.sh" --build-release=latest
+    TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true DIST_DIR=out/dist "$top/vendor/google/build/mainline_modules_sdks.sh" --build-release=latest
 
     # Update prebuilts.
     "$top/prebuilts/build-tools/path/linux-x86/python3" -W ignore::DeprecationWarning "$top/prebuilts/sdk/update_prebuilts.py" --local_mode -f ${FINAL_PLATFORM_SDK_VERSION} -e ${FINAL_MAINLINE_EXTENSION} --bug 1 1
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index d31f87e..b8dcd84 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -215,7 +215,7 @@
 
   This simulates how apexd activates APEXes.
   1. create {inp}/APEX which is treated as a "/apex" on device.
-  2. invoke apexd_host with vendor APEXes.
+  2. invoke apexd_host with APEXes.
   """
 
   apex_dir = common.MakeTempDir('APEX')
@@ -225,12 +225,13 @@
   # Always create /apex directory for dirmap
   os.makedirs(apex_dir, exist_ok=True)
 
-  # Invoke apexd_host to activate vendor APEXes for checkvintf
+  # Invoke apexd_host to activate APEXes for checkvintf
   apex_host = os.path.join(OPTIONS.search_path, 'bin', 'apexd_host')
   cmd = [apex_host, '--tool_path', OPTIONS.search_path]
   cmd += ['--apex_path', dirmap['/apex']]
-  if '/vendor' in dirmap:
-      cmd += ['--vendor_path', dirmap['/vendor']]
+  for p in ['system', 'system_ext', 'product', 'vendor']:
+    if '/' + p in dirmap:
+      cmd += ['--' + p + '_path', dirmap['/' + p]]
   common.RunAndCheckOutput(cmd)