Write fingerprint to package map.

Write fingerprint to package.map fingerprint field. This involves some
re-work of how the fingerprint is calculated. Guard the write with a
new arg in create-storage, enable-fingerprint. The default value for
enable-fingerprint is false, and I haven't updated the build code to
pass in anything, so none of this code should run right now. Next step
is to create a build flag and use that to set enable-fingerprint so we
can roll out this change. Then, I will use the fingerprint in codegen as
well.

Bug: 316357686
Test: atest
Change-Id: Ie3a290864d4f971a3f1d070edb4dcefec36f05b6
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 0ad3d97..c7d4d9c 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -427,14 +427,14 @@
                     // 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.
-pub fn compute_flags_fingerprint(flag_names: &mut Vec<String>) -> Result<u64> {
+pub fn compute_flags_fingerprint(flag_names: &mut Vec<String>) -> u64 {
     flag_names.sort();
 
     let mut hasher = SipHasher13::new();
     for flag in flag_names {
         hasher.write(flag.as_bytes());
     }
-    Ok(hasher.finish())
+    hasher.finish()
 }
 
 #[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
@@ -466,7 +466,7 @@
         let mut extracted_flags = extract_flag_names(parsed_flags).unwrap();
         let hash_result = compute_flags_fingerprint(&mut extracted_flags);
 
-        assert_eq!(hash_result.unwrap(), expected_fingerprint);
+        assert_eq!(hash_result, expected_fingerprint);
     }
 
     #[test]
@@ -487,7 +487,7 @@
         let result_from_names = compute_flags_fingerprint(&mut flag_names_vec);
 
         // Assert the same hash is generated for each case.
-        assert_eq!(result_from_parsed_flags.unwrap(), result_from_names.unwrap());
+        assert_eq!(result_from_parsed_flags, result_from_names);
     }
 
     #[test]
@@ -497,9 +497,9 @@
         let second_parsed_flags = crate::test::parse_second_package_flags();
 
         let mut extracted_flags = extract_flag_names(parsed_flags).unwrap();
-        let result_from_parsed_flags = compute_flags_fingerprint(&mut extracted_flags).unwrap();
+        let result_from_parsed_flags = compute_flags_fingerprint(&mut extracted_flags);
         let mut second_extracted_flags = extract_flag_names(second_parsed_flags).unwrap();
-        let second_result = compute_flags_fingerprint(&mut second_extracted_flags).unwrap();
+        let second_result = compute_flags_fingerprint(&mut second_extracted_flags);
 
         // Different flags should have a different fingerprint.
         assert_ne!(result_from_parsed_flags, second_result);
diff --git a/tools/aconfig/aconfig/src/storage/flag_info.rs b/tools/aconfig/aconfig/src/storage/flag_info.rs
index 5d565e8..0b5a67b 100644
--- a/tools/aconfig/aconfig/src/storage/flag_info.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_info.rs
@@ -73,7 +73,7 @@
 
     pub fn create_test_flag_info_list_from_source() -> Result<FlagInfoList> {
         let caches = parse_all_test_flags();
-        let packages = group_flags_by_package(caches.iter());
+        let packages = group_flags_by_package(caches.iter(), DEFAULT_FILE_VERSION);
         create_flag_info("mockup", &packages, DEFAULT_FILE_VERSION)
     }
 
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index 8856eb6..ae5a16c 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -148,7 +148,7 @@
 
     fn create_test_flag_table_from_source() -> Result<FlagTable> {
         let caches = parse_all_test_flags();
-        let packages = group_flags_by_package(caches.iter());
+        let packages = group_flags_by_package(caches.iter(), DEFAULT_FILE_VERSION);
         create_flag_table("mockup", &packages, DEFAULT_FILE_VERSION)
     }
 
diff --git a/tools/aconfig/aconfig/src/storage/flag_value.rs b/tools/aconfig/aconfig/src/storage/flag_value.rs
index 0dd5a9d..065b7e3 100644
--- a/tools/aconfig/aconfig/src/storage/flag_value.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_value.rs
@@ -72,7 +72,7 @@
 
     pub fn create_test_flag_value_list_from_source() -> Result<FlagValueList> {
         let caches = parse_all_test_flags();
-        let packages = group_flags_by_package(caches.iter());
+        let packages = group_flags_by_package(caches.iter(), DEFAULT_FILE_VERSION);
         create_flag_value("mockup", &packages, DEFAULT_FILE_VERSION)
     }
 
