Merge "Add bins into the otatools.zip" into main
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index d74e87a..e9c95fd 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -893,12 +893,16 @@
         package com.android.aconfig.test;
 
         import java.util.Arrays;
+        import java.util.HashMap;
+        import java.util.Map;
         import java.util.HashSet;
         import java.util.List;
         import java.util.Set;
         import java.util.function.BiPredicate;
         import java.util.function.Predicate;
 
+        import android.os.Build;
+
         /** @hide */
         public class CustomFeatureFlags implements FeatureFlags {
 
@@ -941,6 +945,19 @@
                     ""
                 )
             );
+
+            private Map<String, Integer> mFinalizedFlags = new HashMap<>(
+                Map.ofEntries(
+                    Map.entry("", Integer.MAX_VALUE)
+                )
+            );
+
+            public boolean isFlagFinalized(String flagName) {
+                if (!mFinalizedFlags.containsKey(flagName)) {
+                    return false;
+                }
+                return Build.VERSION.SDK_INT >= mFinalizedFlags.get(flagName);
+            }
         }
     "#;
 
@@ -1089,11 +1106,14 @@
         package com.android.aconfig.test;
 
         import java.util.Arrays;
+        import java.util.HashMap;
+        import java.util.Map;
         import java.util.HashSet;
         import java.util.List;
         import java.util.Set;
         import java.util.function.BiPredicate;
         import java.util.function.Predicate;
+        import android.os.Build;
 
         /** @hide */
         public class CustomFeatureFlags implements FeatureFlags {
@@ -1137,6 +1157,19 @@
                     ""
                 )
             );
+
+            private Map<String, Integer> mFinalizedFlags = new HashMap<>(
+                Map.ofEntries(
+                    Map.entry("", Integer.MAX_VALUE)
+                )
+            );
+
+            public boolean isFlagFinalized(String flagName) {
+                if (!mFinalizedFlags.containsKey(flagName)) {
+                    return false;
+                }
+                return Build.VERSION.SDK_INT >= mFinalizedFlags.get(flagName);
+            }
         }
     "#;
 
@@ -1296,11 +1329,14 @@
         package com.android.aconfig.test;
 
         import java.util.Arrays;
+        import java.util.HashMap;
+        import java.util.Map;
         import java.util.HashSet;
         import java.util.List;
         import java.util.Set;
         import java.util.function.BiPredicate;
         import java.util.function.Predicate;
+        import android.os.Build;
 
         /** @hide */
         public class CustomFeatureFlags implements FeatureFlags {
@@ -1344,6 +1380,20 @@
                     ""
                 )
             );
+
+            private Map<String, Integer> mFinalizedFlags = new HashMap<>(
+                Map.ofEntries(
+                    Map.entry(Flags.FLAG_DISABLED_RW_EXPORTED, 36),
+                    Map.entry("", Integer.MAX_VALUE)
+                )
+            );
+
+            public boolean isFlagFinalized(String flagName) {
+                if (!mFinalizedFlags.containsKey(flagName)) {
+                    return false;
+                }
+                return Build.VERSION.SDK_INT >= mFinalizedFlags.get(flagName);
+            }
         }
     "#;
 
diff --git a/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template b/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template
index ef18367..c702c9b 100644
--- a/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template
+++ b/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template
@@ -5,11 +5,18 @@
 import android.compat.annotation.UnsupportedAppUsage;
 {{ -endif }}
 import java.util.Arrays;
+{{ -if library_exported }}
+import java.util.HashMap;
+import java.util.Map;
+{{ -endif }}
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.function.BiPredicate;
 import java.util.function.Predicate;
+{{ -if library_exported }}
+import android.os.Build;
+{{ -endif }}
 
 {{ -if single_exported_file }}
 {{ -if library_exported }}
@@ -73,4 +80,24 @@
             ""{# The empty string here is to resolve the ending comma #}
         )
     );
+
+{{ -if library_exported }}
+    private Map<String, Integer> mFinalizedFlags = new HashMap<>(
+        Map.ofEntries(
+            {{ -for item in flag_elements }}
+            {{ -if item.finalized_sdk_present }}
+            Map.entry(Flags.FLAG_{item.flag_name_constant_suffix}, {item.finalized_sdk_value}),
+            {{ -endif }}
+            {{ -endfor }}
+            Map.entry("", Integer.MAX_VALUE){# The empty entry to avoid empty entries #}
+        )
+    );
+
+    public boolean isFlagFinalized(String flagName) \{
+        if (!mFinalizedFlags.containsKey(flagName)) \{
+            return false;
+        }
+        return Build.VERSION.SDK_INT >= mFinalizedFlags.get(flagName);
+    }
+{{ -endif }}
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_info.rs b/tools/aconfig/aconfig_storage_file/src/flag_info.rs
index cf16834..a39b7ed 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_info.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_info.rs
@@ -199,49 +199,28 @@
     };
 
     // this test point locks down the value list serialization
