Merge "Move product_packages.txt to soong" into main
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index 88630ba..7602c64 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -35,7 +35,7 @@
 LOG_PATH = 'logs/build_test_suites.log'
 # Currently, this prevents the removal of those tags when they exist. In the future we likely
 # want the script to supply 'dist directly
-REQUIRED_BUILD_TARGETS = frozenset(['dist', 'droid'])
+REQUIRED_BUILD_TARGETS = frozenset(['dist', 'droid', 'checkbuild'])
 
 
 class Error(Exception):
@@ -166,13 +166,15 @@
           if re.search(regex, opt):
             get_metrics_agent().report_unoptimized_target(target, 'Test artifact used.')
             build_targets.add(target)
-            continue
+            # proceed to next target evaluation
+            break
           get_metrics_agent().report_optimized_target(target)
         except Exception as e:
           # In case of exception report as unoptimized
           build_targets.add(target)
           get_metrics_agent().report_unoptimized_target(target, f'Error in parsing test discovery output for {target}: {repr(e)}')
           logging.error(f'unable to parse test discovery output: {repr(e)}')
+          break
 
     return build_targets
 
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index f17d8c6..95c0736 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -82,6 +82,7 @@
 $(call soong_config_set_bool,chre,chre_dedicated_transport_channel_enabled,$(if $(filter true,$(CHRE_DEDICATED_TRANSPORT_CHANNEL_ENABLED)),true,false))
 $(call soong_config_set_bool,chre,chre_log_atom_extension_enabled,$(if $(filter true,$(CHRE_LOG_ATOM_EXTENSION_ENABLED)),true,false))
 $(call soong_config_set_bool,chre,building_vendor_image,$(if $(filter true,$(BUILDING_VENDOR_IMAGE)),true,false))
+$(call soong_config_set_bool,chre,chre_usf_daemon_enabled,$(if $(filter true,$(CHRE_USF_DAEMON_ENABLED)),true,false))
 
 ifdef TARGET_BOARD_AUTO
   $(call add_soong_config_var_value, ANDROID, target_board_auto, $(TARGET_BOARD_AUTO))
diff --git a/core/config.mk b/core/config.mk
index 20ebeeb..454c0e5 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1333,3 +1333,58 @@
 $(error SYSTEM_OPTIMIZE_JAVA must be enabled when FULL_SYSTEM_OPTIMIZE_JAVA is enabled)
 endif
 endif
+
+# -----------------------------------------------------------------
+# Define fingerprint, thumbprint, and version tags for the current build
+#
+# BUILD_VERSION_TAGS is a comma-separated list of tags chosen by the device
+# implementer that further distinguishes the build. It's basically defined
+# by the device implementer. Here, we are adding a mandatory tag that
+# identifies the signing config of the build.
+BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
+ifeq ($(TARGET_BUILD_TYPE),debug)
+  BUILD_VERSION_TAGS += debug
+endif
+# The "test-keys" tag marks builds signed with the old test keys,
+# which are available in the SDK.  "dev-keys" marks builds signed with
+# non-default dev keys (usually private keys from a vendor directory).
+# Both of these tags will be removed and replaced with "release-keys"
+# when the target-files is signed in a post-build step.
+ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
+BUILD_KEYS := test-keys
+else
+BUILD_KEYS := dev-keys
+endif
+BUILD_VERSION_TAGS += $(BUILD_KEYS)
+BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
+
+# BUILD_FINGERPRINT is used used to uniquely identify the combined build and
+# product; used by the OTA server.
+ifeq (,$(strip $(BUILD_FINGERPRINT)))
+  BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+endif
+
+BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
+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))
+# unset it for safety.
+BUILD_FINGERPRINT :=
+
+# BUILD_THUMBPRINT is used to uniquely identify the system build; used by the
+# OTA server. This purposefully excludes any product-specific variables.
+ifeq (,$(strip $(BUILD_THUMBPRINT)))
+  BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+endif
+
+BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt
+ifeq ($(strip $(HAS_BUILD_NUMBER)),true)
+$(BUILD_THUMBPRINT_FILE): $(BUILD_NUMBER_FILE)
+endif
+ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE)))
+  $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))")
+endif
+# unset it for safety.
+BUILD_THUMBPRINT_FILE :=
+BUILD_THUMBPRINT :=
diff --git a/core/main.mk b/core/main.mk
index 4b76971..624df49 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -277,7 +277,10 @@
 # Include all of the makefiles in the system
 #
 