diff --git a/tools/aconfig/aconfig/src/storage/mod.rs b/tools/aconfig/aconfig/src/storage/mod.rs
index c7fd55a..14a0957 100644
--- a/tools/aconfig/aconfig/src/storage/mod.rs
+++ b/tools/aconfig/aconfig/src/storage/mod.rs
@@ -22,6 +22,7 @@
 use anyhow::Result;
 use std::collections::{HashMap, HashSet};
 
+use crate::commands::compute_flags_fingerprint;
 use crate::storage::{
     flag_info::create_flag_info, flag_table::create_flag_table, flag_value::create_flag_value,
     package_table::create_package_table,
@@ -59,7 +60,7 @@
     }
 }
 
-pub fn group_flags_by_package<'a, I>(parsed_flags_vec_iter: I) -> Vec<FlagPackage<'a>>
+pub fn group_flags_by_package<'a, I>(parsed_flags_vec_iter: I, version: u32) -> Vec<FlagPackage<'a>>
 where
     I: Iterator<Item = &'a ProtoParsedFlags>,
 {
@@ -76,13 +77,18 @@
         }
     }
 
-    // cacluate boolean flag start index for each package
+    // Calculate boolean flag start index for each package
     let mut boolean_start_index = 0;
     for p in packages.iter_mut() {
         p.boolean_start_index = boolean_start_index;
         boolean_start_index += p.boolean_flags.len() as u32;
 
-        // TODO: b/316357686 - Calculate fingerprint and add to package.
+        if version > 2 {
+            let mut flag_names_vec =
+                p.flag_names.clone().into_iter().map(String::from).collect::<Vec<_>>();
+            let fingerprint = compute_flags_fingerprint(&mut flag_names_vec);
+            p.fingerprint = fingerprint;
+        }
     }
 
     packages
