Merge "aconfig: add storage file type into storage file serialization" into main am: ee18b35565 am: 3a0908ca8e

Original change: https://android-review.googlesource.com/c/platform/build/+/2997856

Change-Id: Ia67007cbff8dd10b00e86e407b1f00d9f6b98457
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index c1df16b..98dde44 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -31,7 +31,7 @@
     ParsedFlagExt, ProtoFlagMetadata, ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag,
     ProtoParsedFlags, ProtoTracepoint,
 };
-use aconfig_storage_file::StorageFileSelection;
+use aconfig_storage_file::StorageFileType;
 
 pub struct Input {
     pub source: String,
@@ -237,7 +237,7 @@
 pub fn create_storage(
     caches: Vec<Input>,
     container: &str,
-    file: &StorageFileSelection,
+    file: &StorageFileType,
 ) -> Result<Vec<u8>> {
     let parsed_flags_vec: Vec<ProtoParsedFlags> = caches
         .into_iter()
diff --git a/tools/aconfig/aconfig/src/main.rs b/tools/aconfig/aconfig/src/main.rs
index 5a4f23c..69f5458 100644
--- a/tools/aconfig/aconfig/src/main.rs
+++ b/tools/aconfig/aconfig/src/main.rs
@@ -29,7 +29,7 @@
 mod dump;
 mod storage;
 
-use aconfig_storage_file::StorageFileSelection;
+use aconfig_storage_file::StorageFileType;
 use codegen::CodegenMode;
 use dump::DumpFormat;
 
@@ -138,7 +138,7 @@
                 .arg(
                     Arg::new("file")
                         .long("file")
-                        .value_parser(|s: &str| StorageFileSelection::try_from(s)),
+                        .value_parser(|s: &str| StorageFileType::try_from(s)),
                 )
                 .arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
                 .arg(Arg::new("out").long("out").required(true)),
@@ -285,7 +285,7 @@
             write_output_to_file_or_stdout(path, &output)?;
         }
         Some(("create-storage", sub_matches)) => {
-            let file = get_required_arg::<StorageFileSelection>(sub_matches, "file")
+            let file = get_required_arg::<StorageFileType>(sub_matches, "file")
                 .context("Invalid storage file selection")?;
             let cache = open_zero_or_more_files(sub_matches, "cache")?;
             let container = get_required_arg::<String>(sub_matches, "container")?;
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index 1381e89..b861c1f 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -17,7 +17,7 @@
 use crate::commands::assign_flag_ids;
 use crate::storage::FlagPackage;
 use aconfig_storage_file::{
-    get_table_size, FlagTable, FlagTableHeader, FlagTableNode, FILE_VERSION,
+    get_table_size, FlagTable, FlagTableHeader, FlagTableNode, FILE_VERSION, StorageFileType
 };
 use anyhow::{anyhow, Result};
 
@@ -25,6 +25,7 @@
     FlagTableHeader {
         version: FILE_VERSION,
         container: String::from(container),
+        file_type: StorageFileType::FlagMap as u8,
         file_size: 0,
         num_flags,
         bucket_offset: 0,
@@ -168,31 +169,32 @@
         let expected_header = FlagTableHeader {
             version: FILE_VERSION,
             container: String::from("system"),
-            file_size: 320,
+            file_type: StorageFileType::FlagMap as u8,
+            file_size: 321,
             num_flags: 8,
-            bucket_offset: 30,
-            node_offset: 98,
+            bucket_offset: 31,
+            node_offset: 99,
         };
         assert_eq!(header, &expected_header);
 
         let buckets: &Vec<Option<u32>> = &flag_table.as_ref().unwrap().buckets;
         let expected_bucket: Vec<Option<u32>> = vec![
-            Some(98),
-            Some(124),
+            Some(99),
+            Some(125),
             None,
             None,
             None,
-            Some(177),
+            Some(178),
             None,
-            Some(203),
+            Some(204),
             None,
-            Some(261),
+            Some(262),
             None,
             None,
             None,
             None,
             None,
-            Some(293),
+            Some(294),
             None,
         ];
         assert_eq!(buckets, &expected_bucket);
@@ -201,10 +203,10 @@
         assert_eq!(nodes.len(), 8);
 
         assert_eq!(nodes[0], new_expected_node(0, "enabled_ro", 1, 1, None));
-        assert_eq!(nodes[1], new_expected_node(0, "enabled_rw", 1, 2, Some(150)));
+        assert_eq!(nodes[1], new_expected_node(0, "enabled_rw", 1, 2, Some(151)));
         assert_eq!(nodes[2], new_expected_node(1, "disabled_ro", 1, 0, None));
         assert_eq!(nodes[3], new_expected_node(2, "enabled_ro", 1, 1, None));
-        assert_eq!(nodes[4], new_expected_node(1, "enabled_fixed_ro", 1, 1, Some(235)));
+        assert_eq!(nodes[4], new_expected_node(1, "enabled_fixed_ro", 1, 1, Some(236)));
         assert_eq!(nodes[5], new_expected_node(1, "enabled_ro", 1, 2, None));
         assert_eq!(nodes[6], new_expected_node(2, "enabled_fixed_ro", 1, 0, None));
         assert_eq!(nodes[7], new_expected_node(0, "disabled_rw", 1, 0, None));
diff --git a/tools/aconfig/aconfig/src/storage/flag_value.rs b/tools/aconfig/aconfig/src/storage/flag_value.rs
index 0d4b5b4..e40bbc1 100644
--- a/tools/aconfig/aconfig/src/storage/flag_value.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_value.rs
@@ -17,13 +17,14 @@
 use crate::commands::assign_flag_ids;
 use crate::storage::FlagPackage;
 use aconfig_protos::ProtoFlagState;
-use aconfig_storage_file::{FlagValueHeader, FlagValueList, FILE_VERSION};
+use aconfig_storage_file::{FlagValueHeader, FlagValueList, FILE_VERSION, StorageFileType};
 use anyhow::{anyhow, Result};
 
 fn new_header(container: &str, num_flags: u32) -> FlagValueHeader {
     FlagValueHeader {
         version: FILE_VERSION,
         container: String::from(container),
+        file_type: StorageFileType::FlagVal as u8,
         file_size: 0,
         num_flags,
         boolean_value_offset: 0,
@@ -79,9 +80,10 @@
         let expected_header = FlagValueHeader {
             version: FILE_VERSION,
             container: String::from("system"),
-            file_size: 34,
+            file_type: StorageFileType::FlagVal as u8,
+            file_size: 35,
             num_flags: 8,
-            boolean_value_offset: 26,
+            boolean_value_offset: 27,
         };
         assert_eq!(header, &expected_header);
 
diff --git a/tools/aconfig/aconfig/src/storage/mod.rs b/tools/aconfig/aconfig/src/storage/mod.rs
index 29eb9c8..c818d79 100644
--- a/tools/aconfig/aconfig/src/storage/mod.rs
+++ b/tools/aconfig/aconfig/src/storage/mod.rs
@@ -26,7 +26,7 @@
     package_table::create_package_table,
 };
 use aconfig_protos::{ProtoParsedFlag, ProtoParsedFlags};
-use aconfig_storage_file::StorageFileSelection;
+use aconfig_storage_file::StorageFileType;
 
 pub struct FlagPackage<'a> {
     pub package_name: &'a str,
@@ -87,7 +87,7 @@
 pub fn generate_storage_file<'a, I>(
     container: &str,
     parsed_flags_vec_iter: I,
-    file: &StorageFileSelection,
+    file: &StorageFileType,
 ) -> Result<Vec<u8>>
 where
     I: Iterator<Item = &'a ProtoParsedFlags>,
@@ -95,15 +95,15 @@
     let packages = group_flags_by_package(parsed_flags_vec_iter);
 
     match file {
-        StorageFileSelection::PackageMap => {
+        StorageFileType::PackageMap => {
             let package_table = create_package_table(container, &packages)?;
             Ok(package_table.as_bytes())
         }
-        StorageFileSelection::FlagMap => {
+        StorageFileType::FlagMap => {
             let flag_table = create_flag_table(container, &packages)?;
             Ok(flag_table.as_bytes())
         }
-        StorageFileSelection::FlagVal => {
+        StorageFileType::FlagVal => {
             let flag_value = create_flag_value(container, &packages)?;
             Ok(flag_value.as_bytes())
         }
diff --git a/tools/aconfig/aconfig/src/storage/package_table.rs b/tools/aconfig/aconfig/src/storage/package_table.rs
index 4c08129..bc2da4d 100644
--- a/tools/aconfig/aconfig/src/storage/package_table.rs
+++ b/tools/aconfig/aconfig/src/storage/package_table.rs
@@ -17,7 +17,7 @@
 use anyhow::Result;
 
 use aconfig_storage_file::{
-    get_table_size, PackageTable, PackageTableHeader, PackageTableNode, FILE_VERSION,
+    get_table_size, PackageTable, PackageTableHeader, PackageTableNode, FILE_VERSION, StorageFileType
 };
 
 use crate::storage::FlagPackage;
@@ -26,6 +26,7 @@
     PackageTableHeader {
         version: FILE_VERSION,
         container: String::from(container),
+        file_type: StorageFileType::PackageMap as u8,
         file_size: 0,
         num_packages,
         bucket_offset: 0,
@@ -123,15 +124,16 @@
         let expected_header = PackageTableHeader {
             version: FILE_VERSION,
             container: String::from("system"),
-            file_size: 208,
+            file_type: StorageFileType::PackageMap as u8,
+            file_size: 209,
             num_packages: 3,
-            bucket_offset: 30,
-            node_offset: 58,
+            bucket_offset: 31,
+            node_offset: 59,
         };
         assert_eq!(header, &expected_header);
 
         let buckets: &Vec<Option<u32>> = &package_table.as_ref().unwrap().buckets;
-        let expected: Vec<Option<u32>> = vec![Some(58), None, None, Some(108), None, None, None];
+        let expected: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), None, None, None];
         assert_eq!(buckets, &expected);
 
         let nodes: &Vec<PackageTableNode> = &package_table.as_ref().unwrap().nodes;
@@ -147,7 +149,7 @@
             package_name: String::from("com.android.aconfig.storage.test_1"),
             package_id: 0,
             boolean_offset: 0,
-            next_offset: Some(158),
+            next_offset: Some(159),
         };
         assert_eq!(nodes[1], second_node_expected);
         let third_node_expected = PackageTableNode {
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_table.rs b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
index d6e5c62..5f5f845 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
@@ -17,8 +17,11 @@
 //! flag table module defines the flag table file format and methods for serialization
 //! and deserialization
 
-use crate::AconfigStorageError::{self, BytesParseFail};
-use crate::{get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes};
+use crate::{
+    get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes,
+    read_u8_from_bytes,
+};
+use crate::{AconfigStorageError, StorageFileType};
 use anyhow::anyhow;
 use std::fmt;
 
@@ -27,6 +30,7 @@
 pub struct FlagTableHeader {
     pub version: u32,
     pub container: String,
+    pub file_type: u8,
     pub file_size: u32,
     pub num_flags: u32,
     pub bucket_offset: u32,
@@ -38,8 +42,11 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         writeln!(
             f,
-            "Version: {}, Container: {}, File Size: {}",
-            self.version, self.container, self.file_size
+            "Version: {}, Container: {}, File Type: {:?}, File Size: {}",
+            self.version,
+            self.container,
+            StorageFileType::try_from(self.file_type),
+            self.file_size
         )?;
         writeln!(
             f,
@@ -58,6 +65,7 @@
         let container_bytes = self.container.as_bytes();
         result.extend_from_slice(&(container_bytes.len() as u32).to_le_bytes());
         result.extend_from_slice(container_bytes);
+        result.extend_from_slice(&self.file_type.to_le_bytes());
         result.extend_from_slice(&self.file_size.to_le_bytes());
         result.extend_from_slice(&self.num_flags.to_le_bytes());
         result.extend_from_slice(&self.bucket_offset.to_le_bytes());
@@ -68,14 +76,21 @@
     /// Deserialize from bytes
     pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> {
         let mut head = 0;
-        Ok(Self {
+        let table = Self {
             version: read_u32_from_bytes(bytes, &mut head)?,
             container: read_str_from_bytes(bytes, &mut head)?,
+            file_type: read_u8_from_bytes(bytes, &mut head)?,
             file_size: read_u32_from_bytes(bytes, &mut head)?,
             num_flags: read_u32_from_bytes(bytes, &mut head)?,
             bucket_offset: read_u32_from_bytes(bytes, &mut head)?,
             node_offset: read_u32_from_bytes(bytes, &mut head)?,
-        })
+        };
+        if table.file_type != StorageFileType::FlagMap as u8 {
+            return Err(AconfigStorageError::BytesParseFail(anyhow!(
+                "binary file is not a flag map"
+            )));
+        }
+        Ok(table)
     }
 }
 
@@ -191,7 +206,9 @@
                 Ok(node)
             })
             .collect::<Result<Vec<_>, AconfigStorageError>>()
-            .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse flag table: {}", errmsg)))?;
+            .map_err(|errmsg| {
+                AconfigStorageError::BytesParseFail(anyhow!("fail to parse flag table: {}", errmsg))
+            })?;
 
         let table = Self { header, buckets, nodes };
         Ok(table)
@@ -234,4 +251,16 @@
         let version = read_u32_from_bytes(bytes, &mut head).unwrap();
         assert_eq!(version, 1234)
     }
+
+    #[test]
+    // this test point locks down file type check
+    fn test_file_type_check() {
+        let mut flag_table = create_test_flag_table();
+        flag_table.header.file_type = 123u8;
+        let error = FlagTable::from_bytes(&flag_table.as_bytes()).unwrap_err();
+        assert_eq!(
+            format!("{:?}", error),
+            format!("BytesParseFail(binary file is not a flag map)")
+        );
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_value.rs b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
index 021546c..d7867d3 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_value.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
@@ -17,8 +17,9 @@
 //! flag value module defines the flag value file format and methods for serialization
 //! and deserialization
 
-use crate::AconfigStorageError;
 use crate::{read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes};
+use crate::{AconfigStorageError, StorageFileType};
+use anyhow::anyhow;
 use std::fmt;
 
 /// Flag value header struct
@@ -26,6 +27,7 @@
 pub struct FlagValueHeader {
     pub version: u32,
     pub container: String,
+    pub file_type: u8,
     pub file_size: u32,
     pub num_flags: u32,
     pub boolean_value_offset: u32,
@@ -36,8 +38,11 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         writeln!(
             f,
-            "Version: {}, Container: {}, File Size: {}",
-            self.version, self.container, self.file_size
+            "Version: {}, Container: {}, File Type: {:?}, File Size: {}",
+            self.version,
+            self.container,
+            StorageFileType::try_from(self.file_type),
+            self.file_size
         )?;
         writeln!(
             f,
@@ -56,6 +61,7 @@
         let container_bytes = self.container.as_bytes();
         result.extend_from_slice(&(container_bytes.len() as u32).to_le_bytes());
         result.extend_from_slice(container_bytes);
+        result.extend_from_slice(&self.file_type.to_le_bytes());
         result.extend_from_slice(&self.file_size.to_le_bytes());
         result.extend_from_slice(&self.num_flags.to_le_bytes());
         result.extend_from_slice(&self.boolean_value_offset.to_le_bytes());
@@ -65,13 +71,20 @@
     /// Deserialize from bytes
     pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> {
         let mut head = 0;
-        Ok(Self {
+        let list = Self {
             version: read_u32_from_bytes(bytes, &mut head)?,
             container: read_str_from_bytes(bytes, &mut head)?,
+            file_type: read_u8_from_bytes(bytes, &mut head)?,
             file_size: read_u32_from_bytes(bytes, &mut head)?,
             num_flags: read_u32_from_bytes(bytes, &mut head)?,
             boolean_value_offset: read_u32_from_bytes(bytes, &mut head)?,
-        })
+        };
+        if list.file_type != StorageFileType::FlagVal as u8 {
+            return Err(AconfigStorageError::BytesParseFail(anyhow!(
+                "binary file is not a flag value file"
+            )));
+        }
+        Ok(list)
     }
 }
 
@@ -145,4 +158,16 @@
         let version = read_u32_from_bytes(bytes, &mut head).unwrap();
         assert_eq!(version, 1234)
     }
+
+    #[test]
+    // this test point locks down file type check
+    fn test_file_type_check() {
+        let mut flag_value_list = create_test_flag_value_list();
+        flag_value_list.header.file_type = 123u8;
+        let error = FlagValueList::from_bytes(&flag_value_list.as_bytes()).unwrap_err();
+        assert_eq!(
+            format!("{:?}", error),
+            format!("BytesParseFail(binary file is not a flag value file)")
+        );
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index c40caba..24b16a1 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -64,13 +64,13 @@
 
 /// Storage file type enum
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub enum StorageFileSelection {
-    PackageMap,
-    FlagMap,
-    FlagVal,
+pub enum StorageFileType {
+    PackageMap = 0,
+    FlagMap = 1,
+    FlagVal = 2,
 }
 
-impl TryFrom<&str> for StorageFileSelection {
+impl TryFrom<&str> for StorageFileType {
     type Error = anyhow::Error;
 
     fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
@@ -79,12 +79,25 @@
             "flag_map" => Ok(Self::FlagMap),
             "flag_val" => Ok(Self::FlagVal),
             _ => Err(anyhow!(
-                "Invalid storage file type, valid types are package_map|flag_map|flag_val]"
+                "Invalid storage file type, valid types are package_map|flag_map|flag_val"
             )),
         }
     }
 }
 
+impl TryFrom<u8> for StorageFileType {
+    type Error = anyhow::Error;
+
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            x if x == Self::PackageMap as u8 => Ok(Self::PackageMap),
+            x if x == Self::FlagMap as u8 => Ok(Self::FlagMap),
+            x if x == Self::FlagVal as u8 => Ok(Self::FlagVal),
+            _ => Err(anyhow!("Invalid storage file type")),
+        }
+    }
+}
+
 /// Get the right hash table size given number of entries in the table. Use a
 /// load factor of 0.5 for performance.
 pub fn get_table_size(entries: u32) -> Result<u32, AconfigStorageError> {
diff --git a/tools/aconfig/aconfig_storage_file/src/main.rs b/tools/aconfig/aconfig_storage_file/src/main.rs
index b5e6158..293d018 100644
--- a/tools/aconfig/aconfig_storage_file/src/main.rs
+++ b/tools/aconfig/aconfig_storage_file/src/main.rs
@@ -18,7 +18,7 @@
 
 use aconfig_storage_file::{
     list_flags, read_file_to_bytes, AconfigStorageError, FlagTable, FlagValueList, PackageTable,
-    StorageFileSelection,
+    StorageFileType,
 };
 
 use clap::{builder::ArgAction, Arg, Command};
@@ -33,7 +33,7 @@
                     Arg::new("type")
                         .long("type")
                         .required(true)
-                        .value_parser(|s: &str| StorageFileSelection::try_from(s)),
+                        .value_parser(|s: &str| StorageFileType::try_from(s)),
                 ),
         )
         .subcommand(
@@ -51,19 +51,19 @@
 
 fn print_storage_file(
     file_path: &str,
-    file_type: &StorageFileSelection,
+    file_type: &StorageFileType,
 ) -> Result<(), AconfigStorageError> {
     let bytes = read_file_to_bytes(file_path)?;
     match file_type {
-        StorageFileSelection::PackageMap => {
+        StorageFileType::PackageMap => {
             let package_table = PackageTable::from_bytes(&bytes)?;
             println!("{:?}", package_table);
         }
-        StorageFileSelection::FlagMap => {
+        StorageFileType::FlagMap => {
             let flag_table = FlagTable::from_bytes(&bytes)?;
             println!("{:?}", flag_table);
         }
-        StorageFileSelection::FlagVal => {
+        StorageFileType::FlagVal => {
             let flag_value = FlagValueList::from_bytes(&bytes)?;
             println!("{:?}", flag_value);
         }
@@ -76,7 +76,7 @@
     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();
+            let file_type = sub_matches.get_one::<StorageFileType>("type").unwrap();
             print_storage_file(file_path, file_type)?
         }
         Some(("list", sub_matches)) => {
diff --git a/tools/aconfig/aconfig_storage_file/src/package_table.rs b/tools/aconfig/aconfig_storage_file/src/package_table.rs
index f7435b0..80d38d8 100644
--- a/tools/aconfig/aconfig_storage_file/src/package_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/package_table.rs
@@ -17,8 +17,8 @@
 //! package table module defines the package table file format and methods for serialization
 //! and deserialization
 
-use crate::AconfigStorageError::{self, BytesParseFail};
-use crate::{get_bucket_index, read_str_from_bytes, read_u32_from_bytes};
+use crate::{get_bucket_index, read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes};
+use crate::{AconfigStorageError, StorageFileType};
 use anyhow::anyhow;
 use std::fmt;
 
@@ -27,6 +27,7 @@
 pub struct PackageTableHeader {
     pub version: u32,
     pub container: String,
+    pub file_type: u8,
     pub file_size: u32,
     pub num_packages: u32,
     pub bucket_offset: u32,
@@ -38,8 +39,11 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         writeln!(
             f,
-            "Version: {}, Container: {}, File Size: {}",
-            self.version, self.container, self.file_size
+            "Version: {}, Container: {}, File Type: {:?}, File Size: {}",
+            self.version,
+            self.container,
+            StorageFileType::try_from(self.file_type),
+            self.file_size
         )?;
         writeln!(
             f,
@@ -58,6 +62,7 @@
         let container_bytes = self.container.as_bytes();
         result.extend_from_slice(&(container_bytes.len() as u32).to_le_bytes());
         result.extend_from_slice(container_bytes);
+        result.extend_from_slice(&self.file_type.to_le_bytes());
         result.extend_from_slice(&self.file_size.to_le_bytes());
         result.extend_from_slice(&self.num_packages.to_le_bytes());
         result.extend_from_slice(&self.bucket_offset.to_le_bytes());
@@ -68,14 +73,21 @@
     /// Deserialize from bytes
     pub fn from_bytes(bytes: &[u8]) -> Result<Self, AconfigStorageError> {
         let mut head = 0;
-        Ok(Self {
+        let table = Self {
             version: read_u32_from_bytes(bytes, &mut head)?,
             container: read_str_from_bytes(bytes, &mut head)?,
+            file_type: read_u8_from_bytes(bytes, &mut head)?,
             file_size: read_u32_from_bytes(bytes, &mut head)?,
             num_packages: read_u32_from_bytes(bytes, &mut head)?,
             bucket_offset: read_u32_from_bytes(bytes, &mut head)?,
             node_offset: read_u32_from_bytes(bytes, &mut head)?,
-        })
+        };
+        if table.file_type != StorageFileType::PackageMap as u8 {
+            return Err(AconfigStorageError::BytesParseFail(anyhow!(
+                "binary file is not a package map"
+            )));
+        }
+        Ok(table)
     }
 }
 
@@ -191,7 +203,12 @@
                 Ok(node)
             })
             .collect::<Result<Vec<_>, AconfigStorageError>>()
-            .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse package table: {}", errmsg)))?;
+            .map_err(|errmsg| {
+                AconfigStorageError::BytesParseFail(anyhow!(
+                    "fail to parse package table: {}",
+                    errmsg
+                ))
+            })?;
 
         let table = Self { header, buckets, nodes };
         Ok(table)
@@ -233,4 +250,16 @@
         let version = read_u32_from_bytes(bytes, &mut head).unwrap();
         assert_eq!(version, 1234)
     }
+
+    #[test]
+    // this test point locks down file type check
+    fn test_file_type_check() {
+        let mut package_table = create_test_package_table();
+        package_table.header.file_type = 123u8;
+        let error = PackageTable::from_bytes(&package_table.as_bytes()).unwrap_err();
+        assert_eq!(
+            format!("{:?}", error),
+            format!("BytesParseFail(binary file is not a package map)")
+        );
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
index 7780044..13637f0 100644
--- a/tools/aconfig/aconfig_storage_file/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -27,6 +27,7 @@
     let header = PackageTableHeader {
         version: 1234,
         container: String::from("system"),
+        file_type: 0,
         file_size: 208,
         num_packages: 3,
         bucket_offset: 30,
@@ -72,6 +73,7 @@
     let header = FlagTableHeader {
         version: 1234,
         container: String::from("system"),
+        file_type: 1,
         file_size: 320,
         num_flags: 8,
         bucket_offset: 30,
@@ -113,6 +115,7 @@
     let header = FlagValueHeader {
         version: 1234,
         container: String::from("system"),
+        file_type: 2,
         file_size: 34,
         num_flags: 8,
         boolean_value_offset: 26,
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 721f9a5..a8fde53 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -74,24 +74,3 @@
     whole_static_libs: ["libaconfig_storage_read_api_cxx_bridge"],
     export_include_dirs: ["include"],
 }
-
-genrule {
-    name: "ro.package.map",
-    out: ["tests/tmp.ro.package.map"],
-    srcs: ["tests/package.map"],
-    cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)",
-}
-
-genrule {
-    name: "ro.flag.map",
-    out: ["tests/tmp.ro.flag.map"],
-    srcs: ["tests/flag.map"],
-    cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)",
-}
-
-genrule {
-    name: "ro.flag.val",
-    out: ["tests/tmp.ro.flag.val"],
-    srcs: ["tests/flag.val"],
-    cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)",
-}
diff --git a/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs b/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs
index cc05557..403badb 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs
@@ -65,7 +65,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::FlagTable;
+    use aconfig_storage_file::{StorageFileType, FlagTable};
 
     // create test baseline, syntactic sugar
     fn new_expected_node(
@@ -88,36 +88,37 @@
         let header = FlagTableHeader {
             version: crate::FILE_VERSION,
             container: String::from("system"),
-            file_size: 320,
+            file_type: StorageFileType::FlagMap as u8,
+            file_size: 321,
             num_flags: 8,
-            bucket_offset: 30,
-            node_offset: 98,
+            bucket_offset: 31,
+            node_offset: 99,
         };
         let buckets: Vec<Option<u32>> = vec![
-            Some(98),
-            Some(124),
+            Some(99),
+            Some(125),
             None,
             None,
             None,
-            Some(177),
+            Some(178),
             None,
-            Some(203),
+            Some(204),
             None,
-            Some(261),
+            Some(262),
             None,
             None,
             None,
             None,
             None,
-            Some(293),
+            Some(294),
             None,
         ];
         let nodes = vec![
             new_expected_node(0, "enabled_ro", 1, 1, None),
-            new_expected_node(0, "enabled_rw", 1, 2, Some(150)),
+            new_expected_node(0, "enabled_rw", 1, 2, Some(151)),
             new_expected_node(1, "disabled_ro", 1, 0, None),
             new_expected_node(2, "enabled_ro", 1, 1, None),
-            new_expected_node(1, "enabled_fixed_ro", 1, 1, Some(235)),
+            new_expected_node(1, "enabled_fixed_ro", 1, 1, Some(236)),
             new_expected_node(1, "enabled_ro", 1, 2, None),
             new_expected_node(2, "enabled_fixed_ro", 1, 0, None),
             new_expected_node(0, "disabled_rw", 1, 0, None),
diff --git a/tools/aconfig/aconfig_storage_read_api/src/flag_value_query.rs b/tools/aconfig/aconfig_storage_read_api/src/flag_value_query.rs
index 6ff6b05..4b7a65e 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/flag_value_query.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/flag_value_query.rs
@@ -48,15 +48,16 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::FlagValueList;
+    use aconfig_storage_file::{StorageFileType, FlagValueList};
 
     pub fn create_test_flag_value_list() -> FlagValueList {
         let header = FlagValueHeader {
             version: crate::FILE_VERSION,
             container: String::from("system"),
-            file_size: 34,
+            file_type: StorageFileType::FlagVal as u8,
+            file_size: 35,
             num_flags: 8,
-            boolean_value_offset: 26,
+            boolean_value_offset: 27,
         };
         let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
         FlagValueList { header, booleans }
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index 3958b2e..cb6a74a 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -43,7 +43,7 @@
 mod test_utils;
 
 pub use aconfig_storage_file::{
-    protos::ProtoStorageFiles, read_u32_from_bytes, AconfigStorageError, StorageFileSelection,
+    protos::ProtoStorageFiles, read_u32_from_bytes, AconfigStorageError, StorageFileType,
     FILE_VERSION,
 };
 pub use flag_table_query::FlagOffset;
@@ -67,7 +67,7 @@
     container: &str,
     package: &str,
 ) -> Result<Option<PackageOffset>, AconfigStorageError> {
-    let mapped_file = get_mapped_file(pb_file, container, StorageFileSelection::PackageMap)?;
+    let mapped_file = get_mapped_file(pb_file, container, StorageFileType::PackageMap)?;
     find_package_offset(&mapped_file, package)
 }
 
@@ -78,7 +78,7 @@
     package_id: u32,
     flag: &str,
 ) -> Result<Option<FlagOffset>, AconfigStorageError> {
-    let mapped_file = get_mapped_file(pb_file, container, StorageFileSelection::FlagMap)?;
+    let mapped_file = get_mapped_file(pb_file, container, StorageFileType::FlagMap)?;
     find_flag_offset(&mapped_file, package_id, flag)
 }
 
@@ -88,7 +88,7 @@
     container: &str,
     offset: u32,
 ) -> Result<bool, AconfigStorageError> {
-    let mapped_file = get_mapped_file(pb_file, container, StorageFileSelection::FlagVal)?;
+    let mapped_file = get_mapped_file(pb_file, container, StorageFileType::FlagVal)?;
     find_boolean_flag_value(&mapped_file, offset)
 }
 
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 e94c56f..67c293c 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
@@ -15,7 +15,7 @@
  */
 
 use std::collections::HashMap;
-use std::fs::File;
+use std::fs::{self, File};
 use std::io::{BufReader, Read};
 use std::sync::{Arc, Mutex};
 
@@ -26,7 +26,7 @@
 use crate::AconfigStorageError::{
     self, FileReadFail, MapFileFail, ProtobufParseFail, StorageFileNotFound,
 };
-use crate::StorageFileSelection;
+use crate::StorageFileType;
 use aconfig_storage_file::protos::{
     storage_record_pb::try_from_binary_proto, ProtoStorageFileInfo, ProtoStorageFiles,
 };
@@ -75,17 +75,15 @@
 
 /// Verify the file is read only and then map it
 fn verify_read_only_and_map(file_path: &str) -> Result<Mmap, AconfigStorageError> {
-    let file = File::open(file_path)
-        .map_err(|errmsg| FileReadFail(anyhow!("Failed to open file {}: {}", file_path, errmsg)))?;
-    let metadata = file.metadata().map_err(|errmsg| {
-        FileReadFail(anyhow!("Failed to find metadata for {}: {}", file_path, errmsg))
-    })?;
-
-    // ensure storage file is read only
-    if !metadata.permissions().readonly() {
+    // ensure file has read only permission
+    let perms = fs::metadata(file_path).unwrap().permissions();
+    if !perms.readonly() {
         return Err(MapFileFail(anyhow!("fail to map non read only storage file {}", file_path)));
     }
 
+    let file = File::open(file_path)
+        .map_err(|errmsg| FileReadFail(anyhow!("Failed to open file {}: {}", file_path, errmsg)))?;
+
     // SAFETY:
     //
     // Mmap constructors are unsafe as it would have undefined behaviors if the file
@@ -95,10 +93,6 @@
     // which means it is read only. Here in the code, we check explicitly that the file
     // being mapped must only have read permission, otherwise, error out, thus making sure
     // it is safe.
-    //
-    // We should remove this restriction if we need to support mmap non read only file in
-    // the future (by making this api unsafe). But for now, all flags are boot stable, so
-    // the boot flag file copy should be readonly.
     unsafe {
         let mapped_file = Mmap::map(&file).map_err(|errmsg| {
             MapFileFail(anyhow!("fail to map storage file {}: {}", file_path, errmsg))
@@ -123,21 +117,21 @@
 pub(crate) fn get_mapped_file(
     location_pb_file: &str,
     container: &str,
-    file_selection: StorageFileSelection,
+    file_selection: StorageFileType,
 ) -> Result<Arc<Mmap>, AconfigStorageError> {
     let mut all_mapped_files = ALL_MAPPED_FILES.lock().unwrap();
     match all_mapped_files.get(container) {
         Some(mapped_files) => Ok(match file_selection {
-            StorageFileSelection::PackageMap => Arc::clone(&mapped_files.package_map),
-            StorageFileSelection::FlagMap => Arc::clone(&mapped_files.flag_map),
-            StorageFileSelection::FlagVal => Arc::clone(&mapped_files.flag_val),
+            StorageFileType::PackageMap => Arc::clone(&mapped_files.package_map),
+            StorageFileType::FlagMap => Arc::clone(&mapped_files.flag_map),
+            StorageFileType::FlagVal => Arc::clone(&mapped_files.flag_val),
         }),
         None => {
             let mapped_files = map_container_storage_files(location_pb_file, container)?;
             let file_ptr = match file_selection {
-                StorageFileSelection::PackageMap => Arc::clone(&mapped_files.package_map),
-                StorageFileSelection::FlagMap => Arc::clone(&mapped_files.flag_map),
-                StorageFileSelection::FlagVal => Arc::clone(&mapped_files.flag_val),
+                StorageFileType::PackageMap => Arc::clone(&mapped_files.package_map),
+                StorageFileType::FlagMap => Arc::clone(&mapped_files.flag_map),
+                StorageFileType::FlagVal => Arc::clone(&mapped_files.flag_val),
             };
             all_mapped_files.insert(container.to_string(), mapped_files);
             Ok(file_ptr)
@@ -196,11 +190,7 @@
         );
     }
 
-    fn map_and_verify(
-        location_pb_file: &str,
-        file_selection: StorageFileSelection,
-        actual_file: &str,
-    ) {
+    fn map_and_verify(location_pb_file: &str, file_selection: StorageFileType, actual_file: &str) {
         let mut opened_file = File::open(actual_file).unwrap();
         let mut content = Vec::new();
         opened_file.read_to_end(&mut content).unwrap();
@@ -238,13 +228,9 @@
 
         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,
-            StorageFileSelection::PackageMap,
-            &ro_files.package_map.name,
-        );
-        map_and_verify(&file_full_path, StorageFileSelection::FlagMap, &ro_files.flag_map.name);
-        map_and_verify(&file_full_path, StorageFileSelection::FlagVal, &ro_files.flag_val.name);
+        map_and_verify(&file_full_path, StorageFileType::PackageMap, &ro_files.package_map.name);
+        map_and_verify(&file_full_path, StorageFileType::FlagMap, &ro_files.flag_map.name);
+        map_and_verify(&file_full_path, StorageFileType::FlagVal, &ro_files.flag_val.name);
     }
 
     #[test]
diff --git a/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs b/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs
index 6d2ed5f7..81feec6 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs
@@ -72,18 +72,19 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::PackageTable;
+    use aconfig_storage_file::{StorageFileType, PackageTable};
 
     pub fn create_test_package_table() -> PackageTable {
         let header = PackageTableHeader {
             version: crate::FILE_VERSION,
             container: String::from("system"),
-            file_size: 208,
+            file_type: StorageFileType::PackageMap as u8,
+            file_size: 209,
             num_packages: 3,
-            bucket_offset: 30,
-            node_offset: 58,
+            bucket_offset: 31,
+            node_offset: 59,
         };
-        let buckets: Vec<Option<u32>> = vec![Some(58), None, None, Some(108), None, None, None];
+        let buckets: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), None, None, None];
         let first_node = PackageTableNode {
             package_name: String::from("com.android.aconfig.storage.test_2"),
             package_id: 1,
@@ -94,7 +95,7 @@
             package_name: String::from("com.android.aconfig.storage.test_1"),
             package_id: 0,
             boolean_offset: 0,
-            next_offset: Some(158),
+            next_offset: Some(159),
         };
         let third_node = PackageTableNode {
             package_name: String::from("com.android.aconfig.storage.test_4"),
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 cc5938d..22f367f 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
@@ -26,14 +26,6 @@
     }
 }
 
-fn set_file_read_write(file: &NamedTempFile) {
-    let mut perms = fs::metadata(file.path()).unwrap().permissions();
-    if perms.readonly() {
-        perms.set_readonly(false);
-        fs::set_permissions(file.path(), perms).unwrap();
-    }
-}
-
 #[allow(dead_code)]
 pub(crate) struct TestStorageFile {
     pub file: NamedTempFile,
@@ -46,8 +38,6 @@
         fs::copy(source_file, file.path())?;
         if read_only {
             set_file_read_only(&file);
-        } else {
-            set_file_read_write(&file);
         }
         let name = file.path().display().to_string();
         Ok(Self { file, name })
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
index 0bfc7bf..ab5ca44 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
@@ -10,9 +10,9 @@
         "libtempfile",
     ],
     data: [
-        ":ro.package.map",
-        ":ro.flag.map",
-        ":ro.flag.val",
+        "package.map",
+        "flag.map",
+        "flag.val",
     ],
     test_suites: ["general-tests"],
 }
@@ -31,9 +31,9 @@
         "liblog",
     ],
     data: [
-        ":ro.package.map",
-        ":ro.flag.map",
-        ":ro.flag.val",
+        "package.map",
+        "flag.map",
+        "flag.val",
     ],
     test_suites: [
         "device-tests",
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/flag.map b/tools/aconfig/aconfig_storage_read_api/tests/flag.map
index 43b6f9a..5507894 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/flag.map
+++ b/tools/aconfig/aconfig_storage_read_api/tests/flag.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/flag.val b/tools/aconfig/aconfig_storage_read_api/tests/flag.val
index f39f8d3..75b8564 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/flag.val
+++ b/tools/aconfig/aconfig_storage_read_api/tests/flag.val
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/package.map b/tools/aconfig/aconfig_storage_read_api/tests/package.map
index 8ed4767..02267e5 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/package.map
+++ b/tools/aconfig/aconfig_storage_read_api/tests/package.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
index 6fecd08..1fd7770 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
@@ -16,58 +16,104 @@
 
 #include <string>
 #include <vector>
+#include <cstdio>
 
+#include <sys/stat.h>
 #include "aconfig_storage/aconfig_storage_read_api.hpp"
 #include <gtest/gtest.h>
 #include <protos/aconfig_storage_metadata.pb.h>
 #include <android-base/file.h>
+#include <android-base/result.h>
 
 using android::aconfig_storage_metadata::storage_files;
+using ::android::base::ReadFileToString;
 using ::android::base::WriteStringToFile;
+using ::android::base::Result;
+using ::android::base::Error;
 using ::aconfig_storage::test_only_api::get_package_offset_impl;
 using ::aconfig_storage::test_only_api::get_flag_offset_impl;
 using ::aconfig_storage::test_only_api::get_boolean_flag_value_impl;
 using ::aconfig_storage::get_storage_file_version;
 
-void write_storage_location_pb_to_file(std::string const& file_path) {
-  auto const test_dir = android::base::GetExecutableDirectory();
-  auto proto = storage_files();
-  auto* info = proto.add_files();
-  info->set_version(0);
-  info->set_container("system");
-  info->set_package_map(test_dir + "/tests/tmp.ro.package.map");
-  info->set_flag_map(test_dir + "/tests/tmp.ro.flag.map");
-  info->set_flag_val(test_dir + "/tests/tmp.ro.flag.val");
-  info->set_timestamp(12345);
+class AconfigStorageTest : public ::testing::Test {
+ protected:
+  Result<std::string> copy_to_ro_temp_file(std::string const& source_file) {
+    auto temp_file = std::string(std::tmpnam(nullptr));
+    auto content = std::string();
+    if (!ReadFileToString(source_file, &content)) {
+      return Error() << "failed to read file: " << source_file;
+    }
+    if (!WriteStringToFile(content, temp_file)) {
+      return Error() << "failed to copy file: " << source_file;
+    }
+    if (chmod(temp_file.c_str(), S_IRUSR | S_IRGRP) == -1) {
+      return Error() << "failed to make file read only";
+    }
+    return temp_file;
+  }
 
-  auto content = std::string();
-  proto.SerializeToString(&content);
-  ASSERT_TRUE(WriteStringToFile(content, file_path))
-      << "Failed to write a file: " << file_path;
-}
+  Result<std::string> write_storage_location_pb_file(std::string const& package_map,
+                                                     std::string const& flag_map,
+                                                     std::string const& flag_val) {
+    auto temp_file = std::tmpnam(nullptr);
+    auto proto = storage_files();
+    auto* info = proto.add_files();
+    info->set_version(0);
+    info->set_container("system");
+    info->set_package_map(package_map);
+    info->set_flag_map(flag_map);
+    info->set_flag_val(flag_val);
+    info->set_timestamp(12345);
 
-TEST(AconfigStorageTest, test_storage_version_query) {
-  auto const test_dir = android::base::GetExecutableDirectory();
-  auto query = get_storage_file_version(test_dir + "/tests/tmp.ro.package.map");
+    auto content = std::string();
+    proto.SerializeToString(&content);
+    if (!WriteStringToFile(content, temp_file)) {
+      return Error() << "failed to write storage records pb file";
+    }
+    return temp_file;
+  }
+
+  void SetUp() override {
+    auto const test_dir = android::base::GetExecutableDirectory();
+    package_map = *copy_to_ro_temp_file(test_dir + "/package.map");
+    flag_map = *copy_to_ro_temp_file(test_dir + "/flag.map");
+    flag_val = *copy_to_ro_temp_file(test_dir + "/flag.val");
+    storage_record_pb = *write_storage_location_pb_file(
+        package_map, flag_map, flag_val);
+  }
+
+  void TearDown() override {
+    std::remove(package_map.c_str());
+    std::remove(flag_map.c_str());
+    std::remove(flag_val.c_str());
+    std::remove(storage_record_pb.c_str());
+  }
+
+  std::string package_map;
+  std::string flag_map;
+  std::string flag_val;
+  std::string storage_record_pb;
+};
+
+
+TEST_F(AconfigStorageTest, test_storage_version_query) {
+  auto query = get_storage_file_version(package_map);
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_EQ(query.version_number, 1);
-  query = get_storage_file_version(test_dir + "/tests/tmp.ro.flag.map");
+  query = get_storage_file_version(flag_map);
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_EQ(query.version_number, 1);
-  query = get_storage_file_version(test_dir + "/tests/tmp.ro.flag.val");
+  query = get_storage_file_version(flag_val);
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_EQ(query.version_number, 1);
 }
 
-TEST(AconfigStorageTest, test_package_offset_query) {
-  auto pb_file = std::string("/tmp/test_package_offset_query.pb");
-  write_storage_location_pb_to_file(pb_file);
-
+TEST_F(AconfigStorageTest, test_package_offset_query) {
   auto query = get_package_offset_impl(
-      pb_file, "system", "com.android.aconfig.storage.test_1");
+      storage_record_pb, "system", "com.android.aconfig.storage.test_1");
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_TRUE(query.package_exists);
@@ -75,7 +121,7 @@
   ASSERT_EQ(query.boolean_offset, 0);
 
   query = get_package_offset_impl(
-      pb_file, "system", "com.android.aconfig.storage.test_2");
+      storage_record_pb, "system", "com.android.aconfig.storage.test_2");
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_TRUE(query.package_exists);
@@ -83,7 +129,7 @@
   ASSERT_EQ(query.boolean_offset, 3);
 
   query = get_package_offset_impl(
-      pb_file, "system", "com.android.aconfig.storage.test_4");
+      storage_record_pb, "system", "com.android.aconfig.storage.test_4");
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_TRUE(query.package_exists);
@@ -91,27 +137,21 @@
   ASSERT_EQ(query.boolean_offset, 6);
 }
 
-TEST(AconfigStorageTest, test_invalid_package_offset_query) {
-  auto pb_file = std::string("/tmp/test_package_offset_query.pb");
-  write_storage_location_pb_to_file(pb_file);
-
+TEST_F(AconfigStorageTest, test_invalid_package_offset_query) {
   auto query = get_package_offset_impl(
-      pb_file, "system", "com.android.aconfig.storage.test_3");
+      storage_record_pb, "system", "com.android.aconfig.storage.test_3");
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_FALSE(query.package_exists);
 
   query = get_package_offset_impl(
-      pb_file, "vendor", "com.android.aconfig.storage.test_1");
+      storage_record_pb, "vendor", "com.android.aconfig.storage.test_1");
   ASSERT_EQ(query.error_message,
             std::string("StorageFileNotFound(Storage file does not exist for vendor)"));
   ASSERT_FALSE(query.query_success);
 }
 
-TEST(AconfigStorageTest, test_flag_offset_query) {
-  auto pb_file = std::string("/tmp/test_package_offset_query.pb");
-  write_storage_location_pb_to_file(pb_file);
-
+TEST_F(AconfigStorageTest, test_flag_offset_query) {
   auto baseline = std::vector<std::tuple<int, std::string, int>>{
     {0, "enabled_ro", 1},
     {0, "enabled_rw", 2},
@@ -123,7 +163,7 @@
     {0, "disabled_rw", 0},
   };
   for (auto const&[package_id, flag_name, expected_offset] : baseline) {
-    auto query = get_flag_offset_impl(pb_file, "system", package_id, flag_name);
+    auto query = get_flag_offset_impl(storage_record_pb, "system", package_id, flag_name);
     ASSERT_EQ(query.error_message, std::string());
     ASSERT_TRUE(query.query_success);
     ASSERT_TRUE(query.flag_exists);
@@ -131,47 +171,39 @@
   }
 }
 
-TEST(AconfigStorageTest, test_invalid_flag_offset_query) {
-  auto pb_file = std::string("/tmp/test_invalid_package_offset_query.pb");
-  write_storage_location_pb_to_file(pb_file);
-
-  auto query = get_flag_offset_impl(pb_file, "system", 0, "none_exist");
+TEST_F(AconfigStorageTest, test_invalid_flag_offset_query) {
+  auto query = get_flag_offset_impl(storage_record_pb, "system", 0, "none_exist");
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_FALSE(query.flag_exists);
 
-  query = get_flag_offset_impl(pb_file, "system", 3, "enabled_ro");
+  query = get_flag_offset_impl(storage_record_pb, "system", 3, "enabled_ro");
   ASSERT_EQ(query.error_message, std::string());
   ASSERT_TRUE(query.query_success);
   ASSERT_FALSE(query.flag_exists);
 
-  query = get_flag_offset_impl(pb_file, "vendor", 0, "enabled_ro");
+  query = get_flag_offset_impl(storage_record_pb, "vendor", 0, "enabled_ro");
   ASSERT_EQ(query.error_message,
             std::string("StorageFileNotFound(Storage file does not exist for vendor)"));
   ASSERT_FALSE(query.query_success);
 }
 
-TEST(AconfigStorageTest, test_boolean_flag_value_query) {
-  auto pb_file = std::string("/tmp/test_boolean_flag_value_query.pb");
-  write_storage_location_pb_to_file(pb_file);
+TEST_F(AconfigStorageTest, test_boolean_flag_value_query) {
   for (int offset = 0; offset < 8; ++offset) {
-    auto query = get_boolean_flag_value_impl(pb_file, "system", offset);
+    auto query = get_boolean_flag_value_impl(storage_record_pb, "system", offset);
     ASSERT_EQ(query.error_message, std::string());
     ASSERT_TRUE(query.query_success);
     ASSERT_FALSE(query.flag_value);
   }
 }
 
-TEST(AconfigStorageTest, test_invalid_boolean_flag_value_query) {
-  auto pb_file = std::string("/tmp/test_invalid_boolean_flag_value_query.pb");
-  write_storage_location_pb_to_file(pb_file);
-
-  auto query = get_boolean_flag_value_impl(pb_file, "vendor", 0);
+TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_query) {
+  auto query = get_boolean_flag_value_impl(storage_record_pb, "vendor", 0);
   ASSERT_EQ(query.error_message,
             std::string("StorageFileNotFound(Storage file does not exist for vendor)"));
   ASSERT_FALSE(query.query_success);
 
-  query = get_boolean_flag_value_impl(pb_file, "system", 8);
+  query = get_boolean_flag_value_impl(storage_record_pb, "system", 8);
   ASSERT_EQ(query.error_message,
             std::string("InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"));
   ASSERT_FALSE(query.query_success);
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
index 4a65876..b178d83 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
@@ -5,22 +5,43 @@
         get_storage_file_version, PackageOffset, ProtoStorageFiles,
     };
     use protobuf::Message;
+    use std::fs;
     use std::io::Write;
     use tempfile::NamedTempFile;
 
-    fn write_storage_location_file() -> NamedTempFile {
-        let text_proto = r#"
-files {
+    pub fn copy_to_ro_temp_file(source_file: &str) -> NamedTempFile {
+        let file = NamedTempFile::new().unwrap();
+        fs::copy(source_file, file.path()).unwrap();
+        let file_name = file.path().display().to_string();
+        let mut perms = fs::metadata(file_name).unwrap().permissions();
+        perms.set_readonly(true);
+        fs::set_permissions(file.path(), perms.clone()).unwrap();
+        file
+    }
+
+    fn write_storage_location_file(
+        package_table: &NamedTempFile,
+        flag_table: &NamedTempFile,
+        flag_value: &NamedTempFile,
+    ) -> NamedTempFile {
+        let text_proto = format!(
+            r#"
+files {{
     version: 0
     container: "system"
-    package_map: "./tests/tmp.ro.package.map"
-    flag_map: "./tests/tmp.ro.flag.map"
-    flag_val: "./tests/tmp.ro.flag.val"
+    package_map: "{}"
+    flag_map: "{}"
+    flag_val: "{}"
     timestamp: 12345
-}
-"#;
+}}
+"#,
+            package_table.path().display(),
+            flag_table.path().display(),
+            flag_value.path().display(),
+        );
+
         let storage_files: ProtoStorageFiles =
-            protobuf::text_format::parse_from_str(text_proto).unwrap();
+            protobuf::text_format::parse_from_str(&text_proto).unwrap();
         let mut binary_proto_bytes = Vec::new();
         storage_files.write_to_vec(&mut binary_proto_bytes).unwrap();
         let mut file = NamedTempFile::new().unwrap();
@@ -30,7 +51,11 @@
 
     #[test]
     fn test_package_offset_query() {
-        let file = write_storage_location_file();
+        let package_table = copy_to_ro_temp_file("./package.map");
+        let flag_table = copy_to_ro_temp_file("./flag.map");
+        let flag_value = copy_to_ro_temp_file("./flag.val");
+
+        let file = write_storage_location_file(&package_table, &flag_table, &flag_value);
         let file_full_path = file.path().display().to_string();
 
         let package_offset = get_package_offset_impl(
@@ -74,7 +99,11 @@
 
     #[test]
     fn test_invalid_package_offset_query() {
-        let file = write_storage_location_file();
+        let package_table = copy_to_ro_temp_file("./package.map");
+        let flag_table = copy_to_ro_temp_file("./flag.map");
+        let flag_value = copy_to_ro_temp_file("./flag.val");
+
+        let file = write_storage_location_file(&package_table, &flag_table, &flag_value);
         let file_full_path = file.path().display().to_string();
 
         let package_offset_option = get_package_offset_impl(
@@ -99,7 +128,11 @@
 
     #[test]
     fn test_flag_offset_query() {
-        let file = write_storage_location_file();
+        let package_table = copy_to_ro_temp_file("./package.map");
+        let flag_table = copy_to_ro_temp_file("./flag.map");
+        let flag_value = copy_to_ro_temp_file("./flag.val");
+
+        let file = write_storage_location_file(&package_table, &flag_table, &flag_value);
         let file_full_path = file.path().display().to_string();
 
         let baseline = vec![
@@ -123,7 +156,11 @@
 
     #[test]
     fn test_invalid_flag_offset_query() {
-        let file = write_storage_location_file();
+        let package_table = copy_to_ro_temp_file("./package.map");
+        let flag_table = copy_to_ro_temp_file("./flag.map");
+        let flag_value = copy_to_ro_temp_file("./flag.val");
+
+        let file = write_storage_location_file(&package_table, &flag_table, &flag_value);
         let file_full_path = file.path().display().to_string();
 
         let flag_offset_option =
@@ -143,7 +180,11 @@
 
     #[test]
     fn test_boolean_flag_value_query() {
-        let file = write_storage_location_file();
+        let package_table = copy_to_ro_temp_file("./package.map");
+        let flag_table = copy_to_ro_temp_file("./flag.map");
+        let flag_value = copy_to_ro_temp_file("./flag.val");
+
+        let file = write_storage_location_file(&package_table, &flag_table, &flag_value);
         let file_full_path = file.path().display().to_string();
 
         let baseline: Vec<bool> = vec![false; 8];
@@ -156,7 +197,11 @@
 
     #[test]
     fn test_invalid_boolean_flag_value_query() {
-        let file = write_storage_location_file();
+        let package_table = copy_to_ro_temp_file("./package.map");
+        let flag_table = copy_to_ro_temp_file("./flag.map");
+        let flag_value = copy_to_ro_temp_file("./flag.val");
+
+        let file = write_storage_location_file(&package_table, &flag_table, &flag_value);
         let file_full_path = file.path().display().to_string();
 
         let err = get_boolean_flag_value_impl(&file_full_path, "vendor", 0u32).unwrap_err();
@@ -174,8 +219,8 @@
 
     #[test]
     fn test_storage_version_query() {
-        assert_eq!(get_storage_file_version("./tests/tmp.ro.package.map").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./tests/tmp.ro.flag.map").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./tests/tmp.ro.flag.val").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./package.map").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./flag.map").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./flag.val").unwrap(), 1);
     }
 }
diff --git a/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs b/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs
index 1e9612a..c2375dd 100644
--- a/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs
+++ b/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.rs
@@ -51,15 +51,16 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::FlagValueList;
+    use aconfig_storage_file::{FlagValueList, StorageFileType};
 
     pub fn create_test_flag_value_list() -> FlagValueList {
         let header = FlagValueHeader {
             version: FILE_VERSION,
             container: String::from("system"),
-            file_size: 34,
+            file_type: StorageFileType::FlagVal as u8,
+            file_size: 35,
             num_flags: 8,
-            boolean_value_offset: 26,
+            boolean_value_offset: 27,
         };
         let booleans: Vec<bool> = vec![false; 8];
         FlagValueList { header, booleans }
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/flag.val b/tools/aconfig/aconfig_storage_write_api/tests/flag.val
index f39f8d3..75b8564 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/flag.val
+++ b/tools/aconfig/aconfig_storage_write_api/tests/flag.val
Binary files differ