-subdir_makefiles := $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT)$(COVERAGE_SUFFIX).mk $(SOONG_ANDROID_MK)
+subdir_makefiles := \
+    $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT)$(COVERAGE_SUFFIX).mk \
+    $(SOONG_ANDROID_MK) \
+    build/make/target/board/android-info.mk
 
 # Android.mk files are only used on Linux builds, Mac only supports Android.bp
 ifeq ($(HOST_OS),linux)
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index fd9dc9b..a371a00 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -109,10 +109,17 @@
 define generate-partition-aconfig-storage-file
 $(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
 $(eval $(strip $(1)): PRIVATE_IN := $(strip $(9)))
+
+ifneq (,$(RELEASE_FINGERPRINT_ACONFIG_PACKAGES))
+STORAGE_FILE_VERSION := 2
+else
+STORAGE_FILE_VERSION := 1
+endif
+
 $(strip $(1)): $(ACONFIG) $(strip $(9))
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
-		$$(ACONFIG) create-storage --container $(10) --file package_map --out $$(PRIVATE_OUT) \
+		$$(ACONFIG) create-storage --container $(10) --file package_map --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
 			$$(addprefix --cache ,$$(PRIVATE_IN)), \
 	)
 	touch $$(PRIVATE_OUT)
@@ -121,7 +128,7 @@
 $(strip $(2)): $(ACONFIG) $(strip $(9))
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
-		$$(ACONFIG) create-storage --container $(10) --file flag_map --out $$(PRIVATE_OUT) \
+		$$(ACONFIG) create-storage --container $(10) --file flag_map --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
 			$$(addprefix --cache ,$$(PRIVATE_IN)), \
 	)
 	touch $$(PRIVATE_OUT)
@@ -130,7 +137,7 @@
 $(strip $(3)): $(ACONFIG) $(strip $(9))
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
-		$$(ACONFIG) create-storage --container $(10) --file flag_val --out $$(PRIVATE_OUT) \
+		$$(ACONFIG) create-storage --container $(10) --file flag_val --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
 		$$(addprefix --cache ,$$(PRIVATE_IN)), \
 	)
 	touch $$(PRIVATE_OUT)
@@ -139,7 +146,7 @@
 $(strip $(4)): $(ACONFIG) $(strip $(9))
 	mkdir -p $$(dir $$(PRIVATE_OUT))
 	$$(if $$(PRIVATE_IN), \
-		$$(ACONFIG) create-storage --container $(10) --file flag_info --out $$(PRIVATE_OUT) \
+		$$(ACONFIG) create-storage --container $(10) --file flag_info --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
 		$$(addprefix --cache ,$$(PRIVATE_IN)), \
 	)
 	touch $$(PRIVATE_OUT)
diff --git a/core/sysprop.mk b/core/sysprop.mk
index c532dd1..e4f994f 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -160,61 +160,6 @@
 $(call declare-1p-target,$(2))
 endef
 