@@ -97,7 +103,7 @@
 where
     I: Iterator<Item = &'a ProtoParsedFlags>,
 {
-    let packages = group_flags_by_package(parsed_flags_vec_iter);
+    let packages = group_flags_by_package(parsed_flags_vec_iter, version);
 
     match file {
         StorageFileType::PackageMap => {
@@ -121,6 +127,8 @@
 
 #[cfg(test)]
 mod tests {
+    use aconfig_storage_file::DEFAULT_FILE_VERSION;
+
     use super::*;
     use crate::Input;
 
@@ -173,7 +181,7 @@
     #[test]
     fn test_flag_package() {
         let caches = parse_all_test_flags();
-        let packages = group_flags_by_package(caches.iter());
+        let packages = group_flags_by_package(caches.iter(), DEFAULT_FILE_VERSION);
 
         for pkg in packages.iter() {
             let pkg_name = pkg.package_name;
diff --git a/tools/aconfig/aconfig/src/storage/package_table.rs b/tools/aconfig/aconfig/src/storage/package_table.rs
index e46607b..53daa7f 100644
--- a/tools/aconfig/aconfig/src/storage/package_table.rs
+++ b/tools/aconfig/aconfig/src/storage/package_table.rs
@@ -112,24 +112,59 @@
 
 #[cfg(test)]
 mod tests {
-    use aconfig_storage_file::DEFAULT_FILE_VERSION;
+    use aconfig_storage_file::{DEFAULT_FILE_VERSION, MAX_SUPPORTED_FILE_VERSION};
 
     use super::*;
     use crate::storage::{group_flags_by_package, tests::parse_all_test_flags};
 
-    pub fn create_test_package_table_from_source() -> Result<PackageTable> {
+    pub fn create_test_package_table_from_source(version: u32) -> Result<PackageTable> {
         let caches = parse_all_test_flags();
-        let packages = group_flags_by_package(caches.iter());
-        create_package_table("mockup", &packages, DEFAULT_FILE_VERSION)
+        let packages = group_flags_by_package(caches.iter(), version);
+        create_package_table("mockup", &packages, version)
     }
 
     #[test]
     // this test point locks down the table creation and each field
-    fn test_table_contents() {
-        let package_table = create_test_package_table_from_source();
-        assert!(package_table.is_ok());
+    fn test_table_contents_default_version() {
+        let package_table_result = create_test_package_table_from_source(DEFAULT_FILE_VERSION);
+        assert!(package_table_result.is_ok());
+        let package_table = package_table_result.unwrap();
+
         let expected_package_table =
             aconfig_storage_file::test_utils::create_test_package_table(DEFAULT_FILE_VERSION);
-        assert_eq!(package_table.unwrap(), expected_package_table);
+
+        assert_eq!(package_table.header, expected_package_table.header);
+        assert_eq!(package_table.buckets, expected_package_table.buckets);
+        for (node, expected_node) in
+            package_table.nodes.iter().zip(expected_package_table.nodes.iter())
+        {
+            assert_eq!(node.package_name, expected_node.package_name);
+            assert_eq!(node.package_id, expected_node.package_id);
+            assert_eq!(node.boolean_start_index, expected_node.boolean_start_index);
+            assert_eq!(node.next_offset, expected_node.next_offset);
+        }
+    }
+
+    #[test]
+    // this test point locks down the table creation and each field
+    fn test_table_contents_max_version() {
+        let package_table_result =
+            create_test_package_table_from_source(MAX_SUPPORTED_FILE_VERSION);
+        assert!(package_table_result.is_ok());
+        let package_table = package_table_result.unwrap();
+
+        let expected_package_table =
+            aconfig_storage_file::test_utils::create_test_package_table(MAX_SUPPORTED_FILE_VERSION);
+
+        assert_eq!(package_table.header, expected_package_table.header);
+        assert_eq!(package_table.buckets, expected_package_table.buckets);
+        for (node, expected_node) in
+            package_table.nodes.iter().zip(expected_package_table.nodes.iter())
+        {
+            assert_eq!(node.package_name, expected_node.package_name);
+            assert_eq!(node.package_id, expected_node.package_id);
+            assert_eq!(node.boolean_start_index, expected_node.boolean_start_index);
+            assert_eq!(node.next_offset, expected_node.next_offset);
+        }
     }
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
index 55780ed..7c603df 100644
--- a/tools/aconfig/aconfig_storage_file/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -46,14 +46,22 @@
     let first_node = PackageTableNode {
         package_name: String::from("com.android.aconfig.storage.test_2"),
         package_id: 1,
-        fingerprint: 0,
+        fingerprint: match version {
+            1 => 0,
+            2 => 4431940502274857964u64,
+            _ => panic!("Unsupported version."),
+        },
         boolean_start_index: 3,
         next_offset: None,
     };
     let second_node = PackageTableNode {
         package_name: String::from("com.android.aconfig.storage.test_1"),
         package_id: 0,
-        fingerprint: 0,
+        fingerprint: match version {
+            1 => 0,
+            2 => 15248948510590158086u64,
+            _ => panic!("Unsupported version."),
+        },
         boolean_start_index: 0,
         next_offset: match version {
             1 => Some(159),
@@ -64,7 +72,11 @@
     let third_node = PackageTableNode {
         package_name: String::from("com.android.aconfig.storage.test_4"),
         package_id: 2,
-        fingerprint: 0,
+        fingerprint: match version {
+            1 => 0,
+            2 => 16233229917711622375u64,
+            _ => panic!("Unsupported version."),
+        },
         boolean_start_index: 6,
         next_offset: None,
     };
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v2/package_v2.map b/tools/aconfig/aconfig_storage_file/tests/data/v2/package_v2.map
index 16f4054..0a9f95e 100644
--- a/tools/aconfig/aconfig_storage_file/tests/data/v2/package_v2.map
+++ b/tools/aconfig/aconfig_storage_file/tests/data/v2/package_v2.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
index 4d7ab2a..5906d8b 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
@@ -116,5 +116,9 @@
         assertTrue(node1.hasPackageFingerprint());
         assertTrue(node2.hasPackageFingerprint());
         assertTrue(node4.hasPackageFingerprint());
+
+        assertEquals(-3197795563119393530L, node1.getPackageFingerprint());
+        assertEquals(4431940502274857964L, node2.getPackageFingerprint());
+        assertEquals(-2213514155997929241L, node4.getPackageFingerprint());
     }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v2/package_v2.map b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/package_v2.map
index 16f4054..0a9f95e 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/data/v2/package_v2.map
+++ b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/package_v2.map
Binary files differ