-    // TODO: b/376108268 - Use parameterized tests.
     #[test]
-    fn test_serialization_default() {
-        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
+    fn test_serialization() {
+        for file_version in 1..=MAX_SUPPORTED_FILE_VERSION {
+            let flag_info_list = create_test_flag_info_list(file_version);
 
-        let header: &FlagInfoHeader = &flag_info_list.header;
-        let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
+            let header: &FlagInfoHeader = &flag_info_list.header;
+            let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes());
+            assert!(reinterpreted_header.is_ok());
+            assert_eq!(header, &reinterpreted_header.unwrap());
 
-        let nodes: &Vec<FlagInfoNode> = &flag_info_list.nodes;
-        for node in nodes.iter() {
-            let reinterpreted_node = FlagInfoNode::from_bytes(&node.into_bytes()).unwrap();
-            assert_eq!(node, &reinterpreted_node);
+            let nodes: &Vec<FlagInfoNode> = &flag_info_list.nodes;
+            for node in nodes.iter() {
+                let reinterpreted_node = FlagInfoNode::from_bytes(&node.into_bytes()).unwrap();
+                assert_eq!(node, &reinterpreted_node);
+            }
+
+            let flag_info_bytes = flag_info_list.into_bytes();
+            let reinterpreted_info_list = FlagInfoList::from_bytes(&flag_info_bytes);
+            assert!(reinterpreted_info_list.is_ok());
+            assert_eq!(&flag_info_list, &reinterpreted_info_list.unwrap());
+            assert_eq!(flag_info_bytes.len() as u32, header.file_size);
         }
-
-        let flag_info_bytes = flag_info_list.into_bytes();
-        let reinterpreted_info_list = FlagInfoList::from_bytes(&flag_info_bytes);
-        assert!(reinterpreted_info_list.is_ok());
-        assert_eq!(&flag_info_list, &reinterpreted_info_list.unwrap());
-        assert_eq!(flag_info_bytes.len() as u32, header.file_size);
-    }
-
-    #[test]
-    fn test_serialization_max() {
-        let flag_info_list = create_test_flag_info_list(MAX_SUPPORTED_FILE_VERSION);
-
-        let header: &FlagInfoHeader = &flag_info_list.header;
-        let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
-
-        let nodes: &Vec<FlagInfoNode> = &flag_info_list.nodes;
-        for node in nodes.iter() {
-            let reinterpreted_node = FlagInfoNode::from_bytes(&node.into_bytes()).unwrap();
-            assert_eq!(node, &reinterpreted_node);
-        }
-
-        let flag_info_bytes = flag_info_list.into_bytes();
-        let reinterpreted_info_list = FlagInfoList::from_bytes(&flag_info_bytes);
-        assert!(reinterpreted_info_list.is_ok());
-        assert_eq!(&flag_info_list, &reinterpreted_info_list.unwrap());
-        assert_eq!(flag_info_bytes.len() as u32, header.file_size);
     }
 
     // this test point locks down that version number should be at the top of serialized
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_table.rs b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
index 6fbee02..1b70c49 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
@@ -225,49 +225,28 @@
     };
 
     // this test point locks down the table serialization
-    // TODO: b/376108268 - Use parameterized tests.
     #[test]