-# -----------------------------------------------------------------
-# Define fingerprint, thumbprint, and version tags for the current build
-#
-# BUILD_VERSION_TAGS is a comma-separated list of tags chosen by the device
-# implementer that further distinguishes the build. It's basically defined
-# by the device implementer. Here, we are adding a mandatory tag that
-# identifies the signing config of the build.
-BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
-ifeq ($(TARGET_BUILD_TYPE),debug)
-  BUILD_VERSION_TAGS += debug
-endif
-# The "test-keys" tag marks builds signed with the old test keys,
-# which are available in the SDK.  "dev-keys" marks builds signed with
-# non-default dev keys (usually private keys from a vendor directory).
-# Both of these tags will be removed and replaced with "release-keys"
-# when the target-files is signed in a post-build step.
-ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
-BUILD_KEYS := test-keys
-else
-BUILD_KEYS := dev-keys
-endif
-BUILD_VERSION_TAGS += $(BUILD_KEYS)
-BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
-
-# BUILD_FINGERPRINT is used used to uniquely identify the combined build and
-# product; used by the OTA server.
-ifeq (,$(strip $(BUILD_FINGERPRINT)))
-  BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
-endif
-
-BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
-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))
-# unset it for safety.
-BUILD_FINGERPRINT :=
-
-# BUILD_THUMBPRINT is used to uniquely identify the system build; used by the
-# OTA server. This purposefully excludes any product-specific variables.
-ifeq (,$(strip $(BUILD_THUMBPRINT)))
-  BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
-endif
-
-BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt
-ifeq ($(strip $(HAS_BUILD_NUMBER)),true)
-$(BUILD_THUMBPRINT_FILE): $(BUILD_NUMBER_FILE)
-endif
-ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE)))
-  $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))")
-endif
-# unset it for safety.
-BUILD_THUMBPRINT_FILE :=
-BUILD_THUMBPRINT :=
-
 KNOWN_OEM_THUMBPRINT_PROPERTIES := \
     ro.product.brand \
     ro.product.name \
diff --git a/target/board/Android.mk b/target/board/android-info.mk
similarity index 100%
rename from target/board/Android.mk
rename to target/board/android-info.mk
diff --git a/target/board/generic_64bitonly_x86_64/device.mk b/target/board/generic_64bitonly_x86_64/device.mk
index bb49057..5edf5e0 100644
--- a/target/board/generic_64bitonly_x86_64/device.mk
+++ b/target/board/generic_64bitonly_x86_64/device.mk
@@ -17,8 +17,3 @@
 ifdef NET_ETH0_STARTONBOOT
   PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
 endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
-    bios.bin \
-    vgabios-cirrus.bin \
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 60f0cc3..27fb310 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -17,8 +17,3 @@
 ifdef NET_ETH0_STARTONBOOT
   PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
 endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
-	bios.bin \
-	vgabios-cirrus.bin \
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 52498ee..b3b58d3 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -489,6 +489,7 @@
 
 PRODUCT_SYSTEM_PROPERTIES += debug.atrace.tags.enableflags=0
 PRODUCT_SYSTEM_PROPERTIES += persist.traced.enable=1
+PRODUCT_SYSTEM_PROPERTIES += ro.surface_flinger.game_default_frame_rate_override=60
 
 # Include kernel configs.
 PRODUCT_PACKAGES += \
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index 07f6472..a1b71ca 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -32,11 +32,6 @@
   PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
 endif
 
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
-	bios.bin \
-	vgabios-cirrus.bin \
-
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
diff --git a/target/product/fullmte.mk b/target/product/fullmte.mk
index b622496..fed66e7 100644
--- a/target/product/fullmte.mk
+++ b/target/product/fullmte.mk
@@ -20,7 +20,7 @@
 # For more details, see:
 # https://source.android.com/docs/security/test/memory-safety/arm-mte
 ifeq ($(filter memtag_heap,$(SANITIZE_TARGET)),)
-  SANITIZE_TARGET := $(strip $(SANITIZE_TARGET) memtag_heap memtag_stack)
+  SANITIZE_TARGET := $(strip $(SANITIZE_TARGET) memtag_heap memtag_stack memtag_globals)
   SANITIZE_TARGET_DIAG := $(strip $(SANITIZE_TARGET_DIAG) memtag_heap)
 endif
 PRODUCT_PRODUCT_PROPERTIES += persist.arm64.memtag.default=sync
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index 1b585d8..5d7ec9a 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -1,5 +1,4 @@
 generic_rootdirs = [
-    "acct",
     "apex",
     "bootstrap-apex",
     "config",
@@ -471,7 +470,6 @@
         "locksettings", // base_system
         "logcat", // base_system
         "logd", // base_system
-        "logpersist.start",
         "lpdump", // base_system
         "lshal", // base_system
         "make_f2fs", // media_system
@@ -528,7 +526,6 @@
         "sfdo", // base_system
         "sgdisk", // base_system
         "sm", // base_system
-        "snapshotctl", // base_system
         "snapuserd", // base_system
         "storaged", // base_system
         "surfaceflinger", // base_system
@@ -586,6 +583,7 @@
             "iperf3",
             "iw",
             "layertracegenerator",
+            "logpersist.start",
             "logtagd.rc",
             "ot-cli-ftd",
             "ot-ctl",
@@ -596,6 +594,7 @@
             "sanitizer-status",
             "servicedispatcher",
             "showmap",
+            "snapshotctl",
             "sqlite3",
             "ss",
             "start_with_lockagent",
@@ -912,4 +911,9 @@
         compressor: "lz4hc,9",
         compress_hints: "erofs_compress_hints.txt",
     },
+    deps: [
+        // DO NOT update this list. Instead, update the system_image_defaults to
+        // sync with the base_system.mk
+        "logpersist.start", // cf only
+    ],
 }
diff --git a/tools/aconfig/aconfig/src/codegen/cpp.rs b/tools/aconfig/aconfig/src/codegen/cpp.rs
index ae18679..d7d77c5 100644
--- a/tools/aconfig/aconfig/src/codegen/cpp.rs
+++ b/tools/aconfig/aconfig/src/codegen/cpp.rs
@@ -24,7 +24,7 @@
 
 use crate::codegen;
 use crate::codegen::CodegenMode;
-use crate::commands::OutputFile;
+use crate::commands::{should_include_flag, OutputFile};
 
 pub fn generate_cpp_code<I>(
     package: &str,
@@ -127,10 +127,7 @@
     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 no_assigned_offset = !should_include_flag(pf);
 
     let flag_offset = match flag_ids.get(pf.name()) {
         Some(offset) => offset,
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 0d528d2..81340f2 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -22,7 +22,7 @@
 
 use crate::codegen;
 use crate::codegen::CodegenMode;
-use crate::commands::OutputFile;
+use crate::commands::{should_include_flag, OutputFile};
 use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
 use std::collections::HashMap;
 
@@ -162,10 +162,7 @@
     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 no_assigned_offset = !should_include_flag(pf);
 
     let flag_offset = match flag_offsets.get(pf.name()) {
         Some(offset) => offset,
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index 2bf565a..74da1bc 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -24,7 +24,7 @@
 
 use crate::codegen;
 use crate::codegen::CodegenMode;
-use crate::commands::OutputFile;
+use crate::commands::{should_include_flag, OutputFile};
 
 pub fn generate_rust_code<I>(
     package: &str,
@@ -88,18 +88,12 @@
 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 {
+                if !should_include_flag(pf) {
                     &0
                 }
                 // All other flags _must_ have an offset.
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 4c06462..2f96015 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -221,13 +221,13 @@
     new_exported: bool,
 ) -> Result<Vec<OutputFile>> {
     let parsed_flags = input.try_parse_flags()?;
-    let modified_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, codegen_mode)?;
+    let modified_parsed_flags =
+        modify_parsed_flags_based_on_mode(parsed_flags.clone(), codegen_mode)?;
     let Some(package) = find_unique_package(&modified_parsed_flags) else {
         bail!("no parsed flags, or the parsed flags use different packages");
     };
     let package = package.to_string();
-    let mut flag_names =
-        modified_parsed_flags.iter().map(|pf| pf.name().to_string()).collect::<Vec<_>>();
+    let mut flag_names = extract_flag_names(parsed_flags)?;
     let package_fingerprint = compute_flags_fingerprint(&mut flag_names);
     let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
     generate_java_code(
@@ -436,14 +436,7 @@
             return Err(anyhow::anyhow!("the number of flags in a package cannot exceed 65535"));
         }
 
-        // 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()))
-        {
+        if should_include_flag(pf) {
             flag_ids.insert(pf.name().to_string(), flag_idx as u16);
             flag_idx += 1;
         }
@@ -451,10 +444,8 @@
     Ok(flag_ids)
 }
 
-#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
-                    // protect hardcoded offset reads.
-                    // Creates a fingerprint of the flag names (which requires sorting the vector).
-                    // Fingerprint is used by both codegen and storage files.
+// Creates a fingerprint of the flag names (which requires sorting the vector).
+// Fingerprint is used by both codegen and storage files.
 pub fn compute_flags_fingerprint(flag_names: &mut Vec<String>) -> u64 {
     flag_names.sort();
 
@@ -465,11 +456,9 @@
     hasher.finish()
 }
 
-#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
-                    // protect hardcoded offset reads.
-                    // Converts ProtoParsedFlags into a vector of strings containing all of the flag
-                    // names. Helper fn for creating fingerprint for codegen files. Flags must all
-                    // belong to the same package.
+// Converts ProtoParsedFlags into a vector of strings containing all of the flag
+// names. Helper fn for creating fingerprint for codegen files. Flags must all
+// belong to the same package.
 fn extract_flag_names(flags: ProtoParsedFlags) -> Result<Vec<String>> {
     let separated_flags: Vec<ProtoParsedFlag> = flags.parsed_flag.into_iter().collect::<Vec<_>>();
 
@@ -478,7 +467,23 @@
         bail!("No parsed flags, or the parsed flags use different packages.");
     };
 
-    Ok(separated_flags.into_iter().map(|flag| flag.name.unwrap()).collect::<Vec<_>>())
+    Ok(separated_flags
+        .into_iter()
+        .filter(should_include_flag)
+        .map(|flag| flag.name.unwrap())
+        .collect::<Vec<_>>())
+}
+
+// Exclude system/vendor/product flags that are RO+disabled.
+pub fn should_include_flag(pf: &ProtoParsedFlag) -> bool {
+    let should_filter_container = pf.container == Some("vendor".to_string())
+        || pf.container == Some("system".to_string())
+        || pf.container == Some("product".to_string());
+
+    let disabled_ro = pf.state == Some(ProtoFlagState::DISABLED.into())
+        && pf.permission == Some(ProtoFlagPermission::READ_ONLY.into());
+
+    !should_filter_container || !disabled_ro
 }
 
 #[cfg(test)]
@@ -489,7 +494,7 @@
     #[test]
     fn test_offset_fingerprint() {
         let parsed_flags = crate::test::parse_test_flags();
-        let expected_fingerprint: u64 = 5801144784618221668;
+        let expected_fingerprint: u64 = 11551379960324242360;
 
         let mut extracted_flags = extract_flag_names(parsed_flags).unwrap();
         let hash_result = compute_flags_fingerprint(&mut extracted_flags);
@@ -509,6 +514,7 @@
             .parsed_flag
             .clone()
             .into_iter()
+            .filter(should_include_flag)
             .map(|flag| flag.name.unwrap())
             .map(String::from)
             .collect::<Vec<_>>();
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index 3b245a7..a3b4e8f 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-use crate::commands::assign_flag_ids;
+use crate::commands::{assign_flag_ids, should_include_flag};
 use crate::storage::FlagPackage;
-use aconfig_protos::{ProtoFlagPermission, ProtoFlagState};
+use aconfig_protos::ProtoFlagPermission;
 use aconfig_storage_file::{
     get_table_size, FlagTable, FlagTableHeader, FlagTableNode, StorageFileType, StoredFlagType,
 };
@@ -64,13 +64,7 @@
     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()))
-        });
+        filtered_package.boolean_flags.retain(|pf| should_include_flag(pf));
 
         let flag_ids =
             assign_flag_ids(package.package_name, filtered_package.boolean_flags.iter().copied())?;