-    fn test_serialization_default() {
-        let flag_table = create_test_flag_table(DEFAULT_FILE_VERSION);
+    fn test_serialization() {
+        for file_version in 1..=MAX_SUPPORTED_FILE_VERSION {
+            let flag_table = create_test_flag_table(file_version);
 
-        let header: &FlagTableHeader = &flag_table.header;
-        let reinterpreted_header = FlagTableHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
+            let header: &FlagTableHeader = &flag_table.header;
+            let reinterpreted_header = FlagTableHeader::from_bytes(&header.into_bytes());
+            assert!(reinterpreted_header.is_ok());
+            assert_eq!(header, &reinterpreted_header.unwrap());
 
-        let nodes: &Vec<FlagTableNode> = &flag_table.nodes;
-        for node in nodes.iter() {
-            let reinterpreted_node = FlagTableNode::from_bytes(&node.into_bytes()).unwrap();
-            assert_eq!(node, &reinterpreted_node);
+            let nodes: &Vec<FlagTableNode> = &flag_table.nodes;
+            for node in nodes.iter() {
+                let reinterpreted_node = FlagTableNode::from_bytes(&node.into_bytes()).unwrap();
+                assert_eq!(node, &reinterpreted_node);
+            }
+
+            let flag_table_bytes = flag_table.into_bytes();
+            let reinterpreted_table = FlagTable::from_bytes(&flag_table_bytes);
+            assert!(reinterpreted_table.is_ok());
+            assert_eq!(&flag_table, &reinterpreted_table.unwrap());
+            assert_eq!(flag_table_bytes.len() as u32, header.file_size);
         }
-
-        let flag_table_bytes = flag_table.into_bytes();
-        let reinterpreted_table = FlagTable::from_bytes(&flag_table_bytes);
-        assert!(reinterpreted_table.is_ok());
-        assert_eq!(&flag_table, &reinterpreted_table.unwrap());
-        assert_eq!(flag_table_bytes.len() as u32, header.file_size);
-    }
-
-    #[test]
-    fn test_serialization_max() {
-        let flag_table = create_test_flag_table(MAX_SUPPORTED_FILE_VERSION);
-
-        let header: &FlagTableHeader = &flag_table.header;
-        let reinterpreted_header = FlagTableHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
-
-        let nodes: &Vec<FlagTableNode> = &flag_table.nodes;
-        for node in nodes.iter() {
-            let reinterpreted_node = FlagTableNode::from_bytes(&node.into_bytes()).unwrap();
-            assert_eq!(node, &reinterpreted_node);
-        }
-
-        let flag_table_bytes = flag_table.into_bytes();
-        let reinterpreted_table = FlagTable::from_bytes(&flag_table_bytes);
-        assert!(reinterpreted_table.is_ok());
-        assert_eq!(&flag_table, &reinterpreted_table.unwrap());
-        assert_eq!(flag_table_bytes.len() as u32, header.file_size);
     }
 
     // this test point locks down that version number should be at the top of serialized
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_value.rs b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
index 9a14bec..d73bcfb 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_value.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
@@ -138,37 +138,21 @@
 
     #[test]
     // this test point locks down the value list serialization
-    // TODO: b/376108268 - Use parameterized tests.
-    fn test_serialization_default() {
-        let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
+    fn test_serialization() {
+        for file_version in 1..=MAX_SUPPORTED_FILE_VERSION {
+            let flag_value_list = create_test_flag_value_list(file_version);
 
-        let header: &FlagValueHeader = &flag_value_list.header;
-        let reinterpreted_header = FlagValueHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
+            let header: &FlagValueHeader = &flag_value_list.header;
+            let reinterpreted_header = FlagValueHeader::from_bytes(&header.into_bytes());
+            assert!(reinterpreted_header.is_ok());
+            assert_eq!(header, &reinterpreted_header.unwrap());
 
-        let flag_value_bytes = flag_value_list.into_bytes();
-        let reinterpreted_value_list = FlagValueList::from_bytes(&flag_value_bytes);
-        assert!(reinterpreted_value_list.is_ok());
-        assert_eq!(&flag_value_list, &reinterpreted_value_list.unwrap());
-        assert_eq!(flag_value_bytes.len() as u32, header.file_size);
-    }
-
-    #[test]
-    // this test point locks down the value list serialization
-    fn test_serialization_max() {
-        let flag_value_list = create_test_flag_value_list(MAX_SUPPORTED_FILE_VERSION);
-
-        let header: &FlagValueHeader = &flag_value_list.header;
-        let reinterpreted_header = FlagValueHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
-
-        let flag_value_bytes = flag_value_list.into_bytes();
-        let reinterpreted_value_list = FlagValueList::from_bytes(&flag_value_bytes);
-        assert!(reinterpreted_value_list.is_ok());
-        assert_eq!(&flag_value_list, &reinterpreted_value_list.unwrap());
-        assert_eq!(flag_value_bytes.len() as u32, header.file_size);
+            let flag_value_bytes = flag_value_list.into_bytes();
+            let reinterpreted_value_list = FlagValueList::from_bytes(&flag_value_bytes);
+            assert!(reinterpreted_value_list.is_ok());
+            assert_eq!(&flag_value_list, &reinterpreted_value_list.unwrap());
+            assert_eq!(flag_value_bytes.len() as u32, header.file_size);
+        }
     }
 
     #[test]
diff --git a/tools/aconfig/aconfig_storage_file/src/package_table.rs b/tools/aconfig/aconfig_storage_file/src/package_table.rs
index 21357c7..4d6bd91 100644
--- a/tools/aconfig/aconfig_storage_file/src/package_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/package_table.rs
@@ -287,50 +287,28 @@
 
     #[test]
     // this test point locks down the table serialization
-    // TODO: b/376108268 - Use parameterized tests.
-    fn test_serialization_default() {
-        let package_table = create_test_package_table(DEFAULT_FILE_VERSION);
-        let header: &PackageTableHeader = &package_table.header;
-        let reinterpreted_header = PackageTableHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
+    fn test_serialization() {
+        for file_version in 1..=MAX_SUPPORTED_FILE_VERSION {
+            let package_table = create_test_package_table(file_version);
+            let header: &PackageTableHeader = &package_table.header;
+            let reinterpreted_header = PackageTableHeader::from_bytes(&header.into_bytes());
+            assert!(reinterpreted_header.is_ok());
+            assert_eq!(header, &reinterpreted_header.unwrap());
 
-        let nodes: &Vec<PackageTableNode> = &package_table.nodes;
-        for node in nodes.iter() {
-            let reinterpreted_node =
-                PackageTableNode::from_bytes(&node.into_bytes(header.version), header.version)
-                    .unwrap();
-            assert_eq!(node, &reinterpreted_node);
+            let nodes: &Vec<PackageTableNode> = &package_table.nodes;
+            for node in nodes.iter() {
+                let reinterpreted_node =
+                    PackageTableNode::from_bytes(&node.into_bytes(header.version), header.version)
+                        .unwrap();
+                assert_eq!(node, &reinterpreted_node);
+            }
+
+            let package_table_bytes = package_table.into_bytes();
+            let reinterpreted_table = PackageTable::from_bytes(&package_table_bytes);
+            assert!(reinterpreted_table.is_ok());
+            assert_eq!(&package_table, &reinterpreted_table.unwrap());
+            assert_eq!(package_table_bytes.len() as u32, header.file_size);
         }
-
-        let package_table_bytes = package_table.into_bytes();
-        let reinterpreted_table = PackageTable::from_bytes(&package_table_bytes);
-        assert!(reinterpreted_table.is_ok());
-        assert_eq!(&package_table, &reinterpreted_table.unwrap());
-        assert_eq!(package_table_bytes.len() as u32, header.file_size);
-    }
-
-    #[test]
-    fn test_serialization_max() {
-        let package_table = create_test_package_table(MAX_SUPPORTED_FILE_VERSION);
-        let header: &PackageTableHeader = &package_table.header;
-        let reinterpreted_header = PackageTableHeader::from_bytes(&header.into_bytes());
-        assert!(reinterpreted_header.is_ok());
-        assert_eq!(header, &reinterpreted_header.unwrap());
-
-        let nodes: &Vec<PackageTableNode> = &package_table.nodes;
-        for node in nodes.iter() {
-            let reinterpreted_node =
-                PackageTableNode::from_bytes(&node.into_bytes(header.version), header.version)
-                    .unwrap();
-            assert_eq!(node, &reinterpreted_node);
-        }
-
-        let package_table_bytes = package_table.into_bytes();
-        let reinterpreted_table = PackageTable::from_bytes(&package_table_bytes);
-        assert!(reinterpreted_table.is_ok());
-        assert_eq!(&package_table, &reinterpreted_table.unwrap());
-        assert_eq!(package_table_bytes.len() as u32, header.file_size);
     }
 
     #[test]
diff --git a/tools/aconfig/fake_device_config/src/android/os/Build.java b/tools/aconfig/fake_device_config/src/android/os/Build.java
index 8ec72fb..790ff82 100644
--- a/tools/aconfig/fake_device_config/src/android/os/Build.java
+++ b/tools/aconfig/fake_device_config/src/android/os/Build.java
@@ -18,6 +18,9 @@
 
 public class Build {
     public static class VERSION {
-        public static final int SDK_INT = 0;
+        public static final int SDK_INT = placeholder();
+        private static int placeholder() {
+            throw new UnsupportedOperationException("Stub!");
+        }
     }
 }