diff --git a/tools/aconfig/aconfig_flags/flags.aconfig b/tools/aconfig/aconfig_flags/flags.aconfig
index 0a004ca..96bb81a 100644
--- a/tools/aconfig/aconfig_flags/flags.aconfig
+++ b/tools/aconfig/aconfig_flags/flags.aconfig
@@ -14,3 +14,20 @@
   bug: "369808805"
   description: "When enabled, launch aconfigd from config infra module."
 }
+
+flag {
+  name: "tools_read_from_new_storage"
+  namespace: "core_experiments_team_internal"
+  bug: "370499640"
+  description: "When enabled, tools read directly from the new aconfig storage."
+}
+
+flag {
+  name: "tools_read_from_new_storage_bugfix"
+  namespace: "core_experiments_team_internal"
+  bug: "370499640"
+  description: "When enabled, tools read directly from the new aconfig storage."
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
\ No newline at end of file
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index fa41ff0..16341b9 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -154,18 +154,15 @@
 java_library {
     name: "aconfig_storage_reader_java",
     srcs: [
-        "srcs/android/os/flagging/PlatformAconfigPackageInternal.java",
+        "srcs/android/os/flagging/*.java",
     ],
     libs: [
         "unsupportedappusage",
-        "strict_mode_stub",
-        "aconfig_storage_stub",
     ],
     static_libs: [
         "aconfig_storage_file_java",
     ],
-    sdk_version: "core_current",
-    host_supported: true,
+    sdk_version: "current",
     visibility: [
         "//frameworks/base",
         "//build/make/tools/aconfig/aconfig_storage_read_api/tests",
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackage.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackage.java
new file mode 100644
index 0000000..5fbe567
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackage.java
@@ -0,0 +1,168 @@
+/*
+ * 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.flagging;
+
+import android.aconfig.storage.AconfigStorageException;
+import android.aconfig.storage.FlagTable;
+import android.aconfig.storage.FlagValueList;
+import android.aconfig.storage.PackageTable;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An {@code aconfig} package containing the enabled state of its flags.
+ *
+ * <p><strong>Note: this is intended only to be used by generated code. To determine if a given flag
+ * is enabled in app code, the generated android flags should be used.</strong>
+ *
+ * <p>This class is used to read the flag from platform Aconfig Package.Each instance of this class
+ * will cache information related to one package. To read flags from a different package, a new
+ * instance of this class should be {@link #load loaded}.
+ *
+ * @hide
+ */
+public class PlatformAconfigPackage {
+    private static final String TAG = "PlatformAconfigPackage";
+    private static final String MAP_PATH = "/metadata/aconfig/maps/";
+    private static final String BOOT_PATH = "/metadata/aconfig/boot/";
+
+    private static final Map<String, PackageTable> sPackageTableCache = new HashMap<>();
+
+    private FlagTable mFlagTable;
+    private FlagValueList mFlagValueList;
+
+    private int mPackageBooleanStartOffset = -1;
+    private int mPackageId = -1;
+
+    private PlatformAconfigPackage() {}
+
+    /** @hide */
+    @UnsupportedAppUsage
+    public static final Set<String> PLATFORM_PACKAGE_MAP_FILES =
+            Set.of("system.package.map", "vendor.package.map", "product.package.map");
+
+    static {
+        for (String pf : PLATFORM_PACKAGE_MAP_FILES) {
+            try {
+                PackageTable pTable = PackageTable.fromBytes(mapStorageFile(MAP_PATH + pf));
+                for (String packageName : pTable.getPackageList()) {
+                    sPackageTableCache.put(packageName, pTable);
+                }
+            } catch (Exception e) {
+                // pass
+                Log.w(TAG, e.toString());
+            }
+        }
+    }
+
+    /**
+     * Loads a platform Aconfig Package from Aconfig Storage.
+     *
+     * <p>This method attempts to load the specified platform Aconfig package.
+     *
+     * @param packageName The name of the Aconfig package to load.
+     * @return An instance of {@link PlatformAconfigPackage}, which may be empty if the package is
+     *     not found in the container. Null if the package is not found in platform partitions.
+     * @throws AconfigStorageReadException if there is an error reading from Aconfig Storage, such
+     *     as if the storage system is not found, or there is an error reading the storage file. The
+     *     specific error code can be got using {@link AconfigStorageReadException#getErrorCode()}.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public static PlatformAconfigPackage load(String packageName) {
+        try {
+            PlatformAconfigPackage aconfigPackage = new PlatformAconfigPackage();
+            PackageTable pTable = sPackageTableCache.get(packageName);
+            if (pTable == null) {
+                return null;
+            }
+            PackageTable.Node pNode = pTable.get(packageName);
+            String container = pTable.getHeader().getContainer();
+            aconfigPackage.mFlagTable =
+                    FlagTable.fromBytes(mapStorageFile(MAP_PATH + container + ".flag.map"));
+            aconfigPackage.mFlagValueList =
+                    FlagValueList.fromBytes(mapStorageFile(BOOT_PATH + container + ".val"));
+            aconfigPackage.mPackageBooleanStartOffset = pNode.getBooleanStartIndex();
+            aconfigPackage.mPackageId = pNode.getPackageId();
+            return aconfigPackage;
+        } catch (AconfigStorageException e) {
+            throw new AconfigStorageReadException(
+                    e.getErrorCode(), "Fail to create AconfigPackage", e);
+        } catch (Exception e) {
+            throw new AconfigStorageReadException(
+                    AconfigStorageReadException.ERROR_GENERIC,
+                    "Fail to create PlatformAconfigPackage",
+                    e);
+        }
+    }
+
+    /**
+     * Retrieves the value of a boolean flag.
+     *
+     * <p>This method retrieves the value of the specified flag. If the flag exists within the
+     * loaded Aconfig Package, its value is returned. Otherwise, the provided `defaultValue` is
+     * returned.
+     *
+     * @param flagName The name of the flag (excluding any package name prefix).
+     * @param defaultValue The value to return if the flag is not found.
+     * @return The boolean value of the flag, or `defaultValue` if the flag is not found.
+     * @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);
+    }
+
+    // Map a storage file given file path
+    private static MappedByteBuffer mapStorageFile(String file) {
+        FileChannel channel = null;
+        try {
+            channel = FileChannel.open(Paths.get(file), StandardOpenOption.READ);
+            return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+        } catch (Exception e) {
+            throw new AconfigStorageReadException(
+                    AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE,
+                    "Fail to mmap storage",
+                    e);
+        } finally {
+            quietlyDispose(channel);
+        }
+    }
+
+    private static void quietlyDispose(Closeable closable) {
+        try {
+            if (closable != null) {
+                closable.close();
+            }
+        } catch (Exception e) {
+            // no need to care, at least as of now
+        }
+    }
+}
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 2b0aeae..e532ff6 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
@@ -45,7 +45,7 @@
     private static final Set<String> PLATFORM_CONTAINERS = Set.of("system", "vendor", "product");
 
     @Test
-    public void testAconfigPackageInternal_load() throws IOException {
+    public void testPlatformAconfigPackageInternal_load() throws IOException {
         List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
         Map<String, PlatformAconfigPackageInternal> readerMap = new HashMap<>();
         StorageFileProvider fp = StorageFileProvider.getDefaultProvider();
@@ -82,7 +82,7 @@
     }
 
     @Test
-    public void testAconfigPackage_load_withError() throws IOException {
+    public void testPlatformAconfigPackage_load_withError() throws IOException {
         // container not found fake_container
         AconfigStorageException e =
                 assertThrows(
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageTest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageTest.java
new file mode 100644
index 0000000..fabc2c9
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.aconfig.DeviceProtos;
+import android.aconfig.nano.Aconfig;
+import android.aconfig.nano.Aconfig.parsed_flag;
+import android.aconfig.storage.FlagTable;
+import android.aconfig.storage.FlagValueList;
+import android.aconfig.storage.PackageTable;
+import android.aconfig.storage.StorageFileProvider;
+import android.os.flagging.PlatformAconfigPackage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public class PlatformAconfigPackageTest {
+
+    private static final Set<String> PLATFORM_CONTAINERS = Set.of("system", "vendor", "product");
+
+    @Test
+    public void testPlatformAconfigPackage_load() throws IOException {
+        List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
+        Map<String, PlatformAconfigPackage> readerMap = new HashMap<>();
+        StorageFileProvider fp = StorageFileProvider.getDefaultProvider();
+
+        for (parsed_flag flag : flags) {
+            if (flag.permission == Aconfig.READ_ONLY && flag.state == Aconfig.DISABLED) {
+                continue;
+            }
+            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);
+
+            long fingerprint = pNode.getPackageFingerprint();
+
+            PlatformAconfigPackage reader = readerMap.get(packageName);
+            if (reader == null) {
+                reader = PlatformAconfigPackage.load(packageName);
+                readerMap.put(packageName, reader);
+            }
+            boolean jVal = reader.getBooleanFlagValue(flagName, !rVal);
+
+            assertEquals(rVal, jVal);
+        }
+    }
+
+    @Test
+    public void testPlatformAconfigPackage_load_withError() throws IOException {
+        // package not found
+        assertNull(PlatformAconfigPackage.load("fake_container"));
+    }
+}
diff --git a/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigStorageReadException.java b/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigStorageReadException.java
deleted file mode 100644
index bfec98c..0000000
--- a/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigStorageReadException.java
+++ /dev/null
@@ -1,61 +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.os.flagging;
-
-public class AconfigStorageReadException extends RuntimeException {
-
-    /** Generic error code indicating an unspecified Aconfig Storage error. */
-    public static final int ERROR_GENERIC = 0;
-
-    /** Error code indicating that the Aconfig Storage system is not found on the device. */
-    public static final int ERROR_STORAGE_SYSTEM_NOT_FOUND = 1;
-
-    /** Error code indicating that the requested configuration package is not found. */
-    public static final int ERROR_PACKAGE_NOT_FOUND = 2;
-
-    /** Error code indicating that the specified container is not found. */
-    public static final int ERROR_CONTAINER_NOT_FOUND = 3;
-
-    /** Error code indicating that there was an error reading the Aconfig Storage file. */
-    public static final int ERROR_CANNOT_READ_STORAGE_FILE = 4;
-
-    public static final int ERROR_FILE_FINGERPRINT_MISMATCH = 5;
-
-    public AconfigStorageReadException(int errorCode, String msg) {
-        super(msg);
-        throw new UnsupportedOperationException("Stub!");
-    }
-
-    public AconfigStorageReadException(int errorCode, String msg, Throwable cause) {
-        super(msg, cause);
-        throw new UnsupportedOperationException("Stub!");
-    }
-
-    public AconfigStorageReadException(int errorCode, Throwable cause) {
-        super(cause);
-        throw new UnsupportedOperationException("Stub!");
-    }
-
-    public int getErrorCode() {
-        throw new UnsupportedOperationException("Stub!");
-    }
-
-    @Override
-    public String getMessage() {
-        throw new UnsupportedOperationException("Stub!");
-    }
-}
diff --git a/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackage.java b/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackage.java
new file mode 100644
index 0000000..ec79f7d
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackage.java
@@ -0,0 +1,36 @@
+/*
+ * 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.flagging;
+
+import java.util.Set;
+
+/*
+ * This class allows generated aconfig code to compile independently of the framework.
+ */
+public class PlatformAconfigPackage {
+
+    public static final Set<String> PLATFORM_PACKAGE_MAP_FILES =
+            Set.of("system.package.map", "vendor.package.map", "product.package.map");
+
+    public static PlatformAconfigPackage load(String packageName) {
+        throw new UnsupportedOperationException("Stub!");
+    }
+
+    public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
+        throw new UnsupportedOperationException("Stub!");
+    }
+}
diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py
index 1fd7950..0640041 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -42,8 +42,9 @@
 _EM_X86_64 = 62
 _EM_AARCH64 = 183
 
-_KNOWN_MACHINES = {_EM_386, _EM_ARM, _EM_X86_64, _EM_AARCH64}
-
+_32_BIT_MACHINES = {_EM_386, _EM_ARM}
+_64_BIT_MACHINES = {_EM_X86_64, _EM_AARCH64}
+_KNOWN_MACHINES = _32_BIT_MACHINES | _64_BIT_MACHINES
 
 # ELF header struct
 _ELF_HEADER_STRUCT = (
@@ -483,6 +484,11 @@
       sys.exit(2)
 
   def check_max_page_size(self, max_page_size):
+    if self._file_under_test.header.e_machine in _32_BIT_MACHINES:
+      # Skip test on 32-bit machines. 16 KB pages is an arm64 feature
+      # and no 32-bit systems in Android use it.
+      return
+
     for alignment in self._file_under_test.alignments:
       if alignment % max_page_size != 0:
         self._error(f'Load segment has alignment {alignment} but '