Merge "Reland linking shared_libs to their modules" into main
diff --git a/backported_fixes/Android.bp b/backported_fixes/Android.bp
new file mode 100644
index 0000000..a20f3fc
--- /dev/null
+++ b/backported_fixes/Android.bp
@@ -0,0 +1,115 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+    default_team: "trendy_team_android_media_reliability",
+}
+
+genrule {
+    name: "applied_backported_fixes",
+    tools: ["applied_backported_fixes_main"],
+    srcs: [":applied_backported_fix_binpbs"],
+    out: ["applied_backported_fixes.prop"],
+    cmd: "$(location applied_backported_fixes_main)" +
+        " -p $(location applied_backported_fixes.prop)" +
+        " $(in)",
+}
+
+java_library {
+    name: "backported_fixes_proto",
+    srcs: [
+        "backported_fixes.proto",
+    ],
+    host_supported: true,
+}
+
+java_library {
+    name: "backported_fixes_common",
+    srcs: ["src/java/com/android/build/backportedfixes/common/*.java"],
+    static_libs: [
+        "backported_fixes_proto",
+        "guava",
+    ],
+    host_supported: true,
+}
+
+java_test_host {
+    name: "backported_fixes_common_test",
+    srcs: ["tests/java/com/android/build/backportedfixes/common/*.java"],
+    static_libs: [
+        "backported_fixes_common",
+        "backported_fixes_proto",
+        "junit",
+        "truth",
+        "truth-liteproto-extension",
+        "truth-proto-extension",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+    test_suites: ["general-tests"],
+}
+
+java_library {
+    name: "applied_backported_fixes_lib",
+    srcs: ["src/java/com/android/build/backportedfixes/*.java"],
+    static_libs: [
+        "backported_fixes_common",
+        "backported_fixes_proto",
+        "jcommander",
+        "guava",
+    ],
+    host_supported: true,
+}
+
+java_binary_host {
+    name: "applied_backported_fixes_main",
+    main_class: "com.android.build.backportedfixes.Main",
+    static_libs: [
+        "applied_backported_fixes_lib",
+    ],
+}
+
+java_test_host {
+    name: "applied_backported_fixes_test",
+    srcs: ["tests/java/com/android/build/backportedfixes/*.java"],
+    static_libs: [
+        "applied_backported_fixes_lib",
+        "backported_fixes_proto",
+        "junit",
+        "truth",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+    test_suites: ["general-tests"],
+}
+
+gensrcs {
+    name: "applied_backported_fix_binpbs",
+    tools: ["aprotoc"],
+    srcs: [
+        "applied_fixes/*.txtpb",
+    ],
+    tool_files: [
+        "backported_fixes.proto",
+    ],
+    output_extension: "binpb",
+    cmd: "$(location aprotoc)  " +
+        " --encode=com.android.build.backportedfixes.BackportedFix" +
+        "  $(location backported_fixes.proto)" +
+        " < $(in)" +
+        " > $(out); echo $(out)",
+}
diff --git a/backported_fixes/OWNERS b/backported_fixes/OWNERS
new file mode 100644
index 0000000..ac176bf
--- /dev/null
+++ b/backported_fixes/OWNERS
@@ -0,0 +1,3 @@
+essick@google.com
+nchalko@google.com
+portmannc@google.com
diff --git a/backported_fixes/applied_fixes/ki350037023.txtpb b/backported_fixes/applied_fixes/ki350037023.txtpb
new file mode 100644
index 0000000..456a7ae
--- /dev/null
+++ b/backported_fixes/applied_fixes/ki350037023.txtpb
@@ -0,0 +1,19 @@
+# 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.
+#
+# proto-file: ../backported_fixes.proto
+# proto-message: BackportedFix
+
+known_issue: 350037023
+alias: 1
diff --git a/backported_fixes/backported_fixes.proto b/backported_fixes/backported_fixes.proto
new file mode 100644
index 0000000..91618ee
--- /dev/null
+++ b/backported_fixes/backported_fixes.proto
@@ -0,0 +1,37 @@
+// 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.
+
+syntax = "proto2";
+
+package com.android.build.backportedfixes;
+
+option java_multiple_files = true;
+
+// A list of backported fixes.
+message BackportedFixes {
+  repeated BackportedFix fixes = 1;
+}
+
+// A known issue approved for reporting Build.getBackportedFixStatus
+message BackportedFix {
+
+  // The issue id from the public bug tracker
+  // https://issuetracker.google.com/issues/{known_issue}
+  optional int64 known_issue = 1;
+  // The alias for the known issue.
+  // 1 - 1023 are valid aliases
+  // Must be unique across all backported fixes.
+  optional int32 alias = 2;
+}
+
diff --git a/backported_fixes/src/java/com/android/build/backportedfixes/Main.java b/backported_fixes/src/java/com/android/build/backportedfixes/Main.java
new file mode 100644
index 0000000..79148cc
--- /dev/null
+++ b/backported_fixes/src/java/com/android/build/backportedfixes/Main.java
@@ -0,0 +1,79 @@
+
+/*
+ * 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 com.android.build.backportedfixes;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.android.build.backportedfixes.common.ClosableCollection;
+import com.android.build.backportedfixes.common.Parser;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.converters.FileConverter;
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public final class Main {
+    @Parameter(description = "BackportedFix proto binary files", converter = FileConverter.class,
+            required = true)
+    List<File> fixFiles;
+    @Parameter(description = "The file to write the property value to.",
+            names = {"--property_file", "-p"}, converter = FileConverter.class, required = true)
+    File propertyFile;
+
+    public static void main(String... argv) throws Exception {
+        Main main = new Main();
+        JCommander.newBuilder().addObject(main).build().parse(argv);
+        main.run();
+    }
+
+    Main() {
+    }
+
+    private void run() throws Exception {
+        try (var fixStreams = ClosableCollection.wrap(Parser.getFileInputStreams(fixFiles));
+             var out = Files.newWriter(propertyFile, UTF_8)) {
+            var fixes = Parser.parseBackportedFixes(fixStreams.getCollection());
+            writeFixesAsAliasBitSet(fixes, out);
+        }
+    }
+
+    static void writeFixesAsAliasBitSet(BackportedFixes fixes, Writer out) {
+        PrintWriter printWriter = new PrintWriter(out);
+        printWriter.println("# The following backported fixes have been applied");
+        for (var f : fixes.getFixesList()) {
+            printWriter.printf("# https://issuetracker.google.com/issues/%d with alias %d",
+                    f.getKnownIssue(), f.getAlias());
+            printWriter.println();
+        }
+        var bsArray = Parser.getBitSetArray(
+                fixes.getFixesList().stream().mapToInt(BackportedFix::getAlias).toArray());
+        String bsString = Arrays.stream(bsArray).mapToObj(Long::toString).collect(
+                Collectors.joining(","));
+        printWriter.printf("ro.build.backported_fixes.alias_bitset.long_list=%s", bsString);
+        printWriter.println();
+        if (printWriter.checkError()) {
+            throw new RuntimeException("There was an error writing to " + out.toString());
+        }
+    }
+}
diff --git a/backported_fixes/src/java/com/android/build/backportedfixes/common/ClosableCollection.java b/backported_fixes/src/java/com/android/build/backportedfixes/common/ClosableCollection.java
new file mode 100644
index 0000000..75b6730
--- /dev/null
+++ b/backported_fixes/src/java/com/android/build/backportedfixes/common/ClosableCollection.java
@@ -0,0 +1,67 @@
+/*
+ * 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 com.android.build.backportedfixes.common;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/** An AutoCloseable holder for a collection of AutoCloseables. */
+public final class ClosableCollection<T extends AutoCloseable, C extends Collection<T>> implements
+        AutoCloseable {
+    C source;
+
+    /** Makes the collection AutoCloseable. */
+    public static <T extends AutoCloseable, C extends Collection<T>> ClosableCollection<T, C> wrap(
+            C source) {
+        return new ClosableCollection<>(source);
+    }
+
+    private ClosableCollection(C source) {
+        this.source = source;
+    }
+
+    /** Get the source collection. */
+    public C getCollection() {
+        return source;
+    }
+
+    /**
+     * Closes each item in the collection.
+     *
+     * @throws Exception if any close throws an an exception, a new exception is thrown with
+     *                   all the exceptions thrown closing the streams added as a suppressed
+     *                   exceptions.
+     */
+    @Override
+    public void close() throws Exception {
+        var failures = new ArrayList<Exception>();
+        for (T t : source) {
+            try {
+                t.close();
+            } catch (Exception e) {
+                failures.add(e);
+            }
+        }
+        if (!failures.isEmpty()) {
+            Exception e = new Exception(
+                    "%d of %d failed while closing".formatted(failures.size(), source.size()));
+            failures.forEach(e::addSuppressed);
+            throw e;
+        }
+    }
+}
diff --git a/backported_fixes/src/java/com/android/build/backportedfixes/common/Parser.java b/backported_fixes/src/java/com/android/build/backportedfixes/common/Parser.java
new file mode 100644
index 0000000..6b08b8f
--- /dev/null
+++ b/backported_fixes/src/java/com/android/build/backportedfixes/common/Parser.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.android.build.backportedfixes.common;
+
+import com.android.build.backportedfixes.BackportedFix;
+import com.android.build.backportedfixes.BackportedFixes;
+
+import com.google.common.collect.ImmutableList;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.BitSet;
+import java.util.List;
+
+
+/** Static utilities for working with {@link BackportedFixes}. */
+public final class Parser {
+
+    /** Creates list of FileInputStreams for a list of files. */
+    public static ImmutableList<FileInputStream> getFileInputStreams(List<File> fixFiles) throws
+            FileNotFoundException {
+        var streams = ImmutableList.<FileInputStream>builder();
+        for (var f : fixFiles) {
+            streams.add(new FileInputStream(f));
+        }
+        return streams.build();
+    }
+
+    /** Converts a list of backported fix aliases into a long array representing a {@link BitSet} */
+    public static long[] getBitSetArray(int[] aliases) {
+        BitSet bs = new BitSet();
+        for (int a : aliases) {
+            bs.set(a);
+        }
+        return bs.toLongArray();
+    }
+
+    /**
+     * Creates a {@link BackportedFixes} from a list of {@link BackportedFix} binary proto streams.
+     */
+    public static BackportedFixes parseBackportedFixes(List<? extends InputStream> fixStreams)
+            throws
+            IOException {
+        var fixes = BackportedFixes.newBuilder();
+        for (var s : fixStreams) {
+            BackportedFix fix = BackportedFix.parseFrom(s);
+            fixes.addFixes(fix);
+            s.close();
+        }
+        return fixes.build();
+    }
+
+    private Parser() {
+    }
+}
diff --git a/backported_fixes/tests/java/com/android/build/backportedfixes/MainTest.java b/backported_fixes/tests/java/com/android/build/backportedfixes/MainTest.java
new file mode 100644
index 0000000..84061e1
--- /dev/null
+++ b/backported_fixes/tests/java/com/android/build/backportedfixes/MainTest.java
@@ -0,0 +1,64 @@
+
+/*
+ * 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 com.android.build.backportedfixes;
+
+import com.google.common.truth.Truth;
+
+import org.junit.Test;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/** Tests for {@link Main}. */
+public class MainTest {
+
+
+    @Test
+    public void writeFixesAsAliasBitSet_default() {
+        BackportedFixes fixes = BackportedFixes.newBuilder().build();
+        var result = new StringWriter();
+
+        Main.writeFixesAsAliasBitSet(fixes, new PrintWriter(result));
+
+        Truth.assertThat(result.toString())
+                .isEqualTo("""
+                        # The following backported fixes have been applied
+                        ro.build.backported_fixes.alias_bitset.long_list=
+                        """);
+    }
+
+    @Test
+    public void writeFixesAsAliasBitSet_some() {
+        BackportedFixes fixes = BackportedFixes.newBuilder()
+                .addFixes(BackportedFix.newBuilder().setKnownIssue(1234L).setAlias(1))
+                .addFixes(BackportedFix.newBuilder().setKnownIssue(3L).setAlias(65))
+                .addFixes(BackportedFix.newBuilder().setKnownIssue(4L).setAlias(67))
+                .build();
+        var result = new StringWriter();
+
+        Main.writeFixesAsAliasBitSet(fixes, new PrintWriter(result));
+
+        Truth.assertThat(result.toString())
+                .isEqualTo("""
+                        # The following backported fixes have been applied
+                        # https://issuetracker.google.com/issues/1234 with alias 1
+                        # https://issuetracker.google.com/issues/3 with alias 65
+                        # https://issuetracker.google.com/issues/4 with alias 67
+                        ro.build.backported_fixes.alias_bitset.long_list=2,10
+                        """);
+    }
+}
diff --git a/backported_fixes/tests/java/com/android/build/backportedfixes/common/CloseableCollectionTest.java b/backported_fixes/tests/java/com/android/build/backportedfixes/common/CloseableCollectionTest.java
new file mode 100644
index 0000000..d3d84a8
--- /dev/null
+++ b/backported_fixes/tests/java/com/android/build/backportedfixes/common/CloseableCollectionTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.android.build.backportedfixes.common;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.truth.Correspondence;
+import com.google.common.truth.Truth;
+
+import org.junit.Test;
+
+/** Tests for {@link ClosableCollection}. */
+public class CloseableCollectionTest {
+
+    private static class FakeCloseable implements AutoCloseable {
+        private final boolean throwOnClose;
+        private final String name;
+
+
+        private boolean isClosed = false;
+
+        private FakeCloseable(String name, boolean throwOnClose) {
+            this.name = name;
+            this.throwOnClose = throwOnClose;
+
+        }
+
+        private static FakeCloseable named(String name) {
+            return new FakeCloseable(name, false);
+        }
+
+        private static FakeCloseable failing(String name) {
+            return new FakeCloseable(name, true);
+        }
+
+        public boolean isClosed() {
+            return isClosed;
+        }
+
+        @Override
+        public void close() throws Exception {
+            if (throwOnClose) {
+                throw new Exception(name + " close failed");
+            }
+            isClosed = true;
+        }
+    }
+
+
+    @Test
+    public void bothClosed() throws Exception {
+        var c = ImmutableSet.of(FakeCloseable.named("foo"), FakeCloseable.named("bar"));
+        try (var cc = ClosableCollection.wrap(c);) {
+            Truth.assertThat(cc.getCollection()).isSameInstanceAs(c);
+        }
+        Truth.assertThat(c)
+                .comparingElementsUsing(
+                        Correspondence.transforming(FakeCloseable::isClosed, "is closed"))
+                .containsExactly(true, true);
+    }
+
+    @Test
+    public void bothFailed() {
+        var c = ImmutableSet.of(FakeCloseable.failing("foo"), FakeCloseable.failing("bar"));
+
+        try {
+            try (var cc = ClosableCollection.wrap(c);) {
+                Truth.assertThat(cc.getCollection()).isSameInstanceAs(c);
+            }
+        } catch (Exception e) {
+            Truth.assertThat(e).hasMessageThat().isEqualTo("2 of 2 failed while closing");
+            Truth.assertThat(e.getSuppressed())
+                    .asList()
+                    .comparingElementsUsing(
+                            Correspondence.transforming(Exception::getMessage, "has a message of "))
+                    .containsExactly("foo close failed", "bar close failed");
+        }
+    }
+}
diff --git a/backported_fixes/tests/java/com/android/build/backportedfixes/common/ParserTest.java b/backported_fixes/tests/java/com/android/build/backportedfixes/common/ParserTest.java
new file mode 100644
index 0000000..444e694
--- /dev/null
+++ b/backported_fixes/tests/java/com/android/build/backportedfixes/common/ParserTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.build.backportedfixes.common;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
+
+import com.android.build.backportedfixes.BackportedFix;
+import com.android.build.backportedfixes.BackportedFixes;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/** Tests for {@link Parser}.*/
+public class ParserTest {
+
+    @Test
+    public void getFileInputStreams() throws IOException {
+        var results = Parser.getFileInputStreams(
+                ImmutableList.of(Files.createTempFile("test", null).toFile()));
+        assertThat(results).isNotEmpty();
+    }
+
+
+    @Test
+    public void getBitSetArray_empty() {
+        var results = Parser.getBitSetArray(new int[]{});
+        assertThat(results).isEmpty();
+    }
+
+    @Test
+    public void getBitSetArray_2_3_64() {
+        var results = Parser.getBitSetArray(new int[]{2,3,64});
+        assertThat(results).asList().containsExactly(12L,1L).inOrder();
+    }
+
+    @Test
+    public void parseBackportedFixes_empty() throws IOException {
+        var result = Parser.parseBackportedFixes(ImmutableList.of());
+        assertThat(result).isEqualTo(BackportedFixes.getDefaultInstance());
+    }
+
+    @Test
+    public void parseBackportedFixes_oneBlank() throws IOException {
+        var result = Parser.parseBackportedFixes(
+                ImmutableList.of(inputStream(BackportedFix.getDefaultInstance())));
+
+        assertThat(result).isEqualTo(
+                BackportedFixes.newBuilder()
+                        .addFixes(BackportedFix.getDefaultInstance())
+                        .build());
+    }
+
+    @Test
+    public void parseBackportedFixes_two() throws IOException {
+        BackportedFix ki123 = BackportedFix.newBuilder()
+                .setKnownIssue(123)
+                .setAlias(1)
+                .build();
+        BackportedFix ki456 = BackportedFix.newBuilder()
+                .setKnownIssue(456)
+                .setAlias(2)
+                .build();
+        var result = Parser.parseBackportedFixes(
+                ImmutableList.of(inputStream(ki123), inputStream(ki456)));
+        assertThat(result).isEqualTo(
+                BackportedFixes.newBuilder()
+                        .addFixes(ki123)
+                        .addFixes(ki456)
+                        .build());
+    }
+
+    private static ByteArrayInputStream inputStream(BackportedFix f) {
+        return new ByteArrayInputStream(f.toByteArray());
+    }
+}
diff --git a/ci/Android.bp b/ci/Android.bp
index 0dfbd37..3f28be4 100644
--- a/ci/Android.bp
+++ b/ci/Android.bp
@@ -25,7 +25,7 @@
         "build_test_suites_test.py",
     ],
     libs: [
-        "build_test_suites",
+        "build_test_suites_lib",
         "pyfakefs",
         "ci_test_lib",
     ],
@@ -56,7 +56,7 @@
         "build_test_suites_local_test.py",
     ],
     libs: [
-        "build_test_suites",
+        "build_test_suites_lib",
         "pyfakefs",
         "ci_test_lib",
     ],
@@ -79,7 +79,7 @@
         "optimized_targets_test.py",
     ],
     libs: [
-        "build_test_suites",
+        "build_test_suites_lib",
         "pyfakefs",
     ],
     test_options: {
@@ -95,7 +95,7 @@
     },
 }
 
-python_library_host {
+python_binary_host {
     name: "build_test_suites",
     srcs: [
         "build_test_suites.py",
@@ -103,6 +103,28 @@
         "test_mapping_module_retriever.py",
         "build_context.py",
         "test_discovery_agent.py",
+        "metrics_agent.py",
+        "buildbot.py",
+    ],
+    main: "build_test_suites.py",
+    libs: [
+        "soong-metrics-proto-py",
+    ],
+}
+
+python_library_host {
+    name: "build_test_suites_lib",
+    srcs: [
+        "build_test_suites.py",
+        "optimized_targets.py",
+        "test_mapping_module_retriever.py",
+        "build_context.py",
+        "test_discovery_agent.py",
+        "metrics_agent.py",
+        "buildbot.py",
+    ],
+    libs: [
+        "soong-metrics-proto-py",
     ],
 }
 
diff --git a/ci/build_context.py b/ci/build_context.py
index cc48d53..c7a1def 100644
--- a/ci/build_context.py
+++ b/ci/build_context.py
@@ -47,6 +47,9 @@
       self.is_test_mapping = False
       self.test_mapping_test_groups = set()
       self.file_download_options = set()
+      self.name = test_info_dict.get('name')
+      self.command = test_info_dict.get('command')
+      self.extra_options = test_info_dict.get('extraOptions')
       for opt in test_info_dict.get('extraOptions', []):
         key = opt.get('key')
         if key == 'test-mapping-test-group':
diff --git a/ci/build_test_suites b/ci/build_test_suites
index 5aaf2f4..9d11268 100755
--- a/ci/build_test_suites
+++ b/ci/build_test_suites
@@ -1,4 +1,4 @@
-#!prebuilts/build-tools/linux-x86/bin/py3-cmd -B
+#!/usr/bin/env bash
 #
 # Copyright 2024, The Android Open Source Project
 #
@@ -14,7 +14,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import build_test_suites
-import sys
-
-build_test_suites.main(sys.argv[1:])
+build/soong/soong_ui.bash --make-mode build_test_suites || exit $?
+$(build/soong/soong_ui.bash --dumpvar-mode HOST_OUT)/bin/build_test_suites $@ || exit $?
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index b8c4a38..cd9d76d 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -20,11 +20,14 @@
 import logging
 import os
 import pathlib
+import re
 import subprocess
 import sys
 from typing import Callable
 from build_context import BuildContext
 import optimized_targets
+import metrics_agent
+import test_discovery_agent
 
 
 REQUIRED_ENV_VARS = frozenset(['TARGET_PRODUCT', 'TARGET_RELEASE', 'TOP'])
@@ -70,7 +73,24 @@
 
     build_targets = set()
     packaging_commands_getters = []
+    test_discovery_zip_regexes = set()
+    optimization_rationale = ''
+    try:
+      # Do not use these regexes for now, only run this to collect data on what
+      # would be optimized.
+      test_discovery_zip_regexes = self._get_test_discovery_zip_regexes()
+      logging.info(f'Discovered test discovery regexes: {test_discovery_zip_regexes}')
+    except test_discovery_agent.TestDiscoveryError as e:
+      optimization_rationale = e.message
+      logging.warning(f'Unable to perform test discovery: {optimization_rationale}')
     for target in self.args.extra_targets:
+      if optimization_rationale:
+        get_metrics_agent().report_unoptimized_target(target, optimization_rationale)
+      else:
+        regex = r'\b(%s)\b' % re.escape(target)
+        if any(re.search(regex, opt) for opt in test_discovery_zip_regexes):
+          get_metrics_agent().report_optimized_target(target)
+
       if self._unused_target_exclusion_enabled(
           target
       ) and not self.build_context.build_target_used(target):
@@ -97,6 +117,34 @@
         in self.build_context.enabled_build_features
     )
 
+  def _get_test_discovery_zip_regexes(self) -> set[str]:
+    build_target_regexes = set()
+    for test_info in self.build_context.test_infos:
+      tf_command = self._build_tf_command(test_info)
+      discovery_agent = test_discovery_agent.TestDiscoveryAgent(tradefed_args=tf_command)
+      for regex in discovery_agent.discover_test_zip_regexes():
+        build_target_regexes.add(regex)
+    return build_target_regexes
+
+
+  def _build_tf_command(self, test_info) -> list[str]:
+    command = [test_info.command]
+    for extra_option in test_info.extra_options:
+      if not extra_option.get('key'):
+        continue
+      arg_key = '--' + extra_option.get('key')
+      if arg_key == '--build-id':
+        command.append(arg_key)
+        command.append(os.environ.get('BUILD_NUMBER'))
+        continue
+      if extra_option.get('values'):
+        for value in extra_option.get('values'):
+          command.append(arg_key)
+          command.append(value)
+      else:
+        command.append(arg_key)
+
+    return command
 
 @dataclass(frozen=True)
 class BuildPlan:
@@ -113,19 +161,27 @@
   Returns:
     The exit code of the build.
   """
-  args = parse_args(argv)
-  check_required_env()
-  build_context = BuildContext(load_build_context())
-  build_planner = BuildPlanner(
-      build_context, args, optimized_targets.OPTIMIZED_BUILD_TARGETS
-  )
-  build_plan = build_planner.create_build_plan()
+  get_metrics_agent().analysis_start()
+  try:
+    args = parse_args(argv)
+    check_required_env()
+    build_context = BuildContext(load_build_context())
+    build_planner = BuildPlanner(
+        build_context, args, optimized_targets.OPTIMIZED_BUILD_TARGETS
+    )
+    build_plan = build_planner.create_build_plan()
+  except:
+    raise
+  finally:
+    get_metrics_agent().analysis_end()
 
   try:
     execute_build_plan(build_plan)
   except BuildFailureError as e:
     logging.error('Build command failed! Check build_log for details.')
     return e.return_code
+  finally:
+    get_metrics_agent().end_reporting()
 
   return 0
 
@@ -183,12 +239,15 @@
   except subprocess.CalledProcessError as e:
     raise BuildFailureError(e.returncode) from e
 
-  for packaging_commands_getter in build_plan.packaging_commands_getters:
-    try:
+  get_metrics_agent().packaging_start()
+  try:
+    for packaging_commands_getter in build_plan.packaging_commands_getters:
       for packaging_command in packaging_commands_getter():
         run_command(packaging_command)
-    except subprocess.CalledProcessError as e:
-      raise BuildFailureError(e.returncode) from e
+  except subprocess.CalledProcessError as e:
+    raise BuildFailureError(e.returncode) from e
+  finally:
+    get_metrics_agent().packaging_end()
 
 
 def get_top() -> pathlib.Path:
@@ -199,6 +258,10 @@
   subprocess.run(args=args, check=True, stdout=stdout)
 
 
+def get_metrics_agent():
+  return metrics_agent.MetricsAgent.instance()
+
+
 def main(argv):
   dist_dir = os.environ.get('DIST_DIR')
   if dist_dir:
@@ -209,3 +272,7 @@
         filename=log_file,
     )
   sys.exit(build_test_suites(argv))
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/ci/build_test_suites_test.py b/ci/build_test_suites_test.py
index 2afaab7..26f4316 100644
--- a/ci/build_test_suites_test.py
+++ b/ci/build_test_suites_test.py
@@ -37,6 +37,8 @@
 import ci_test_lib
 import optimized_targets
 from pyfakefs import fake_filesystem_unittest
+import metrics_agent
+import test_discovery_agent
 
 
 class BuildTestSuitesTest(fake_filesystem_unittest.TestCase):
@@ -52,6 +54,10 @@
     self.addCleanup(subprocess_run_patcher.stop)
     self.mock_subprocess_run = subprocess_run_patcher.start()
 
+    metrics_agent_finalize_patcher = mock.patch('metrics_agent.MetricsAgent.end_reporting')
+    self.addCleanup(metrics_agent_finalize_patcher.stop)
+    self.mock_metrics_agent_end = metrics_agent_finalize_patcher.start()
+
     self._setup_working_build_env()
 
   def test_missing_target_release_env_var_raises(self):
@@ -256,6 +262,12 @@
     def get_enabled_flag(self):
       return f'{self.target}_enabled'
 
+  def setUp(self):
+    test_discovery_agent_patcher = mock.patch('test_discovery_agent.TestDiscoveryAgent.discover_test_zip_regexes')
+    self.addCleanup(test_discovery_agent_patcher.stop)
+    self.mock_test_discovery_agent_end = test_discovery_agent_patcher.start()
+
+
   def test_build_optimization_off_builds_everything(self):
     build_targets = {'target_1', 'target_2'}
     build_planner = self.create_build_planner(
diff --git a/ci/metrics_agent.py b/ci/metrics_agent.py
new file mode 100644
index 0000000..bc2479e
--- /dev/null
+++ b/ci/metrics_agent.py
@@ -0,0 +1,116 @@
+# Copyright 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.
+
+"""MetricsAgent is a singleton class that collects metrics for optimized build."""
+
+from enum import Enum
+import time
+import metrics_pb2
+import os
+import logging
+
+
+class MetricsAgent:
+  _SOONG_METRICS_PATH = 'logs/soong_metrics'
+  _DIST_DIR = 'DIST_DIR'
+  _instance = None
+
+  def __init__(self):
+    raise RuntimeError(
+        'MetricsAgent cannot be instantialized, use instance() instead'
+    )
+
+  @classmethod
+  def instance(cls):
+    if not cls._instance:
+      cls._instance = cls.__new__(cls)
+      cls._instance._proto = metrics_pb2.OptimizedBuildMetrics()
+      cls._instance._init_proto()
+      cls._instance._target_results = dict()
+
+    return cls._instance
+
+  def _init_proto(self):
+    self._proto.analysis_perf.name = 'Optimized build analysis time.'
+    self._proto.packaging_perf.name = 'Optimized build total packaging time.'
+
+  def analysis_start(self):
+    self._proto.analysis_perf.start_time = time.time_ns()
+
+  def analysis_end(self):
+    self._proto.analysis_perf.real_time = (
+        time.time_ns() - self._proto.analysis_perf.start_time
+    )
+
+  def packaging_start(self):
+    self._proto.packaging_perf.start_time = time.time_ns()
+
+  def packaging_end(self):
+    self._proto.packaging_perf.real_time = (
+        time.time_ns() - self._proto.packaging_perf.start_time
+    )
+
+  def report_optimized_target(self, name: str):
+    target_result = metrics_pb2.OptimizedBuildMetrics.TargetOptimizationResult()
+    target_result.name = name
+    target_result.optimized = True
+    self._target_results[name] = target_result
+
+  def report_unoptimized_target(self, name: str, optimization_rationale: str):
+    target_result = metrics_pb2.OptimizedBuildMetrics.TargetOptimizationResult()
+    target_result.name = name
+    target_result.optimization_rationale = optimization_rationale
+    target_result.optimized = False
+    self._target_results[name] = target_result
+
+  def target_packaging_start(self, name: str):
+    target_result = self._target_results.get(name)
+    target_result.packaging_perf.start_time = time.time_ns()
+    self._target_results[name] = target_result
+
+  def target_packaging_end(self, name: str):
+    target_result = self._target_results.get(name)
+    target_result.packaging_perf.real_time = (
+        time.time_ns() - target_result.packaging_perf.start_time
+    )
+
+  def add_target_artifact(
+      self,
+      target_name: str,
+      artifact_name: str,
+      size: int,
+      included_modules: set[str],
+  ):
+    target_result = self.target_results.get(target_name)
+    artifact = (
+        metrics_pb2.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact()
+    )
+    artifact.name = artifact_name
+    artifact.size = size
+    for module in included_modules:
+      artifact.included_modules.add(module)
+    target_result.output_artifacts.add(artifact)
+
+  def end_reporting(self):
+    for target_result in self._target_results.values():
+      self._proto.target_result.append(target_result)
+    soong_metrics_proto = metrics_pb2.MetricsBase()
+    # Read in existing metrics that should have been written out by the soong
+    # build command so that we don't overwrite them.
+    with open(os.path.join(os.environ[self._DIST_DIR], self._SOONG_METRICS_PATH), 'rb') as f:
+      soong_metrics_proto.ParseFromString(f.read())
+    soong_metrics_proto.optimized_build_metrics.CopyFrom(self._proto)
+    logging.info(soong_metrics_proto)
+    with open(os.path.join(os.environ[self._DIST_DIR], self._SOONG_METRICS_PATH), 'wb') as f:
+      f.write(soong_metrics_proto.SerializeToString())
diff --git a/ci/test_discovery_agent.py b/ci/test_discovery_agent.py
index 4eed28d..008ee47 100644
--- a/ci/test_discovery_agent.py
+++ b/ci/test_discovery_agent.py
@@ -17,7 +17,6 @@
 import logging
 import os
 import subprocess
-import buildbot
 
 
 class TestDiscoveryAgent:
@@ -50,7 +49,7 @@
       A list of test zip regexes that TF is going to try to pull files from.
     """
     test_discovery_output_file_name = os.path.join(
-        buildbot.OutDir(), self._TRADEFED_DISCOVERY_OUTPUT_FILE_NAME
+        os.environ.get('TOP'), 'out', self._TRADEFED_DISCOVERY_OUTPUT_FILE_NAME
     )
     with open(
         test_discovery_output_file_name, mode="w+t"
diff --git a/core/Makefile b/core/Makefile
index f7a4ac0..5e0d4df 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -192,6 +192,34 @@
 unique_product_copy_files_pairs :=
 unique_product_copy_files_destinations :=
 
+
+# Returns a list of EXTRA_INSTALL_ZIPS trios whose primary file is contained within $(1)
+# The trios will contain the primary installed file : the directory to unzip the zip to : the zip
+define relevant-extra-install-zips
+$(strip $(foreach p,$(EXTRA_INSTALL_ZIPS), \
+  $(if $(filter $(call word-colon,1,$(p)),$(1)), \
+    $(p))))
+endef
+
+# Writes a text file that contains all of the files that will be inside a partition.
+# All the file paths will be relative to the partition's staging directory.
+# It will also take into account files inside zips listed in EXTRA_INSTALL_ZIPS.
+#
+# Arguments:
+#   $(1): Output file
+#   $(2): The partition's staging directory
+#   $(3): Files to include in the partition
+define write-partition-file-list
+$(1): PRIVATE_FILES := $(subst $(2)/,,$(filter $(2)/%,$(3)))
+$(1): PRIVATE_EXTRA_INSTALL_ZIPS := $(call relevant-extra-install-zips,$(filter $(2)/%,$(3)))
+$(1): $$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(foreach p,$(call relevant-extra-install-zips,$(filter $(2)/%,$(3))),$(call word-colon,3,$(p)))
+	@echo Writing $$@
+	rm -f $$@
+	echo -n > $$@
+	$$(foreach f,$$(PRIVATE_FILES),echo "$$(f)" >> $$@$$(newline))
+	$$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(2) $$(PRIVATE_EXTRA_INSTALL_ZIPS) >> $$@
+endef
+
 # -----------------------------------------------------------------
 # Returns the max allowed size for an image suitable for hash verification
 # (e.g., boot.img, recovery.img, etc).
@@ -692,7 +720,7 @@
 
 BOARD_KERNEL_MODULE_DIRS += top
 
-# Default to not generating modules.dep for kernel modules on system
+# Default to not generating modules.load for kernel modules on system
 # side. We should only load these modules if they are depended by vendor
 # side modules.
 ifeq ($(BOARD_SYSTEM_KERNEL_MODULES_LOAD),)
@@ -1267,6 +1295,10 @@
 
 endif
 
+
+ramdisk_intermediates :=$= $(call intermediates-dir-for,PACKAGING,ramdisk)
+$(eval $(call write-partition-file-list,$(ramdisk_intermediates)/file_list.txt,$(TARGET_RAMDISK_OUT),$(INTERNAL_RAMDISK_FILES)))
+
 # The value of RAMDISK_NODE_LIST is defined in system/core/rootdir/Android.bp.
 # This file contains /dev nodes description added to the generic ramdisk
 
@@ -3472,33 +3504,6 @@
 
 FULL_SYSTEMIMAGE_DEPS += $(INTERNAL_ROOT_FILES) $(INSTALLED_FILES_FILE_ROOT)
 
-# Returns a list of EXTRA_INSTALL_ZIPS trios whose primary file is contained within $(1)
-# The trios will contain the primary installed file : the directory to unzip the zip to : the zip
-define relevant-extra-install-zips
-$(strip $(foreach p,$(EXTRA_INSTALL_ZIPS), \
-  $(if $(filter $(call word-colon,1,$(p)),$(1)), \
-    $(p))))
-endef
-
-# Writes a text file that contains all of the files that will be inside a partition.
-# All the file paths will be relative to the partition's staging directory.
-# It will also take into account files inside zips listed in EXTRA_INSTALL_ZIPS.
-#
-# Arguments:
-#   $(1): Output file
-#   $(2): The partition's staging directory
-#   $(3): Files to include in the partition
-define write-partition-file-list
-$(1): PRIVATE_FILES := $(subst $(2)/,,$(filter $(2)/%,$(3)))
-$(1): PRIVATE_EXTRA_INSTALL_ZIPS := $(call relevant-extra-install-zips,$(filter $(2)/%,$(3)))
-$(1): $$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(foreach p,$(call relevant-extra-install-zips,$(filter $(2)/%,$(3))),$(call word-colon,3,$(p)))
-	@echo Writing $$@
-	rm -f $$@
-	echo -n > $$@
-	$$(foreach f,$$(PRIVATE_FILES),echo "$$(f)" >> $$@$$(newline))
-	$$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(2) $$(PRIVATE_EXTRA_INSTALL_ZIPS) >> $$@
-endef
-
 # -----------------------------------------------------------------
 ifdef BUILDING_SYSTEM_IMAGE
 
@@ -6383,6 +6388,10 @@
   endif
 endif
 
+ifdef BUILDING_VENDOR_KERNEL_BOOT_IMAGE
+  $(BUILT_TARGET_FILES_DIR): $(INTERNAL_VENDOR_KERNEL_RAMDISK_FILES)
+endif
+
 ifdef BUILDING_RECOVERY_IMAGE
   # TODO(b/30414428): Can't depend on INTERNAL_RECOVERYIMAGE_FILES alone like other
   # BUILT_TARGET_FILES_PACKAGE dependencies because currently there're cp/rsync/rm
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 26fe1da..769a6f7 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -39,6 +39,7 @@
 $(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_DRMSERVER)
 $(call add_soong_config_var,ANDROID,TARGET_ENABLE_MEDIADRM_64)
 $(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_MEDIASERVER)
+$(call add_soong_config_var,ANDROID,BOARD_GENFS_LABELS_VERSION)
 
 $(call add_soong_config_var,ANDROID,ADDITIONAL_M4DEFS,$(if $(BOARD_SEPOLICY_M4DEFS),$(addprefix -D,$(BOARD_SEPOLICY_M4DEFS))))
 
@@ -229,21 +230,6 @@
 $(call soong_config_set_bool,google_graphics,board_uses_scaler_m2m1shot,$(if $(filter true,$(BOARD_USES_SCALER_M2M1SHOT)),true,false))
 $(call soong_config_set_bool,google_graphics,board_uses_align_restriction,$(if $(filter true,$(BOARD_USES_ALIGN_RESTRICTION)),true,false))
 
-# Export video_codec variables to soong for exynos modules
-$(call soong_config_set,video_codec,target_soc_name,$(TARGET_SOC_NAME))
-$(call soong_config_set_bool,video_codec,board_use_codec2_hidl_1_2,$(if $(filter true,$(BOARD_USE_CODEC2_HIDL_1_2)),true,false))
-$(call soong_config_set_bool,video_codec,board_support_mfc_enc_bt2020,$(if $(filter true,$(BOARD_SUPPORT_MFC_ENC_BT2020)),true,false))
-$(call soong_config_set_bool,video_codec,board_support_flexible_p010,$(if $(filter true,$(BOARD_SUPPORT_FLEXIBLE_P010)),true,false))
-$(call soong_config_set_bool,video_codec,board_use_codec2_aidl,$(if $(BOARD_USE_CODEC2_AIDL),true,false))
-$(call soong_config_set,video_codec,board_gpu_type,$(BOARD_GPU_TYPE))
-$(call soong_config_set_bool,video_codec,board_use_small_secure_memory,$(if $(filter true,$(BOARD_USE_SMALL_SECURE_MEMORY)),true,false))
-ifdef BOARD_SUPPORT_MFC_VERSION
-  $(call soong_config_set,video_codec,board_support_mfc_version,$(BOARD_SUPPORT_MFC_VERSION))
-endif
-ifdef BOARD_USE_MAX_SECURE_RESOURCE
-  $(call soong_config_set,video_codec,board_use_max_secure_resource,$(BOARD_USE_MAX_SECURE_RESOURCE))
-endif
-
 # Export related variables to soong for hardware/google/graphics/common/libacryl:libacryl
 ifdef BOARD_LIBACRYL_DEFAULT_COMPOSITOR
   $(call soong_config_set,acryl,libacryl_default_compositor,$(BOARD_LIBACRYL_DEFAULT_COMPOSITOR))
diff --git a/core/config.mk b/core/config.mk
index f9ba38c..485e8cc 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -894,6 +894,11 @@
     PLATFORM_SEPOLICY_COMPAT_VERSIONS \
     PLATFORM_SEPOLICY_VERSION \
 
+BOARD_GENFS_LABELS_VERSION ?= $(BOARD_API_LEVEL)
+ifeq ($(call math_gt,$(BOARD_API_LEVEL),$(BOARD_GENFS_LABELS_VERSION)),true)
+  $(error BOARD_GENFS_LABELS_VERSION ($(BOARD_GENFS_LABELS_VERSION)) must be greater than or equal to BOARD_API_LEVEL ($(BOARD_API_LEVEL)))
+endif
+
 ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
   ifneq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true)
     $(error PRODUCT_USE_DYNAMIC_PARTITIONS must be true when PRODUCT_RETROFIT_DYNAMIC_PARTITIONS \
diff --git a/core/layoutlib_data.mk b/core/layoutlib_data.mk
index e420a00..dabcfb2 100644
--- a/core/layoutlib_data.mk
+++ b/core/layoutlib_data.mk
@@ -31,8 +31,18 @@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) cp -vf $< $@
 
-# List of all data files - font files, font configuration files, key character map files
-LAYOUTLIB_FILES := $(fonts_device) $(font_config) $(keyboards)
+HYPHEN_TEMP := $(call intermediates-dir-for,PACKAGING,hyphen,HOST,COMMON)
+
+# The hyphenation pattern files needed to support text hyphenation
+hyphen := $(filter $(TARGET_OUT)/usr/hyphen-data/%.hyb, $(INTERNAL_SYSTEMIMAGE_FILES))
+hyphen := $(addprefix $(HYPHEN_TEMP)/, $(notdir $(hyphen)))
+
+$(hyphen): $(HYPHEN_TEMP)/%: $(TARGET_OUT)/usr/hyphen-data/%
+	$(hide) mkdir -p $(dir $@)
+	$(hide) cp -vf $< $@
+
+# List of all data files - font files, font configuration files, key character map files, hyphenation pattern files
+LAYOUTLIB_FILES := $(fonts_device) $(font_config) $(keyboards) $(hyphen)
 
 .PHONY: layoutlib layoutlib-tests
 layoutlib layoutlib-tests: $(LAYOUTLIB_FILES)
@@ -40,6 +50,7 @@
 $(call dist-for-goals, layoutlib, $(foreach m,$(fonts_device), $(m):layoutlib_native/fonts/$(notdir $(m))))
 $(call dist-for-goals, layoutlib, $(foreach m,$(font_config), $(m):layoutlib_native/fonts/$(notdir $(m))))
 $(call dist-for-goals, layoutlib, $(foreach m,$(keyboards), $(m):layoutlib_native/keyboards/$(notdir $(m))))
+$(call dist-for-goals, layoutlib, $(foreach m,$(hyphen), $(m):layoutlib_native/hyphen-data/$(notdir $(m))))
 
 FONT_TEMP :=
 font_config :=
@@ -95,6 +106,7 @@
 _layoutlib_font_config_files := $(sort $(wildcard frameworks/base/data/fonts/*.xml))
 _layoutlib_fonts_files := $(filter $(TARGET_OUT)/fonts/%.ttf $(TARGET_OUT)/fonts/%.ttc $(TARGET_OUT)/fonts/%.otf, $(INTERNAL_SYSTEMIMAGE_FILES))
 _layoutlib_keyboard_files := $(sort $(wildcard frameworks/base/data/keyboards/*.kcm))
+_layoutlib_hyphen_files := $(filter $(TARGET_OUT)/usr/hyphen-data/%.hyb, $(INTERNAL_SYSTEMIMAGE_FILES))
 
 # Find out files disted with layoutlib in Soong.
 ### Filter out static libraries for Windows and files already handled in make.
@@ -124,6 +136,13 @@
 	  echo data/keyboards/$(notdir $f),frameworks/base/data/keyboards,prebuilt_etc,,,,,$f,,, >> $@; \
 	)
 
+	$(foreach f,$(_layoutlib_hyphen_files), \
+	  $(eval _module_name := $(ALL_INSTALLED_FILES.$f)) \
+	  $(eval _module_path := $(strip $(sort $(ALL_MODULES.$(_module_name).PATH)))) \
+	  $(eval _soong_module_type := $(strip $(sort $(ALL_MODULES.$(_module_name).SOONG_MODULE_TYPE)))) \
+	  echo data/hyphen-data/$(notdir $f),$(_module_path),$(_soong_module_type),,,,,$f,,, >> $@; \
+	)
+
 	$(foreach f,$(_layoutlib_files_disted_by_soong), \
 	  $(eval _prebuilt_module_file := $(call word-colon,1,$f)) \
 	  $(eval _dist_file := $(call word-colon,2,$f)) \
@@ -152,7 +171,7 @@
 
 .PHONY: layoutlib-sbom
 layoutlib-sbom: $(LAYOUTLIB_SBOM)/layoutlib.spdx.json
-$(LAYOUTLIB_SBOM)/layoutlib.spdx.json: $(PRODUCT_OUT)/always_dirty_file.txt $(GEN_SBOM) $(LAYOUTLIB_SBOM)/sbom-metadata.csv $(_layoutlib_font_config_files) $(_layoutlib_fonts_files) $(LAYOUTLIB_BUILD_PROP)/layoutlib-build.prop $(_layoutlib_keyboard_files) $(LAYOUTLIB_RES_FILES) $(EMULATED_OVERLAYS_FILES) $(DEVICE_OVERLAYS_FILES)
+$(LAYOUTLIB_SBOM)/layoutlib.spdx.json: $(PRODUCT_OUT)/always_dirty_file.txt $(GEN_SBOM) $(LAYOUTLIB_SBOM)/sbom-metadata.csv $(_layoutlib_font_config_files) $(_layoutlib_fonts_files) $(LAYOUTLIB_BUILD_PROP)/layoutlib-build.prop $(_layoutlib_keyboard_files) $(_layoutlib_hyphen_files) $(LAYOUTLIB_RES_FILES) $(EMULATED_OVERLAYS_FILES) $(DEVICE_OVERLAYS_FILES)
 	rm -rf $@
 	$(GEN_SBOM) --output_file $@ --metadata $(LAYOUTLIB_SBOM)/sbom-metadata.csv --build_version $(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --module_name "layoutlib" --json
 
diff --git a/core/main.mk b/core/main.mk
index 5142adc..624df49 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -277,11 +277,24 @@
 # 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)
-  subdir_makefiles += $(file <$(OUT_DIR)/.module_paths/Android.mk.list)
+  ifeq ($(PRODUCT_IGNORE_ALL_ANDROIDMK),true)
+    allowed_androidmk_files :=
+    ifdef PRODUCT_ANDROIDMK_ALLOWLIST_FILE
+      -include $(PRODUCT_ANDROIDMK_ALLOWLIST_FILE)
+    endif
+    allowed_androidmk_files += $(PRODUCT_ALLOWED_ANDROIDMK_FILES)
+    subdir_makefiles += $(filter $(allowed_androidmk_files),$(file <$(OUT_DIR)/.module_paths/Android.mk.list))
+    allowed_androidmk_files :=
+  else
+    subdir_makefiles += $(file <$(OUT_DIR)/.module_paths/Android.mk.list)
+  endif
 endif
 
 subdir_makefiles += $(SOONG_OUT_DIR)/late-$(TARGET_PRODUCT)$(COVERAGE_SUFFIX).mk
@@ -1386,6 +1399,7 @@
     $(INSTALLED_RAMDISK_TARGET) \
     $(INSTALLED_BOOTIMAGE_TARGET) \
     $(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
+    $(INSTALLED_DTBOIMAGE_TARGET) \
     $(INSTALLED_RADIOIMAGE_TARGET) \
     $(INSTALLED_DEBUG_RAMDISK_TARGET) \
     $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) \
diff --git a/core/product.mk b/core/product.mk
index 7cf4ec2..9c567c3 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -492,6 +492,13 @@
 # should be included in the system_linker_config.
 _product_list_vars += PRODUCT_EXTRA_STUB_LIBRARIES
 
+# If set to true, all Android.mk files will be ignored.
+_product_single_value_vars += PRODUCT_IGNORE_ALL_ANDROIDMK
+# When PRODUCT_IGNORE_ALL_ANDROIDMK is set to true, this variable will be used to allow some Android.mk files.
+_product_list_vars += PRODUCT_ALLOWED_ANDROIDMK_FILES
+# When PRODUCT_IGNORE_ALL_ANDROIDMK is set to true, path of file that contains a list of allowed Android.mk files
+_product_single_value_vars += PRODUCT_ANDROIDMK_ALLOWLIST_FILE
+
 .KATI_READONLY := _product_single_value_vars _product_list_vars
 _product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
 
diff --git a/core/robolectric_test_config_template.xml b/core/robolectric_test_config_template.xml
index 257c820..1956b6e 100644
--- a/core/robolectric_test_config_template.xml
+++ b/core/robolectric_test_config_template.xml
@@ -22,6 +22,13 @@
     <option name="exclude-paths" value="java" />
     <option name="use-robolectric-resources" value="true" />
 
+    <!-- attempt to always show Tradefed errors -->
+    <option name="do-not-swallow-runner-errors" value="true" />
+
+    <!-- prevent Tradefed from hanging indefinitely in CI -->
+    <option name="socket-timeout" value="600000" />
+    <option name="test-case-timeout" value="2m" />
+
     {EXTRA_CONFIGS}
 
     <test class="com.android.tradefed.testtype.IsolatedHostTest" >
diff --git a/core/soong_config.mk b/core/soong_config.mk
index c0641de..0f82b68 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -275,10 +275,6 @@
 
 $(call add_json_bool, CompressedApex, $(filter true,$(PRODUCT_COMPRESSED_APEX)))
 
-ifndef APEX_BUILD_FOR_PRE_S_DEVICES
-$(call add_json_bool, TrimmedApex, $(filter true,$(PRODUCT_TRIMMED_APEX)))
-endif
-
 $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
 
 $(call add_json_list, BoardKernelBinaries, $(BOARD_KERNEL_BINARIES))
@@ -401,6 +397,10 @@
     $(call add_json_str, BoardSquashfsCompressor, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR)) \
     $(call add_json_str, BoardSquashfsCompressorOpt, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR_OPT)) \
     $(call add_json_str, BoardSquashfsDisable4kAlign, $(BOARD_$(image_type)IMAGE_SQUASHFS_DISABLE_4K_ALIGN)) \
+    $(call add_json_str, BoardAvbKeyPath, $(BOARD_AVB_$(image_type)_KEY_PATH)) \
+    $(call add_json_str, BoardAvbAlgorithm, $(BOARD_AVB_$(image_type)_ALGORITHM)) \
+    $(call add_json_str, BoardAvbRollbackIndex, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX)) \
+    $(call add_json_str, BoardAvbRollbackIndexLocation, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX_LOCATION)) \
     $(call add_json_str, ProductBaseFsPath, $(PRODUCT_$(image_type)_BASE_FS_PATH)) \
     $(call add_json_str, ProductHeadroom, $(PRODUCT_$(image_type)_HEADROOM)) \
     $(call add_json_str, ProductVerityPartition, $(PRODUCT_$(image_type)_VERITY_PARTITION)) \
@@ -425,6 +425,21 @@
   $(call add_json_str, BoardExt4ShareDupBlocks, $(BOARD_EXT4_SHARE_DUP_BLOCKS))
   $(call add_json_str, BoardFlashLogicalBlockSize, $(BOARD_FLASH_LOGICAL_BLOCK_SIZE))
   $(call add_json_str, BoardFlashEraseBlockSize, $(BOARD_FLASH_ERASE_BLOCK_SIZE))
+  $(call add_json_bool, BuildingVbmetaImage, $(BUILDING_VBMETA_IMAGE))
+  $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
+  $(call add_json_str, BoardAvbAlgorithm, $(BOARD_AVB_ALGORITHM))
+  $(call add_json_str, BoardAvbKeyPath, $(BOARD_AVB_KEY_PATH))
+  $(call add_json_str, BoardAvbRollbackIndex, $(BOARD_AVB_ROLLBACK_INDEX))
+  $(call add_json_map, ChainedVbmetaPartitions)
+  $(foreach partition,system vendor $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),\
+    $(call add_json_map, $(partition)) \
+      $(call add_json_list,Partitions,$(BOARD_AVB_VBMETA_$(call to-upper,$(partition)))) \
+      $(call add_json_str,Key,$(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_KEY_PATH)) \
+      $(call add_json_str,Algorithm,$(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_ALGORITHM)) \
+      $(call add_json_str,RollbackIndex,$(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_ROLLBACK_INDEX)) \
+      $(call add_json_str,RollbackIndexLocation,$(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_ROLLBACK_INDEX_LOCATION)) \
+    $(call end_json_map))
+  $(call end_json_map)
 
   $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
   $(call add_json_bool, ProductUseDynamicPartitionSize, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)))
@@ -440,15 +455,20 @@
   # Used to generate _dlkm partitions
   $(call add_json_bool, BuildingSystemDlkmImage,               $(BUILDING_SYSTEM_DLKM_IMAGE))
   $(call add_json_list, SystemKernelModules, $(BOARD_SYSTEM_KERNEL_MODULES))
+  $(call add_json_str, SystemKernelBlocklistFile, $(BOARD_SYSTEM_KERNEL_MODULES_BLOCKLIST_FILE))
+  $(call add_json_list, SystemKernelLoadModules, $(BOARD_SYSTEM_KERNEL_MODULES_LOAD))
+  $(call add_json_bool, BuildingVendorDlkmImage,               $(BUILDING_VENDOR_DLKM_IMAGE))
+  $(call add_json_list, VendorKernelModules, $(BOARD_VENDOR_KERNEL_MODULES))
+  $(call add_json_str, VendorKernelBlocklistFile, $(BOARD_VENDOR_KERNEL_MODULES_BLOCKLIST_FILE))
+  $(call add_json_bool, BuildingOdmDlkmImage,               $(BUILDING_ODM_DLKM_IMAGE))
+  $(call add_json_list, OdmKernelModules, $(BOARD_ODM_KERNEL_MODULES))
+  $(call add_json_str, OdmKernelBlocklistFile, $(BOARD_ODM_KERNEL_MODULES_BLOCKLIST_FILE))
 
   # Used to generate /vendor/build.prop
   $(call add_json_list, BoardInfoFiles, $(if $(TARGET_BOARD_INFO_FILES),$(TARGET_BOARD_INFO_FILES),$(firstword $(TARGET_BOARD_INFO_FILE) $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt))))
   $(call add_json_str, BootLoaderBoardName, $(TARGET_BOOTLOADER_BOARD_NAME))
 
-  $(call add_json_map, ProductCopyFiles)
-  $(foreach pair,$(PRODUCT_COPY_FILES),\
-    $(call add_json_str,$(word 1,$(subst :, ,$(pair))),$(word 2,$(subst :, ,$(pair)))))
-  $(call end_json_map)
+  $(call add_json_list, ProductCopyFiles, $(PRODUCT_COPY_FILES))
 
 $(call end_json_map)
 
diff --git a/core/sysprop.mk b/core/sysprop.mk
index 9b70d1c..255b699 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -301,22 +301,12 @@
 
 INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/etc/build.prop
 
-# ----------------------------------------------------------------
-# ramdisk/boot/etc/build.prop
-#
-
 RAMDISK_BUILD_PROP_REL_PATH := system/etc/ramdisk/build.prop
+ifeq (true,$(BOARD_USES_RECOVERY_AS_BOOT))
+INSTALLED_RAMDISK_BUILD_PROP_TARGET := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/$(RAMDISK_BUILD_PROP_REL_PATH)
+else
 INSTALLED_RAMDISK_BUILD_PROP_TARGET := $(TARGET_RAMDISK_OUT)/$(RAMDISK_BUILD_PROP_REL_PATH)
-$(eval $(call build-properties,\
-    bootimage,\
-    $(INSTALLED_RAMDISK_BUILD_PROP_TARGET),\
-    $(empty),\
-    $(empty),\
-    $(empty),\
-    $(empty),\
-    $(empty)))
-
-$(eval $(call declare-1p-target,$(INSTALLED_RAMDISK_BUILD_PROP_TARGET)))
+endif
 
 ALL_INSTALLED_BUILD_PROP_FILES := \
   $(INSTALLED_BUILD_PROP_TARGET) \
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/product/base_system.mk b/target/product/base_system.mk
index 9d6402e..3a7256e 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -18,6 +18,7 @@
 PRODUCT_PACKAGES += \
     abx \
     aconfigd \
+    aconfigd-system \
     adbd_system_api \
     aflags \
     am \
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index c81e66c..ea49af4 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -1,4 +1,4 @@
-android_rootdirs = [
+generic_rootdirs = [
     "acct",
     "apex",
     "bootstrap-apex",
@@ -15,19 +15,22 @@
     "oem",
     "postinstall",
     "proc",
-    "product",
     "second_stage_resources",
     "storage",
     "sys",
     "system",
     "system_dlkm",
-    "system_ext",
     "tmp",
     "vendor",
     "vendor_dlkm",
 ]
 
-android_symlinks = [
+android_rootdirs = [
+    "system_ext",
+    "product",
+]
+
+generic_symlinks = [
     {
         target: "/system/bin/init",
         name: "init",
@@ -41,18 +44,10 @@
         name: "bin",
     },
     {
-        target: "/product",
-        name: "system/product",
-    },
-    {
         target: "/vendor",
         name: "system/vendor",
     },
     {
-        target: "/system_ext",
-        name: "system/system_ext",
-    },
-    {
         target: "/system_dlkm/lib/modules",
         name: "system/lib/modules",
     },
@@ -121,6 +116,17 @@
     },
 ]
 
+android_symlinks = [
+    {
+        target: "/product",
+        name: "system/product",
+    },
+    {
+        target: "/system_ext",
+        name: "system/system_ext",
+    },
+]
+
 filegroup {
     name: "generic_system_sign_key",
     srcs: [":avb_testkey_rsa4096"],
@@ -340,15 +346,22 @@
     ],
 }
 
-android_system_image {
-    name: "generic_system_image",
+filegroup {
+    name: "system_image_erofs_compress_hints.txt",
+    srcs: ["erofs_compress_hints.txt"],
+}
 
+android_filesystem_defaults {
+    name: "system_image_defaults",
     partition_name: "system",
     base_dir: "system",
-    dirs: android_rootdirs,
-    symlinks: android_symlinks,
+    dirs: generic_rootdirs,
+    symlinks: generic_symlinks,
     file_contexts: ":plat_file_contexts",
-    linker_config_src: ":system_linker_config_json_file",
+    linker_config: {
+        gen_linker_config: true,
+        linker_config_srcs: [":system_linker_config_json_file"],
+    },
     fsverity: {
         inputs: [
             "etc/boot-image.prof",
@@ -364,7 +377,7 @@
     type: "erofs",
     erofs: {
         compressor: "lz4hc,9",
-        compress_hints: "erofs_compress_hints.txt",
+        compress_hints: ":system_image_erofs_compress_hints.txt",
     },
     build_logtags: true,
     gen_aconfig_flags_pb: true,
@@ -379,6 +392,7 @@
     deps: [
         "abx",
         "aconfigd",
+        "aconfigd-system",
         "aflags",
         "am",
         "android.software.credentials.prebuilt.xml", // generic_system
@@ -869,3 +883,10 @@
         },
     },
 }
+
+android_system_image {
+    name: "generic_system_image",
+    defaults: ["system_image_defaults"],
+    dirs: android_rootdirs,
+    symlinks: android_symlinks,
+}
diff --git a/target/product/generic_ramdisk.mk b/target/product/generic_ramdisk.mk
index 388b180..5ecb55f 100644
--- a/target/product/generic_ramdisk.mk
+++ b/target/product/generic_ramdisk.mk
@@ -23,6 +23,7 @@
 PRODUCT_PACKAGES += \
     init_first_stage \
     snapuserd_ramdisk \
+    ramdisk-build.prop \
 
 # Debug ramdisk
 PRODUCT_PACKAGES += \
diff --git a/target/product/gsi/Android.bp b/target/product/gsi/Android.bp
index f18f35a..1b8f2d7 100644
--- a/target/product/gsi/Android.bp
+++ b/target/product/gsi/Android.bp
@@ -61,3 +61,139 @@
     system_ext_specific: true,
     relative_install_path: "gsi",
 }
+
+gsi_symlinks = [
+    {
+        target: "/system/system_ext",
+        name: "system_ext",
+    },
+    {
+        target: "/system/product",
+        name: "product",
+    },
+]
+
+android_system_image {
+    name: "android_gsi",
+    defaults: ["system_image_defaults"],
+    symlinks: gsi_symlinks,
+    deps: [
+        ///////////////////////////////////////////
+        // gsi_system_ext
+        ///////////////////////////////////////////
+
+        // handheld packages
+        "Launcher3QuickStep",
+        "Provision",
+        "Settings",
+        "StorageManager",
+        "SystemUI",
+
+        // telephony packages
+        "CarrierConfig",
+
+        // Install a copy of the debug policy to the system_ext partition, and allow
+        // init-second-stage to load debug policy from system_ext.
+        // This option is only meant to be set by compliance GSI targets.
+        "system_ext_userdebug_plat_sepolicy.cil",
+
+        ///////////////////////////////////////////
+        // base_system_ext
+        ///////////////////////////////////////////
+        "build_flag_system_ext",
+        "fs_config_dirs_system_ext",
+        "fs_config_files_system_ext",
+        "group_system_ext",
+        "passwd_system_ext",
+        "SatelliteClient",
+        "selinux_policy_system_ext",
+        "system_ext_manifest.xml",
+        "system_ext-build.prop",
+        // Base modules when shipping api level is less than or equal to 34
+        "hwservicemanager",
+        "android.hidl.allocator@1.0-service",
+
+        ///////////////////////////////////////////
+        // window_extensions_base
+        ///////////////////////////////////////////
+        "androidx.window.extensions",
+        "androidx.window.sidecar",
+
+        ///////////////////////////////////////////
+        // gsi_release
+        ///////////////////////////////////////////
+        "gsi_skip_mount.cfg",
+        "init.gsi.rc",
+        "init.vndk-nodef.rc",
+        // Overlay the GSI specific setting for framework and SystemUI
+        "gsi_overlay_framework",
+        "gsi_overlay_systemui",
+
+        ///////////////////////////////////////////
+        // VNDK
+        ///////////////////////////////////////////
+        "com.android.vndk.v30",
+        "com.android.vndk.v31",
+        "com.android.vndk.v32",
+        "com.android.vndk.v33",
+        "com.android.vndk.v34",
+
+        ///////////////////////////////////////////
+        // AVF
+        ///////////////////////////////////////////
+        "com.android.compos",
+        "features_com.android.virt.xml",
+
+        ///////////////////////////////////////////
+        // gsi_product
+        ///////////////////////////////////////////
+        "Browser2",
+        "Camera2",
+        "Dialer",
+        "LatinIME",
+        "apns-full-conf.xml",
+
+        ///////////////////////////////////////////
+        // media_product
+        ///////////////////////////////////////////
+        "webview",
+
+        ///////////////////////////////////////////
+        // base_product
+        ///////////////////////////////////////////
+
+        // Base modules and settings for the product partition.
+        "build_flag_product",
+        "fs_config_dirs_product",
+        "fs_config_files_product",
+        "group_product",
+        "ModuleMetadata",
+        "passwd_product",
+        "product_compatibility_matrix.xml",
+        "product_manifest.xml",
+        "selinux_policy_product",
+        "product-build.prop",
+
+        // AUDIO
+        "frameworks_sounds",
+
+        ///////////////////////////////////////////
+        // base_system
+        ///////////////////////////////////////////
+        "charger",
+    ] + select(product_variable("debuggable"), {
+        // Packages included only for eng or userdebug builds, previously debug tagged
+        true: ["adb_keys"],
+        default: [],
+    }),
+    multilib: {
+        both: {
+            // PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34
+            deps: ["android.hidl.memory@1.0-impl"],
+        },
+    },
+    enabled: select(soong_config_variable("ANDROID", "PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT"), {
+        "true": true,
+        default: false,
+    }),
+}
diff --git a/teams/Android.bp b/teams/Android.bp
index 21f5222..6307f5c 100644
--- a/teams/Android.bp
+++ b/teams/Android.bp
@@ -70,13 +70,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wear_cloud_platform",
-
-    // go/trendy/manage/engineers/5917762526281728
-    trendy_team_id: "5917762526281728",
-}
-
-team {
     name: "trendy_team_pixel_system_software",
 
     // go/trendy/manage/engineers/4856005120622592
@@ -518,13 +511,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wear_notifications_alerts_attention_management",
-
-    // go/trendy/manage/engineers/6267643681996800
-    trendy_team_id: "6267643681996800",
-}
-
-team {
     name: "trendy_team_fwk_nfc",
 
     // go/trendy/manage/engineers/5962312512864256
@@ -532,13 +518,6 @@
 }
 
 team {
-    name: "trendy_team_wear_personalization_developer_surfaces",
-
-    // go/trendy/manage/engineers/4819890988810240
-    trendy_team_id: "4819890988810240",
-}
-
-team {
     name: "trendy_team_srajkumar_team",
 
     // go/trendy/manage/engineers/5170053894012928
@@ -693,13 +672,6 @@
 }
 
 team {
-    name: "trendy_team_test_eng_android_wear",
-
-    // go/trendy/manage/engineers/4979150422933504
-    trendy_team_id: "4979150422933504",
-}
-
-team {
     name: "trendy_team_mesch_team",
 
     // go/trendy/manage/engineers/5205465899368448
@@ -721,13 +693,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wear_developer_devx",
-
-    // go/trendy/manage/engineers/4894890764697600
-    trendy_team_id: "4894890764697600",
-}
-
-team {
     name: "trendy_team_android_rust",
 
     // go/trendy/manage/engineers/4844600586305536
@@ -931,13 +896,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wallet_on_wear",
-
-    // go/trendy/manage/engineers/5724960437731328
-    trendy_team_id: "5724960437731328",
-}
-
-team {
     name: "trendy_team_glanceables",
 
     // go/trendy/manage/engineers/4658222004600832
@@ -1071,13 +1029,6 @@
 }
 
 team {
-    name: "trendy_team_wear_3xp",
-
-    // go/trendy/manage/engineers/5692317612539904
-    trendy_team_id: "5692317612539904",
-}
-
-team {
     name: "trendy_team_clockwork",
 
     // go/trendy/manage/engineers/4908781678755840
@@ -1211,13 +1162,6 @@
 }
 
 team {
-    name: "trendy_team_wear_software_nti",
-
-    // go/trendy/manage/engineers/5164973558759424
-    trendy_team_id: "5164973558759424",
-}
-
-team {
     name: "trendy_team_machine_learning",
 
     // go/trendy/manage/engineers/5276568318246912
@@ -1309,13 +1253,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wear_power_emulator",
-
-    // go/trendy/manage/engineers/5160338936725504
-    trendy_team_id: "5160338936725504",
-}
-
-team {
     name: "trendy_team_deprecated_framework_svetoslavganov",
 
     // go/trendy/manage/engineers/6404117492531200
@@ -1330,13 +1267,6 @@
 }
 
 team {
-    name: "trendy_team_wear_opus",
-
-    // go/trendy/manage/engineers/5098351636676608
-    trendy_team_id: "5098351636676608",
-}
-
-team {
     name: "trendy_team_text_to_speech",
 
     // go/trendy/manage/engineers/6368933120442368
@@ -1442,13 +1372,6 @@
 }
 
 team {
-    name: "trendy_team_wear_developer_foundation",
-
-    // go/trendy/manage/engineers/5239127108648960
-    trendy_team_id: "5239127108648960",
-}
-
-team {
     name: "trendy_team_tpm_tvc",
 
     // go/trendy/manage/engineers/5390683333230592
@@ -1456,13 +1379,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wear_ux",
-
-    // go/trendy/manage/engineers/5782097411080192
-    trendy_team_id: "5782097411080192",
-}
-
-team {
     name: "trendy_team_lse_desktop_os_experience",
 
     // go/trendy/manage/engineers/5125234900434944
@@ -1673,13 +1589,6 @@
 }
 
 team {
-    name: "trendy_team_wear_wear_assistant",
-
-    // go/trendy/manage/engineers/5848075306172416
-    trendy_team_id: "5848075306172416",
-}
-
-team {
     name: "trendy_team_android_power_and_comms_infra",
 
     // go/trendy/manage/engineers/5325547653332992
diff --git a/tools/aconfig/aconfig/src/storage/flag_info.rs b/tools/aconfig/aconfig/src/storage/flag_info.rs
index 2532609..5d565e8 100644
--- a/tools/aconfig/aconfig/src/storage/flag_info.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_info.rs
@@ -83,7 +83,7 @@
         let flag_info_list = create_test_flag_info_list_from_source();
         assert!(flag_info_list.is_ok());
         let expected_flag_info_list =
-            aconfig_storage_file::test_utils::create_test_flag_info_list();
+            aconfig_storage_file::test_utils::create_test_flag_info_list(DEFAULT_FILE_VERSION);
         assert_eq!(flag_info_list.unwrap(), expected_flag_info_list);
     }
 }
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index 6046d7e..8856eb6 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -157,7 +157,8 @@
     fn test_table_contents() {
         let flag_table = create_test_flag_table_from_source();
         assert!(flag_table.is_ok());
-        let expected_flag_table = aconfig_storage_file::test_utils::create_test_flag_table();
+        let expected_flag_table =
+            aconfig_storage_file::test_utils::create_test_flag_table(DEFAULT_FILE_VERSION);
         assert_eq!(flag_table.unwrap(), expected_flag_table);
     }
 }
diff --git a/tools/aconfig/aconfig/src/storage/flag_value.rs b/tools/aconfig/aconfig/src/storage/flag_value.rs
index 6a655b9..0dd5a9d 100644
--- a/tools/aconfig/aconfig/src/storage/flag_value.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_value.rs
@@ -82,7 +82,7 @@
         let flag_value_list = create_test_flag_value_list_from_source();
         assert!(flag_value_list.is_ok());
         let expected_flag_value_list =
-            aconfig_storage_file::test_utils::create_test_flag_value_list();
+            aconfig_storage_file::test_utils::create_test_flag_value_list(DEFAULT_FILE_VERSION);
         assert_eq!(flag_value_list.unwrap(), expected_flag_value_list);
     }
 }
diff --git a/tools/aconfig/aconfig/src/storage/mod.rs b/tools/aconfig/aconfig/src/storage/mod.rs
index 9e5dad5..c7fd55a 100644
--- a/tools/aconfig/aconfig/src/storage/mod.rs
+++ b/tools/aconfig/aconfig/src/storage/mod.rs
@@ -32,6 +32,7 @@
 pub struct FlagPackage<'a> {
     pub package_name: &'a str,
     pub package_id: u32,
+    pub fingerprint: u64,
     pub flag_names: HashSet<&'a str>,
     pub boolean_flags: Vec<&'a ProtoParsedFlag>,
     // The index of the first boolean flag in this aconfig package among all boolean
@@ -44,6 +45,7 @@
         FlagPackage {
             package_name,
             package_id,
+            fingerprint: 0,
             flag_names: HashSet::new(),
             boolean_flags: vec![],
             boolean_start_index: 0,
@@ -79,6 +81,8 @@
     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.
     }
 
     packages
diff --git a/tools/aconfig/aconfig/src/storage/package_table.rs b/tools/aconfig/aconfig/src/storage/package_table.rs
index 56559f8..e46607b 100644
--- a/tools/aconfig/aconfig/src/storage/package_table.rs
+++ b/tools/aconfig/aconfig/src/storage/package_table.rs
@@ -47,6 +47,7 @@
         let node = PackageTableNode {
             package_name: String::from(package.package_name),
             package_id: package.package_id,
+            fingerprint: package.fingerprint,
             boolean_start_index: package.boolean_start_index,
             next_offset: None,
         };
@@ -127,7 +128,8 @@
     fn test_table_contents() {
         let package_table = create_test_package_table_from_source();
         assert!(package_table.is_ok());
-        let expected_package_table = aconfig_storage_file::test_utils::create_test_package_table();
+        let expected_package_table =
+            aconfig_storage_file::test_utils::create_test_package_table(DEFAULT_FILE_VERSION);
         assert_eq!(package_table.unwrap(), expected_package_table);
     }
 }
diff --git a/tools/aconfig/aconfig_flags/flags.aconfig b/tools/aconfig/aconfig_flags/flags.aconfig
index 0a004ca..b66d282 100644
--- a/tools/aconfig/aconfig_flags/flags.aconfig
+++ b/tools/aconfig/aconfig_flags/flags.aconfig
@@ -14,3 +14,11 @@
   bug: "369808805"
   description: "When enabled, launch aconfigd from config infra module."
 }
+
+flag {
+  name: "enable_system_aconfigd_rust"
+  namespace: "core_experiments_team_internal"
+  bug: "378079539"
+  description: "When enabled, the aconfigd cc_binary target becomes a no-op, and the rust_binary aconfigd-system target starts up."
+  is_fixed_read_only: true
+}
diff --git a/tools/aconfig/aconfig_flags/src/lib.rs b/tools/aconfig/aconfig_flags/src/lib.rs
index 2e89127..b413c62 100644
--- a/tools/aconfig/aconfig_flags/src/lib.rs
+++ b/tools/aconfig/aconfig_flags/src/lib.rs
@@ -39,6 +39,11 @@
     pub fn enable_aconfigd_from_mainline() -> bool {
         aconfig_flags_rust::enable_only_new_storage()
     }
+
+    /// Returns the value for the enable_system_aconfigd_rust flag.
+    pub fn enable_system_aconfigd_rust() -> bool {
+        aconfig_flags_rust::enable_system_aconfigd_rust()
+    }
 }
 
 /// Module used when building with cargo
@@ -55,4 +60,10 @@
         // Used only to enable typechecking and testing with cargo
         true
     }
+
+    /// Returns a placeholder value for the enable_system_aconfigd_rust flag.
+    pub fn enable_system_aconfigd_rust() -> bool {
+        // Used only to enable typechecking and testing with cargo
+        true
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_info.rs b/tools/aconfig/aconfig_storage_file/src/flag_info.rs
index f090396..cf16834 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_info.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_info.rs
@@ -194,12 +194,15 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::create_test_flag_info_list;
+    use crate::{
+        test_utils::create_test_flag_info_list, DEFAULT_FILE_VERSION, MAX_SUPPORTED_FILE_VERSION,
+    };
 
-    #[test]
     // this test point locks down the value list serialization
-    fn test_serialization() {
-        let flag_info_list = create_test_flag_info_list();
+    // TODO: b/376108268 - Use parameterized tests.
+    #[test]
+    fn test_serialization_default() {
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
 
         let header: &FlagInfoHeader = &flag_info_list.header;
         let reinterpreted_header = FlagInfoHeader::from_bytes(&header.into_bytes());
@@ -220,20 +223,42 @@
     }
 
     #[test]
-    // this test point locks down that version number should be at the top of serialized
-    // bytes
-    fn test_version_number() {
-        let flag_info_list = create_test_flag_info_list();
-        let bytes = &flag_info_list.into_bytes();
-        let mut head = 0;
-        let version = read_u32_from_bytes(bytes, &mut head).unwrap();
-        assert_eq!(version, 1);
+    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
+    // bytes
     #[test]
+    fn test_version_number() {
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
+        let bytes = &flag_info_list.into_bytes();
+        let mut head = 0;
+        let version_from_file = read_u32_from_bytes(bytes, &mut head).unwrap();
+        assert_eq!(version_from_file, DEFAULT_FILE_VERSION);
+    }
+
     // this test point locks down file type check
+    #[test]
     fn test_file_type_check() {
-        let mut flag_info_list = create_test_flag_info_list();
+        let mut flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
         flag_info_list.header.file_type = 123u8;
         let error = FlagInfoList::from_bytes(&flag_info_list.into_bytes()).unwrap_err();
         assert_eq!(
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_table.rs b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
index 0588fe5..6fbee02 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
@@ -220,12 +220,15 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::create_test_flag_table;
+    use crate::{
+        test_utils::create_test_flag_table, DEFAULT_FILE_VERSION, MAX_SUPPORTED_FILE_VERSION,
+    };
 
-    #[test]
     // this test point locks down the table serialization
-    fn test_serialization() {
-        let flag_table = create_test_flag_table();
+    // TODO: b/376108268 - Use parameterized tests.
+    #[test]
+    fn test_serialization_default() {
+        let flag_table = create_test_flag_table(DEFAULT_FILE_VERSION);
 
         let header: &FlagTableHeader = &flag_table.header;
         let reinterpreted_header = FlagTableHeader::from_bytes(&header.into_bytes());
@@ -246,20 +249,42 @@
     }
 
     #[test]
-    // this test point locks down that version number should be at the top of serialized
-    // bytes
-    fn test_version_number() {
-        let flag_table = create_test_flag_table();
-        let bytes = &flag_table.into_bytes();
-        let mut head = 0;
-        let version = read_u32_from_bytes(bytes, &mut head).unwrap();
-        assert_eq!(version, 1);
+    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
+    // bytes
     #[test]
+    fn test_version_number() {
+        let flag_table = create_test_flag_table(DEFAULT_FILE_VERSION);
+        let bytes = &flag_table.into_bytes();
+        let mut head = 0;
+        let version_from_file = read_u32_from_bytes(bytes, &mut head).unwrap();
+        assert_eq!(version_from_file, DEFAULT_FILE_VERSION);
+    }
+
     // this test point locks down file type check
+    #[test]
     fn test_file_type_check() {
-        let mut flag_table = create_test_flag_table();
+        let mut flag_table = create_test_flag_table(DEFAULT_FILE_VERSION);
         flag_table.header.file_type = 123u8;
         let error = FlagTable::from_bytes(&flag_table.into_bytes()).unwrap_err();
         assert_eq!(
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_value.rs b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
index b64c10e..9a14bec 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_value.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
@@ -132,12 +132,32 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::test_utils::create_test_flag_value_list;
+    use crate::{
+        test_utils::create_test_flag_value_list, DEFAULT_FILE_VERSION, MAX_SUPPORTED_FILE_VERSION,
+    };
 
     #[test]
     // this test point locks down the value list serialization
-    fn test_serialization() {
-        let flag_value_list = create_test_flag_value_list();
+    // TODO: b/376108268 - Use parameterized tests.
+    fn test_serialization_default() {
+        let flag_value_list = create_test_flag_value_list(DEFAULT_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);
+    }
+
+    #[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());
@@ -155,17 +175,17 @@
     // this test point locks down that version number should be at the top of serialized
     // bytes
     fn test_version_number() {
-        let flag_value_list = create_test_flag_value_list();
+        let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
         let bytes = &flag_value_list.into_bytes();
         let mut head = 0;
-        let version = read_u32_from_bytes(bytes, &mut head).unwrap();
-        assert_eq!(version, 1);
+        let version_from_file = read_u32_from_bytes(bytes, &mut head).unwrap();
+        assert_eq!(version_from_file, DEFAULT_FILE_VERSION);
     }
 
     #[test]
     // this test point locks down file type check
     fn test_file_type_check() {
-        let mut flag_value_list = create_test_flag_value_list();
+        let mut flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
         flag_value_list.header.file_type = 123u8;
         let error = FlagValueList::from_bytes(&flag_value_list.into_bytes()).unwrap_err();
         assert_eq!(
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 5dc5ef7..e991320 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -228,14 +228,10 @@
 
 /// Read and parse bytes as u8
 pub fn read_u8_from_bytes(buf: &[u8], head: &mut usize) -> Result<u8, AconfigStorageError> {
-    let val = u8::from_le_bytes(
-        buf.get(*head..*head + 1)
-            .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
-                "fail to parse u8 from bytes: access out of bounds"
-            )))?
-            .try_into()
-            .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse u8 from bytes: {}", errmsg)))?,
-    );
+    let val =
+        u8::from_le_bytes(buf[*head..*head + 1].try_into().map_err(|errmsg| {
+            BytesParseFail(anyhow!("fail to parse u8 from bytes: {}", errmsg))
+        })?);
     *head += 1;
     Ok(val)
 }
@@ -245,16 +241,10 @@
     buf: &[u8],
     head: &mut usize,
 ) -> Result<u16, AconfigStorageError> {
-    let val = u16::from_le_bytes(
-        buf.get(*head..*head + 2)
-            .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
-                "fail to parse u16 from bytes: access out of bounds"
-            )))?
-            .try_into()
-            .map_err(|errmsg| {
-                BytesParseFail(anyhow!("fail to parse u16 from bytes: {}", errmsg))
-            })?,
-    );
+    let val =
+        u16::from_le_bytes(buf[*head..*head + 2].try_into().map_err(|errmsg| {
+            BytesParseFail(anyhow!("fail to parse u16 from bytes: {}", errmsg))
+        })?);
     *head += 2;
     Ok(val)
 }
@@ -266,32 +256,20 @@
 
 /// Read and parse bytes as u32
 pub fn read_u32_from_bytes(buf: &[u8], head: &mut usize) -> Result<u32, AconfigStorageError> {
-    let val = u32::from_le_bytes(
-        buf.get(*head..*head + 4)
-            .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
-                "fail to parse u32 from bytes: access out of bounds"
-            )))?
-            .try_into()
-            .map_err(|errmsg| {
-                BytesParseFail(anyhow!("fail to parse u32 from bytes: {}", errmsg))
-            })?,
-    );
+    let val =
+        u32::from_le_bytes(buf[*head..*head + 4].try_into().map_err(|errmsg| {
+            BytesParseFail(anyhow!("fail to parse u32 from bytes: {}", errmsg))
+        })?);
     *head += 4;
     Ok(val)
 }
 
 // Read and parse bytes as u64
 pub fn read_u64_from_bytes(buf: &[u8], head: &mut usize) -> Result<u64, AconfigStorageError> {
-    let val = u64::from_le_bytes(
-        buf.get(*head..*head + 8)
-            .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
-                "fail to parse u64 from bytes: access out of bounds"
-            )))?
-            .try_into()
-            .map_err(|errmsg| {
-                BytesParseFail(anyhow!("fail to parse u64 from bytes: {}", errmsg))
-            })?,
-    );
+    let val =
+        u64::from_le_bytes(buf[*head..*head + 8].try_into().map_err(|errmsg| {
+            BytesParseFail(anyhow!("fail to parse u64 from bytes: {}", errmsg))
+        })?);
     *head += 8;
     Ok(val)
 }
@@ -302,21 +280,8 @@
     head: &mut usize,
 ) -> Result<String, AconfigStorageError> {
     let num_bytes = read_u32_from_bytes(buf, head)? as usize;
-    // TODO(opg): Document this limitation and check it when creating files.
-    if num_bytes > 1024 {
-        return Err(AconfigStorageError::BytesParseFail(anyhow!(
-            "fail to parse string from bytes, string is too long (found {}, max is 1024)",
-            num_bytes
-        )));
-    }
-    let val = String::from_utf8(
-        buf.get(*head..*head + num_bytes)
-            .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
-                "fail to parse string from bytes: access out of bounds"
-            )))?
-            .to_vec(),
-    )
-    .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse string from bytes: {}", errmsg)))?;
+    let val = String::from_utf8(buf[*head..*head + num_bytes].to_vec())
+        .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse string from bytes: {}", errmsg)))?;
     *head += num_bytes;
     Ok(val)
 }
@@ -568,41 +533,18 @@
     };
 
     #[test]
-    fn test_list_flags_with_missing_files_error() {
-        let flag_list_error = list_flags("does", "not", "exist").unwrap_err();
-        assert_eq!(
-            format!("{:?}", flag_list_error),
-            format!(
-                "FileReadFail(Failed to open file does: No such file or directory (os error 2))"
-            )
-        );
-    }
-
-    #[test]
-    fn test_list_flags_with_invalid_files_error() {
-        let invalid_bytes: [u8; 3] = [0; 3];
-        let package_table = write_bytes_to_temp_file(&invalid_bytes).unwrap();
-        let flag_table = write_bytes_to_temp_file(&invalid_bytes).unwrap();
-        let flag_value_list = write_bytes_to_temp_file(&invalid_bytes).unwrap();
-        let package_table_path = package_table.path().display().to_string();
-        let flag_table_path = flag_table.path().display().to_string();
-        let flag_value_list_path = flag_value_list.path().display().to_string();
-        let flag_list_error =
-            list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap_err();
-        assert_eq!(
-            format!("{:?}", flag_list_error),
-            format!("BytesParseFail(fail to parse u32 from bytes: access out of bounds)")
-        );
-    }
-
-    #[test]
     // this test point locks down the flag list api
     fn test_list_flag() {
         let package_table =
-            write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap();
-        let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap();
-        let flag_value_list =
-            write_bytes_to_temp_file(&create_test_flag_value_list().into_bytes()).unwrap();
+            write_bytes_to_temp_file(&create_test_package_table(DEFAULT_FILE_VERSION).into_bytes())
+                .unwrap();
+        let flag_table =
+            write_bytes_to_temp_file(&create_test_flag_table(DEFAULT_FILE_VERSION).into_bytes())
+                .unwrap();
+        let flag_value_list = write_bytes_to_temp_file(
+            &create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes(),
+        )
+        .unwrap();
 
         let package_table_path = package_table.path().display().to_string();
         let flag_table_path = flag_table.path().display().to_string();
@@ -667,12 +609,19 @@
     // this test point locks down the flag list with info api
     fn test_list_flag_with_info() {
         let package_table =
-            write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap();
-        let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap();
-        let flag_value_list =
-            write_bytes_to_temp_file(&create_test_flag_value_list().into_bytes()).unwrap();
-        let flag_info_list =
-            write_bytes_to_temp_file(&create_test_flag_info_list().into_bytes()).unwrap();
+            write_bytes_to_temp_file(&create_test_package_table(DEFAULT_FILE_VERSION).into_bytes())
+                .unwrap();
+        let flag_table =
+            write_bytes_to_temp_file(&create_test_flag_table(DEFAULT_FILE_VERSION).into_bytes())
+                .unwrap();
+        let flag_value_list = write_bytes_to_temp_file(
+            &create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes(),
+        )
+        .unwrap();
+        let flag_info_list = write_bytes_to_temp_file(
+            &create_test_flag_info_list(DEFAULT_FILE_VERSION).into_bytes(),
+        )
+        .unwrap();
 
         let package_table_path = package_table.path().display().to_string();
         let flag_table_path = flag_table.path().display().to_string();
diff --git a/tools/aconfig/aconfig_storage_file/src/package_table.rs b/tools/aconfig/aconfig_storage_file/src/package_table.rs
index af39fbc..21357c7 100644
--- a/tools/aconfig/aconfig_storage_file/src/package_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/package_table.rs
@@ -100,6 +100,7 @@
 pub struct PackageTableNode {
     pub package_name: String,
     pub package_id: u32,
+    pub fingerprint: u64,
     // The index of the first boolean flag in this aconfig package among all boolean
     // flags in this container.
     pub boolean_start_index: u32,
@@ -111,8 +112,12 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         writeln!(
             f,
-            "Package: {}, Id: {}, Boolean flag start index: {}, Next: {:?}",
-            self.package_name, self.package_id, self.boolean_start_index, self.next_offset
+            "Package: {}, Id: {}, Fingerprint: {}, Boolean flag start index: {}, Next: {:?}",
+            self.package_name,
+            self.package_id,
+            self.fingerprint,
+            self.boolean_start_index,
+            self.next_offset
         )?;
         Ok(())
     }
@@ -146,9 +151,7 @@
         result.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
         result.extend_from_slice(name_bytes);
         result.extend_from_slice(&self.package_id.to_le_bytes());
-        // V2 storage files have a fingerprint. Current struct (v1) does not, so
-        // we write 0.
-        result.extend_from_slice(&0u64.to_le_bytes());
+        result.extend_from_slice(&self.fingerprint.to_le_bytes());
         result.extend_from_slice(&self.boolean_start_index.to_le_bytes());
         result.extend_from_slice(&self.next_offset.unwrap_or(0).to_le_bytes());
         result
@@ -172,13 +175,15 @@
         let mut head = 0;
         let package_name = read_str_from_bytes(bytes, &mut head)?;
         let package_id = read_u32_from_bytes(bytes, &mut head)?;
+        // v1 does not have fingerprint, so just set to 0.
+        let fingerprint: u64 = 0;
         let boolean_start_index = read_u32_from_bytes(bytes, &mut head)?;
         let next_offset = match read_u32_from_bytes(bytes, &mut head)? {
             0 => None,
             val => Some(val),
         };
 
-        let node = Self { package_name, package_id, boolean_start_index, next_offset };
+        let node = Self { package_name, package_id, fingerprint, boolean_start_index, next_offset };
         Ok(node)
     }
 
@@ -186,18 +191,14 @@
         let mut head = 0;
         let package_name = read_str_from_bytes(bytes, &mut head)?;
         let package_id = read_u32_from_bytes(bytes, &mut head)?;
-
-        // Fingerprint is unused in the current struct (v1), but we need to read
-        // the bytes if the storage file type is v2 or else the subsequent
-        // fields will be inaccurate.
-        let _fingerprint = read_u64_from_bytes(bytes, &mut head)?;
+        let fingerprint = read_u64_from_bytes(bytes, &mut head)?;
         let boolean_start_index = read_u32_from_bytes(bytes, &mut head)?;
         let next_offset = match read_u32_from_bytes(bytes, &mut head)? {
             0 => None,
             val => Some(val),
         };
 
-        let node = Self { package_name, package_id, boolean_start_index, next_offset };
+        let node = Self { package_name, package_id, fingerprint, boolean_start_index, next_offset };
         Ok(node)
     }
 
@@ -281,13 +282,37 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::read_u32_from_start_of_bytes;
-    use crate::{test_utils::create_test_package_table, DEFAULT_FILE_VERSION};
+    use crate::test_utils::create_test_package_table;
+    use crate::{read_u32_from_start_of_bytes, DEFAULT_FILE_VERSION, MAX_SUPPORTED_FILE_VERSION};
 
     #[test]
     // this test point locks down the table serialization
-    fn test_serialization() {
-        let package_table = create_test_package_table();
+    // 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());
+
+        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]
+    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());
@@ -312,44 +337,36 @@
     // this test point locks down that version number should be at the top of serialized
     // bytes
     fn test_version_number() {
-        let package_table = create_test_package_table();
+        let package_table = create_test_package_table(DEFAULT_FILE_VERSION);
         let bytes = &package_table.into_bytes();
-        let version = read_u32_from_start_of_bytes(bytes).unwrap();
-        assert_eq!(version, DEFAULT_FILE_VERSION);
+        let unpacked_version = read_u32_from_start_of_bytes(bytes).unwrap();
+        assert_eq!(unpacked_version, DEFAULT_FILE_VERSION);
     }
 
     #[test]
-    fn test_round_trip_v1() {
-        let table_v1: PackageTable = create_test_package_table();
-        let table_bytes_v1 = table_v1.into_bytes();
+    fn test_round_trip_default() {
+        let table: PackageTable = create_test_package_table(DEFAULT_FILE_VERSION);
+        let table_bytes = table.into_bytes();
 
-        // Will automatically read from version 2 as the version code is encoded
-        // into the bytes.
-        let reinterpreted_table = PackageTable::from_bytes(&table_bytes_v1).unwrap();
+        let reinterpreted_table = PackageTable::from_bytes(&table_bytes).unwrap();
 
-        assert_eq!(table_v1, reinterpreted_table);
+        assert_eq!(table, reinterpreted_table);
     }
 
     #[test]
-    fn test_round_trip_v2() {
-        // Have to fake v2 because though we will set the version to v2
-        // and write the bytes as v2, we don't have the ability to actually set
-        // the fingerprint yet.
-        let mut fake_table_v2 = create_test_package_table();
-        fake_table_v2.header.version = 2;
-        let table_bytes_v2 = fake_table_v2.into_bytes();
+    fn test_round_trip_max() {
+        let table: PackageTable = create_test_package_table(MAX_SUPPORTED_FILE_VERSION);
+        let table_bytes = table.into_bytes();
 
-        // Will automatically read from version 2 as the version code is encoded
-        // into the bytes.
-        let reinterpreted_table = PackageTable::from_bytes(&table_bytes_v2).unwrap();
+        let reinterpreted_table = PackageTable::from_bytes(&table_bytes).unwrap();
 
-        assert_eq!(fake_table_v2, reinterpreted_table);
+        assert_eq!(table, reinterpreted_table);
     }
 
     #[test]
     // this test point locks down file type check
     fn test_file_type_check() {
-        let mut package_table = create_test_package_table();
+        let mut package_table = create_test_package_table(DEFAULT_FILE_VERSION);
         package_table.header.file_type = 123u8;
         let error = PackageTable::from_bytes(&package_table.into_bytes()).unwrap_err();
         assert_eq!(
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
index 5c364f6..55780ed 100644
--- a/tools/aconfig/aconfig_storage_file/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -18,38 +18,53 @@
 use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
 use crate::flag_value::{FlagValueHeader, FlagValueList};
 use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
-use crate::{AconfigStorageError, StorageFileType, StoredFlagType, DEFAULT_FILE_VERSION};
+use crate::{AconfigStorageError, StorageFileType, StoredFlagType};
 
 use anyhow::anyhow;
 use std::io::Write;
 use tempfile::NamedTempFile;
 
-pub fn create_test_package_table() -> PackageTable {
+pub fn create_test_package_table(version: u32) -> PackageTable {
     let header = PackageTableHeader {
-        version: DEFAULT_FILE_VERSION,
+        version: version,
         container: String::from("mockup"),
         file_type: StorageFileType::PackageMap as u8,
-        file_size: 209,
+        file_size: match version {
+            1 => 209,
+            2 => 233,
+            _ => panic!("Unsupported version."),
+        },
         num_packages: 3,
         bucket_offset: 31,
         node_offset: 59,
     };
-    let buckets: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), None, None, None];
+    let buckets: Vec<Option<u32>> = match version {
+        1 => vec![Some(59), None, None, Some(109), None, None, None],
+        2 => vec![Some(59), None, None, Some(117), None, None, None],
+        _ => panic!("Unsupported version."),
+    };
     let first_node = PackageTableNode {
         package_name: String::from("com.android.aconfig.storage.test_2"),
         package_id: 1,
+        fingerprint: 0,
         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,
         boolean_start_index: 0,
-        next_offset: Some(159),
+        next_offset: match version {
+            1 => Some(159),
+            2 => Some(175),
+            _ => panic!("Unsupported version."),
+        },
     };
     let third_node = PackageTableNode {
         package_name: String::from("com.android.aconfig.storage.test_4"),
         package_id: 2,
+        fingerprint: 0,
         boolean_start_index: 6,
         next_offset: None,
     };
@@ -76,9 +91,9 @@
     }
 }
 
-pub fn create_test_flag_table() -> FlagTable {
+pub fn create_test_flag_table(version: u32) -> FlagTable {
     let header = FlagTableHeader {
-        version: DEFAULT_FILE_VERSION,
+        version: version,
         container: String::from("mockup"),
         file_type: StorageFileType::FlagMap as u8,
         file_size: 321,
@@ -118,9 +133,9 @@
     FlagTable { header, buckets, nodes }
 }
 
-pub fn create_test_flag_value_list() -> FlagValueList {
+pub fn create_test_flag_value_list(version: u32) -> FlagValueList {
     let header = FlagValueHeader {
-        version: DEFAULT_FILE_VERSION,
+        version: version,
         container: String::from("mockup"),
         file_type: StorageFileType::FlagVal as u8,
         file_size: 35,
@@ -131,9 +146,9 @@
     FlagValueList { header, booleans }
 }
 
-pub fn create_test_flag_info_list() -> FlagInfoList {
+pub fn create_test_flag_info_list(version: u32) -> FlagInfoList {
     let header = FlagInfoHeader {
-        version: DEFAULT_FILE_VERSION,
+        version: version,
         container: String::from("mockup"),
         file_type: StorageFileType::FlagInfo as u8,
         file_size: 35,
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/StorageFileProvider.java
similarity index 92%
rename from tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
rename to tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/StorageFileProvider.java
index b28341e..8306cc6 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/StorageFileProvider.java
@@ -21,6 +21,7 @@
 import java.nio.channels.FileChannel;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
@@ -51,14 +52,6 @@
     }
 
     /** @hide */
-    public boolean containerFileExists(String container) {
-        if (container == null) {
-            return Files.exists(Paths.get(mMapPath));
-        }
-        return Files.exists(Paths.get(mMapPath, container + PMAP_FILE_EXT));
-    }
-
-    /** @hide */
     public List<Path> listPackageMapFiles() {
         List<Path> result = new ArrayList<>();
         try {
@@ -66,8 +59,9 @@
                     Files.newDirectoryStream(Paths.get(mMapPath), "*" + PMAP_FILE_EXT);
             for (Path entry : stream) {
                 result.add(entry);
-                // sb.append(entry. toString());
             }
+        } catch (NoSuchFileException e) {
+            return result;
         } catch (Exception e) {
             throw new AconfigStorageException(
                     String.format("Fail to list map files in path %s", mMapPath), e);
diff --git a/tools/aconfig/aconfig_storage_file/tests/Android.bp b/tools/aconfig/aconfig_storage_file/tests/Android.bp
index 13d3214..bd46d5f 100644
--- a/tools/aconfig/aconfig_storage_file/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/tests/Android.bp
@@ -10,10 +10,14 @@
         "libbase",
     ],
     data: [
-        "data/v1/package.map",
-        "data/v1/flag.map",
-        "data/v1/flag.val",
-        "data/v1/flag.info",
+        "data/v1/package_v1.map",
+        "data/v1/flag_v1.map",
+        "data/v1/flag_v1.val",
+        "data/v1/flag_v1.info",
+        "data/v2/package_v2.map",
+        "data/v2/flag_v2.map",
+        "data/v2/flag_v2.val",
+        "data/v2/flag_v2.info",
     ],
     test_suites: [
         "device-tests",
@@ -35,10 +39,14 @@
     test_config: "AndroidStorageJaveTest.xml",
     sdk_version: "test_current",
     data: [
-        "data/v1/package.map",
-        "data/v1/flag.map",
-        "data/v1/flag.val",
-        "data/v1/flag.info",
+        "data/v1/package_v1.map",
+        "data/v1/flag_v1.map",
+        "data/v1/flag_v1.val",
+        "data/v1/flag_v1.info",
+        "data/v2/package_v2.map",
+        "data/v2/flag_v2.map",
+        "data/v2/flag_v2.val",
+        "data/v2/flag_v2.info",
     ],
     test_suites: [
         "general-tests",
diff --git a/tools/aconfig/aconfig_storage_file/tests/AndroidStorageJaveTest.xml b/tools/aconfig/aconfig_storage_file/tests/AndroidStorageJaveTest.xml
index 2d52d44..bfc238e 100644
--- a/tools/aconfig/aconfig_storage_file/tests/AndroidStorageJaveTest.xml
+++ b/tools/aconfig/aconfig_storage_file/tests/AndroidStorageJaveTest.xml
@@ -21,13 +21,18 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
-        <option name="push" value="package.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/package.map" />
-        <option name="push" value="flag.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/flag.map" />
-        <option name="push" value="flag.val->/data/local/tmp/aconfig_storage_file_test_java/testdata/flag.val" />
-        <option name="push" value="flag.info->/data/local/tmp/aconfig_storage_file_test_java/testdata/flag.info" />
+        <option name="push" value="package_v1.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v1.package.map" />
+        <option name="push" value="flag_v1.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v1.flag.map" />
+        <option name="push" value="flag_v1.val->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v1.val" />
+        <option name="push" value="flag_v1.info->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v1.info" />
+        <option name="push" value="package_v2.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v2.package.map" />
+        <option name="push" value="flag_v2.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v2.flag.map" />
+        <option name="push" value="flag_v2.val->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v2.val" />
+        <option name="push" value="flag_v2.info->/data/local/tmp/aconfig_storage_file_test_java/testdata/mock.v2.info" />
+        <option name="post-push" value="chmod +r /data/local/tmp/aconfig_storage_file_test_java/testdata/" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.aconfig.storage.test" />
         <option name="runtime-hint" value="1m" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v1/flag.info b/tools/aconfig/aconfig_storage_file/tests/data/v1/flag_v1.info
similarity index 100%
rename from tools/aconfig/aconfig_storage_file/tests/data/v1/flag.info
rename to tools/aconfig/aconfig_storage_file/tests/data/v1/flag_v1.info
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v1/flag.map b/tools/aconfig/aconfig_storage_file/tests/data/v1/flag_v1.map
similarity index 100%
rename from tools/aconfig/aconfig_storage_file/tests/data/v1/flag.map
rename to tools/aconfig/aconfig_storage_file/tests/data/v1/flag_v1.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v1/flag.val b/tools/aconfig/aconfig_storage_file/tests/data/v1/flag_v1.val
similarity index 100%
rename from tools/aconfig/aconfig_storage_file/tests/data/v1/flag.val
rename to tools/aconfig/aconfig_storage_file/tests/data/v1/flag_v1.val
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v1/package.map b/tools/aconfig/aconfig_storage_file/tests/data/v1/package_v1.map
similarity index 100%
rename from tools/aconfig/aconfig_storage_file/tests/data/v1/package.map
rename to tools/aconfig/aconfig_storage_file/tests/data/v1/package_v1.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.info b/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.info
new file mode 100644
index 0000000..9db7fde
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.info
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.map b/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.map
new file mode 100644
index 0000000..cf4685c
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.val b/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.val
new file mode 100644
index 0000000..37d4750
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/data/v2/flag_v2.val
Binary files differ
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
new file mode 100644
index 0000000..16f4054
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/data/v2/package_v2.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/jarjar.txt b/tools/aconfig/aconfig_storage_file/tests/jarjar.txt
index a6c17fa..24952ec 100644
--- a/tools/aconfig/aconfig_storage_file/tests/jarjar.txt
+++ b/tools/aconfig/aconfig_storage_file/tests/jarjar.txt
@@ -7,6 +7,8 @@
 rule android.aconfig.storage.FileType android.aconfig.storage.test.FileType
 rule android.aconfig.storage.FlagValueList android.aconfig.storage.test.FlagValueList
 rule android.aconfig.storage.TableUtils android.aconfig.storage.test.TableUtils
+rule android.aconfig.storage.AconfigPackageImpl android.aconfig.storage.test.AconfigPackageImpl
+rule android.aconfig.storage.StorageFileProvider android.aconfig.storage.test.StorageFileProvider
 
 
 rule android.aconfig.storage.FlagTable$* android.aconfig.storage.test.FlagTable$@1
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/FlagTableTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/FlagTableTest.java
index fd40d4c..dc465b6 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/FlagTableTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/FlagTableTest.java
@@ -31,7 +31,7 @@
 
     @Test
     public void testFlagTable_rightHeader() throws Exception {
-        FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
+        FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer(1));
         FlagTable.Header header = flagTable.getHeader();
         assertEquals(1, header.getVersion());
         assertEquals("mockup", header.getContainer());
@@ -44,7 +44,7 @@
 
     @Test
     public void testFlagTable_rightNode() throws Exception {
-        FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
+        FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer(1));
 
         FlagTable.Node node1 = flagTable.get(0, "enabled_ro");
         FlagTable.Node node2 = flagTable.get(0, "enabled_rw");
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/FlagValueListTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/FlagValueListTest.java
index 1b0de63..306df7d 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/FlagValueListTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/FlagValueListTest.java
@@ -34,7 +34,7 @@
     @Test
     public void testFlagValueList_rightHeader() throws Exception {
         FlagValueList flagValueList =
-                FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
+                FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer(1));
         FlagValueList.Header header = flagValueList.getHeader();
         assertEquals(1, header.getVersion());
         assertEquals("mockup", header.getContainer());
@@ -47,7 +47,7 @@
     @Test
     public void testFlagValueList_rightNode() throws Exception {
         FlagValueList flagValueList =
-                FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
+                FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer(1));
 
         boolean[] expected = new boolean[] {false, true, true, false, true, true, true, true};
         assertEquals(expected.length, flagValueList.size());
@@ -60,11 +60,11 @@
     @Test
     public void testFlagValueList_getValue() throws Exception {
         PackageTable packageTable =
-                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
-        FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
+                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer(1));
+        FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer(1));
 
         FlagValueList flagValueList =
-                FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
+                FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer(1));
 
         PackageTable.Node pNode = packageTable.get("com.android.aconfig.storage.test_1");
         FlagTable.Node fNode = flagTable.get(pNode.getPackageId(), "enabled_rw");
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
index dc2ad92..4d7ab2a 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.aconfig.storage.FileType;
 import android.aconfig.storage.PackageTable;
@@ -32,7 +33,7 @@
     @Test
     public void testPackageTable_rightHeader() throws Exception {
         PackageTable packageTable =
-                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
+                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer(1));
         PackageTable.Header header = packageTable.getHeader();
         assertEquals(1, header.getVersion());
         assertEquals("mockup", header.getContainer());
@@ -44,9 +45,23 @@
     }
 
     @Test
+    public void testPackageTable_rightHeader_v2() throws Exception {
+        PackageTable packageTable =
+                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer(2));
+        PackageTable.Header header = packageTable.getHeader();
+        assertEquals(2, header.getVersion());
+        assertEquals("mockup", header.getContainer());
+        assertEquals(FileType.PACKAGE_MAP, header.getFileType());
+        assertEquals(233, header.getFileSize());
+        assertEquals(3, header.getNumPackages());
+        assertEquals(31, header.getBucketOffset());
+        assertEquals(59, header.getNodeOffset());
+    }
+
+    @Test
     public void testPackageTable_rightNode() throws Exception {
         PackageTable packageTable =
-                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
+                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer(1));
 
         PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
         PackageTable.Node node2 = packageTable.get("com.android.aconfig.storage.test_2");
@@ -72,4 +87,34 @@
         assertFalse(node2.hasPackageFingerprint());
         assertFalse(node4.hasPackageFingerprint());
     }
+
+    @Test
+    public void testPackageTable_rightNode_v2() throws Exception {
+        PackageTable packageTable =
+                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer(2));
+
+        PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
+        PackageTable.Node node2 = packageTable.get("com.android.aconfig.storage.test_2");
+        PackageTable.Node node4 = packageTable.get("com.android.aconfig.storage.test_4");
+
+        assertEquals("com.android.aconfig.storage.test_1", node1.getPackageName());
+        assertEquals("com.android.aconfig.storage.test_2", node2.getPackageName());
+        assertEquals("com.android.aconfig.storage.test_4", node4.getPackageName());
+
+        assertEquals(0, node1.getPackageId());
+        assertEquals(1, node2.getPackageId());
+        assertEquals(2, node4.getPackageId());
+
+        assertEquals(0, node1.getBooleanStartIndex());
+        assertEquals(3, node2.getBooleanStartIndex());
+        assertEquals(6, node4.getBooleanStartIndex());
+
+        assertEquals(175, node1.getNextOffset());
+        assertEquals(-1, node2.getNextOffset());
+        assertEquals(-1, node4.getNextOffset());
+
+        assertTrue(node1.hasPackageFingerprint());
+        assertTrue(node2.hasPackageFingerprint());
+        assertTrue(node4.hasPackageFingerprint());
+    }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/StorageFileProviderTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java
similarity index 63%
rename from tools/aconfig/aconfig_storage_read_api/tests/java/StorageFileProviderTest.java
rename to tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java
index ba1ae9e..4e90e6c 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/StorageFileProviderTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/StorageFileProviderTest.java
@@ -17,7 +17,6 @@
 package android.aconfig.storage.test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -38,43 +37,31 @@
 public class StorageFileProviderTest {
 
     @Test
-    public void testContainerFileExists() throws Exception {
-        StorageFileProvider p =
-                new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
-        assertTrue(p.containerFileExists(null));
-        assertTrue(p.containerFileExists("mockup"));
-        assertFalse(p.containerFileExists("fake"));
-    }
-
-    @Test
     public void testListpackageMapFiles() throws Exception {
         StorageFileProvider p =
                 new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
-        // throw new Exception(Environment.getExternalStorageDirectory().getAbsolutePath());
         List<Path> file = p.listPackageMapFiles();
-        assertEquals(1, file.size());
-        assertTrue(
-                file.get(0)
-                        .equals(
-                                Paths.get(
-                                        TestDataUtils.TESTDATA_PATH,
-                                        TestDataUtils.TEST_PACKAGE_MAP_PATH)));
+        assertEquals(2, file.size());
+
+        p = new StorageFileProvider("fake/path/", "fake/path/");
+        file = p.listPackageMapFiles();
+        assertTrue(file.isEmpty());
     }
 
     @Test
     public void testLoadFiles() throws Exception {
         StorageFileProvider p =
                 new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
-        PackageTable pt = p.getPackageTable("mockup");
+        PackageTable pt = p.getPackageTable("mock.v1");
         assertNotNull(pt);
         pt =
                 StorageFileProvider.getPackageTable(
                         Paths.get(
-                                TestDataUtils.TESTDATA_PATH, TestDataUtils.TEST_PACKAGE_MAP_PATH));
+                                TestDataUtils.TESTDATA_PATH, "mock.v1.package.map"));
         assertNotNull(pt);
-        FlagTable f = p.getFlagTable("mockup");
+        FlagTable f = p.getFlagTable("mock.v1");
         assertNotNull(f);
-        FlagValueList v = p.getFlagValueList("mockup");
+        FlagValueList v = p.getFlagValueList("mock.v1");
         assertNotNull(v);
     }
 }
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/TestDataUtils.java b/tools/aconfig/aconfig_storage_file/tests/srcs/TestDataUtils.java
index f35952d..388971e 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/TestDataUtils.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/TestDataUtils.java
@@ -21,28 +21,27 @@
 import java.nio.ByteBuffer;
 
 public final class TestDataUtils {
-    private static final String TEST_PACKAGE_MAP_PATH = "package.map";
-    private static final String TEST_FLAG_MAP_PATH = "flag.map";
-    private static final String TEST_FLAG_VAL_PATH = "flag.val";
-    private static final String TEST_FLAG_INFO_PATH = "flag.info";
+    private static final String TEST_PACKAGE_MAP_PATH = "mock.v%d.package.map";
+    private static final String TEST_FLAG_MAP_PATH = "mock.v%d.flag.map";
+    private static final String TEST_FLAG_VAL_PATH = "mock.v%d.val";
+    private static final String TEST_FLAG_INFO_PATH = "mock.v%d.info";
 
-    private static final String TESTDATA_PATH =
-            "/data/local/tmp/aconfig_storage_file_test_java/testdata/";
+    public static final String TESTDATA_PATH = "/data/local/tmp/aconfig_storage_file_test_java/testdata/";
 
-    public static ByteBuffer getTestPackageMapByteBuffer() throws Exception {
-        return readFile(TESTDATA_PATH + TEST_PACKAGE_MAP_PATH);
+    public static ByteBuffer getTestPackageMapByteBuffer(int version) throws Exception {
+        return readFile(TESTDATA_PATH + String.format(TEST_PACKAGE_MAP_PATH, version));
     }
 
-    public static ByteBuffer getTestFlagMapByteBuffer() throws Exception {
-        return readFile(TESTDATA_PATH + TEST_FLAG_MAP_PATH);
+    public static ByteBuffer getTestFlagMapByteBuffer(int version) throws Exception {
+        return readFile(TESTDATA_PATH + String.format(TEST_FLAG_MAP_PATH, version));
     }
 
-    public static ByteBuffer getTestFlagValByteBuffer() throws Exception {
-        return readFile(TESTDATA_PATH + TEST_FLAG_VAL_PATH);
+    public static ByteBuffer getTestFlagValByteBuffer(int version) throws Exception {
+        return readFile(TESTDATA_PATH + String.format(TEST_FLAG_VAL_PATH, version));
     }
 
-    public static ByteBuffer getTestFlagInfoByteBuffer() throws Exception {
-        return readFile(TESTDATA_PATH + TEST_FLAG_INFO_PATH);
+    public static ByteBuffer getTestFlagInfoByteBuffer(int version) throws Exception {
+        return readFile(TESTDATA_PATH + String.format(TEST_FLAG_INFO_PATH, version));
     }
 
     private static ByteBuffer readFile(String fileName) throws Exception {
diff --git a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
index 3626f72..5c008af 100644
--- a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
+++ b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
@@ -24,10 +24,8 @@
 using namespace android::base;
 using namespace aconfig_storage;
 
-void verify_value(const FlagValueSummary& flag,
-                  const std::string& package_name,
-                  const std::string& flag_name,
-                  const std::string& flag_val,
+void verify_value(const FlagValueSummary& flag, const std::string& package_name,
+                  const std::string& flag_name, const std::string& flag_val,
                   const std::string& value_type) {
   ASSERT_EQ(flag.package_name, package_name);
   ASSERT_EQ(flag.flag_name, flag_name);
@@ -39,10 +37,8 @@
                        const std::string& package_name,
                        const std::string& flag_name,
                        const std::string& flag_val,
-                       const std::string& value_type,
-                       bool is_readwrite,
-                       bool has_server_override,
-                       bool has_local_override) {
+                       const std::string& value_type, bool is_readwrite,
+                       bool has_server_override, bool has_local_override) {
   ASSERT_EQ(flag.package_name, package_name);
   ASSERT_EQ(flag.flag_name, flag_name);
   ASSERT_EQ(flag.flag_value, flag_val);
@@ -52,63 +48,137 @@
   ASSERT_EQ(flag.has_local_override, has_local_override);
 }
 
-TEST(AconfigStorageFileTest, test_list_flag) {
+Result<std::vector<FlagValueSummary>> get_flag_list_result(
+    const std::string version) {
   auto const test_base_dir = GetExecutableDirectory();
-  auto const test_dir = test_base_dir + "/data/v1";
-  auto const package_map = test_dir + "/package.map";
-  auto const flag_map = test_dir + "/flag.map";
-  auto const flag_val = test_dir + "/flag.val";
-  auto flag_list_result = aconfig_storage::list_flags(
-      package_map, flag_map, flag_val);
+  auto const test_dir = test_base_dir + "/data/v" + version;
+  auto const package_map = test_dir + "/package_v" + version + ".map";
+  auto const flag_map = test_dir + "/flag_v" + version + ".map";
+  auto const flag_val = test_dir + "/flag_v" + version + ".val";
+  return aconfig_storage::list_flags(package_map, flag_map, flag_val);
+}
+
+Result<std::vector<FlagValueAndInfoSummary>> get_flag_list_result_with_info(
+    const std::string version) {
+  auto const test_base_dir = GetExecutableDirectory();
+  auto const test_dir = test_base_dir + "/data/v" + version;
+  auto const package_map = test_dir + "/package_v" + version + ".map";
+  auto const flag_map = test_dir + "/flag_v" + version + ".map";
+  auto const flag_val = test_dir + "/flag_v" + version + ".val";
+  auto const flag_info = test_dir + "/flag_v" + version + ".info";
+  return aconfig_storage::list_flags_with_info(package_map, flag_map, flag_val,
+                                               flag_info);
+}
+
+TEST(AconfigStorageFileTest, test_list_flag) {
+  auto flag_list_result = get_flag_list_result("1");
   ASSERT_TRUE(flag_list_result.ok());
 
   auto const& flag_list = *flag_list_result;
   ASSERT_EQ(flag_list.size(), 8);
-  verify_value(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
-               "false", "ReadWriteBoolean");
+  verify_value(flag_list[0], "com.android.aconfig.storage.test_1",
+               "disabled_rw", "false", "ReadWriteBoolean");
   verify_value(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
                "true", "ReadOnlyBoolean");
   verify_value(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
                "true", "ReadWriteBoolean");
-  verify_value(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
-               "false", "ReadWriteBoolean");
-  verify_value(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
-               "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[3], "com.android.aconfig.storage.test_2",
+               "disabled_rw", "false", "ReadWriteBoolean");
+  verify_value(flag_list[4], "com.android.aconfig.storage.test_2",
+               "enabled_fixed_ro", "true", "FixedReadOnlyBoolean");
   verify_value(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
                "true", "ReadOnlyBoolean");
-  verify_value(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
-               "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[6], "com.android.aconfig.storage.test_4",
+               "enabled_fixed_ro", "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
+               "true", "ReadWriteBoolean");
+}
+
+// TODO: b/376256472 - Use parameterized tests.
+TEST(AconfigStorageFileTest, test_list_flag_v2) {
+  auto flag_list_result = get_flag_list_result("2");
+  ASSERT_TRUE(flag_list_result.ok());
+
+  auto const& flag_list = *flag_list_result;
+  ASSERT_EQ(flag_list.size(), 8);
+  verify_value(flag_list[0], "com.android.aconfig.storage.test_1",
+               "disabled_rw", "false", "ReadWriteBoolean");
+  verify_value(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
+               "true", "ReadOnlyBoolean");
+  verify_value(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
+               "true", "ReadWriteBoolean");
+  verify_value(flag_list[3], "com.android.aconfig.storage.test_2",
+               "disabled_rw", "false", "ReadWriteBoolean");
+  verify_value(flag_list[4], "com.android.aconfig.storage.test_2",
+               "enabled_fixed_ro", "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
+               "true", "ReadOnlyBoolean");
+  verify_value(flag_list[6], "com.android.aconfig.storage.test_4",
+               "enabled_fixed_ro", "true", "FixedReadOnlyBoolean");
   verify_value(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
                "true", "ReadWriteBoolean");
 }
 
 TEST(AconfigStorageFileTest, test_list_flag_with_info) {
-  auto const base_test_dir = GetExecutableDirectory();
-  auto const test_dir = base_test_dir + "/data/v1";
-  auto const package_map = test_dir + "/package.map";
-  auto const flag_map = test_dir + "/flag.map";
-  auto const flag_val = test_dir + "/flag.val";
-  auto const flag_info = test_dir + "/flag.info";
-  auto flag_list_result = aconfig_storage::list_flags_with_info(
-      package_map, flag_map, flag_val, flag_info);
+  auto flag_list_result = get_flag_list_result_with_info("1");
   ASSERT_TRUE(flag_list_result.ok());
 
   auto const& flag_list = *flag_list_result;
   ASSERT_EQ(flag_list.size(), 8);
-  verify_value_info(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
-                    "false", "ReadWriteBoolean", true, false, false);
-  verify_value_info(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
-                    "true", "ReadOnlyBoolean", false, false, false);
-  verify_value_info(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
-                    "true", "ReadWriteBoolean", true, false, false);
-  verify_value_info(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
-                    "false", "ReadWriteBoolean", true, false, false);
-  verify_value_info(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
-                    "true", "FixedReadOnlyBoolean", false, false, false);
-  verify_value_info(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
-                    "true", "ReadOnlyBoolean", false, false, false);
-  verify_value_info(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
-                    "true", "FixedReadOnlyBoolean", false, false, false);
-  verify_value_info(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
-                    "true", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[0], "com.android.aconfig.storage.test_1",
+                    "disabled_rw", "false", "ReadWriteBoolean", true, false,
+                    false);
+  verify_value_info(flag_list[1], "com.android.aconfig.storage.test_1",
+                    "enabled_ro", "true", "ReadOnlyBoolean", false, false,
+                    false);
+  verify_value_info(flag_list[2], "com.android.aconfig.storage.test_1",
+                    "enabled_rw", "true", "ReadWriteBoolean", true, false,
+                    false);
+  verify_value_info(flag_list[3], "com.android.aconfig.storage.test_2",
+                    "disabled_rw", "false", "ReadWriteBoolean", true, false,
+                    false);
+  verify_value_info(flag_list[4], "com.android.aconfig.storage.test_2",
+                    "enabled_fixed_ro", "true", "FixedReadOnlyBoolean", false,
+                    false, false);
+  verify_value_info(flag_list[5], "com.android.aconfig.storage.test_2",
+                    "enabled_ro", "true", "ReadOnlyBoolean", false, false,
+                    false);
+  verify_value_info(flag_list[6], "com.android.aconfig.storage.test_4",
+                    "enabled_fixed_ro", "true", "FixedReadOnlyBoolean", false,
+                    false, false);
+  verify_value_info(flag_list[7], "com.android.aconfig.storage.test_4",
+                    "enabled_rw", "true", "ReadWriteBoolean", true, false,
+                    false);
+}
+
+TEST(AconfigStorageFileTest, test_list_flag_with_info_v2) {
+  auto flag_list_result = get_flag_list_result_with_info("2");
+  ASSERT_TRUE(flag_list_result.ok());
+
+  auto const& flag_list = *flag_list_result;
+  ASSERT_EQ(flag_list.size(), 8);
+  verify_value_info(flag_list[0], "com.android.aconfig.storage.test_1",
+                    "disabled_rw", "false", "ReadWriteBoolean", true, false,
+                    false);
+  verify_value_info(flag_list[1], "com.android.aconfig.storage.test_1",
+                    "enabled_ro", "true", "ReadOnlyBoolean", false, false,
+                    false);
+  verify_value_info(flag_list[2], "com.android.aconfig.storage.test_1",
+                    "enabled_rw", "true", "ReadWriteBoolean", true, false,
+                    false);
+  verify_value_info(flag_list[3], "com.android.aconfig.storage.test_2",
+                    "disabled_rw", "false", "ReadWriteBoolean", true, false,
+                    false);
+  verify_value_info(flag_list[4], "com.android.aconfig.storage.test_2",
+                    "enabled_fixed_ro", "true", "FixedReadOnlyBoolean", false,
+                    false, false);
+  verify_value_info(flag_list[5], "com.android.aconfig.storage.test_2",
+                    "enabled_ro", "true", "ReadOnlyBoolean", false, false,
+                    false);
+  verify_value_info(flag_list[6], "com.android.aconfig.storage.test_4",
+                    "enabled_fixed_ro", "true", "FixedReadOnlyBoolean", false,
+                    false, false);
+  verify_value_info(flag_list[7], "com.android.aconfig.storage.test_4",
+                    "enabled_rw", "true", "ReadWriteBoolean", true, false,
+                    false);
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 666c5ba..3238d79 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -36,10 +36,10 @@
         "librand",
     ],
     data: [
-        "tests/data/v1/package.map",
-        "tests/data/v1/flag.map",
-        "tests/data/v1/flag.val",
-        "tests/data/v1/flag.info",
+        "tests/data/v1/package_v1.map",
+        "tests/data/v1/flag_v1.map",
+        "tests/data/v1/flag_v1.val",
+        "tests/data/v1/flag_v1.info",
     ],
 }
 
@@ -155,7 +155,6 @@
     name: "aconfig_storage_reader_java",
     srcs: [
         "srcs/android/aconfig/storage/AconfigPackageImpl.java",
-        "srcs/android/aconfig/storage/StorageFileProvider.java",
         "srcs/android/aconfig/storage/StorageInternalReader.java",
     ],
     libs: [
@@ -178,7 +177,6 @@
     name: "aconfig_storage_reader_java_none",
     srcs: [
         "srcs/android/aconfig/storage/AconfigPackageImpl.java",
-        "srcs/android/aconfig/storage/StorageFileProvider.java",
         "srcs/android/aconfig/storage/StorageInternalReader.java",
     ],
     libs: [
diff --git a/tools/aconfig/aconfig_storage_read_api/src/flag_info_query.rs b/tools/aconfig/aconfig_storage_read_api/src/flag_info_query.rs
index fe57a6d..68b6193 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/flag_info_query.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/flag_info_query.rs
@@ -55,12 +55,14 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::{test_utils::create_test_flag_info_list, FlagInfoBit};
+    use aconfig_storage_file::{
+        test_utils::create_test_flag_info_list, FlagInfoBit, DEFAULT_FILE_VERSION,
+    };
 
     #[test]
     // this test point locks down query if flag has server override
     fn test_is_flag_sticky() {
-        let flag_info_list = create_test_flag_info_list().into_bytes();
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION).into_bytes();
         for offset in 0..8 {
             let attribute =
                 find_flag_attribute(&flag_info_list[..], FlagValueType::Boolean, offset).unwrap();
@@ -71,7 +73,7 @@
     #[test]
     // this test point locks down query if flag is readwrite
     fn test_is_flag_readwrite() {
-        let flag_info_list = create_test_flag_info_list().into_bytes();
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION).into_bytes();
         let baseline: Vec<bool> = vec![true, false, true, true, false, false, false, true];
         for offset in 0..8 {
             let attribute =
@@ -86,7 +88,7 @@
     #[test]
     // this test point locks down query if flag has local override
     fn test_flag_has_override() {
-        let flag_info_list = create_test_flag_info_list().into_bytes();
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION).into_bytes();
         for offset in 0..8 {
             let attribute =
                 find_flag_attribute(&flag_info_list[..], FlagValueType::Boolean, offset).unwrap();
@@ -97,7 +99,7 @@
     #[test]
     // this test point locks down query beyond the end of boolean section
     fn test_boolean_out_of_range() {
-        let flag_info_list = create_test_flag_info_list().into_bytes();
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION).into_bytes();
         let error =
             find_flag_attribute(&flag_info_list[..], FlagValueType::Boolean, 8).unwrap_err();
         assert_eq!(
@@ -109,7 +111,7 @@
     #[test]
     // this test point locks down query error when file has a higher version
     fn test_higher_version_storage_file() {
-        let mut info_list = create_test_flag_info_list();
+        let mut info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
         info_list.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
         let flag_info = info_list.into_bytes();
         let error = find_flag_attribute(&flag_info[..], FlagValueType::Boolean, 4).unwrap_err();
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 e9bc604..3e87acc 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
@@ -74,12 +74,12 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::test_utils::create_test_flag_table;
+    use aconfig_storage_file::{test_utils::create_test_flag_table, DEFAULT_FILE_VERSION};
 
     #[test]
     // this test point locks down table query
     fn test_flag_query() {
-        let flag_table = create_test_flag_table().into_bytes();
+        let flag_table = create_test_flag_table(DEFAULT_FILE_VERSION).into_bytes();
         let baseline = vec![
             (0, "enabled_ro", StoredFlagType::ReadOnlyBoolean, 1u16),
             (0, "enabled_rw", StoredFlagType::ReadWriteBoolean, 2u16),
@@ -101,7 +101,7 @@
     #[test]
     // this test point locks down table query of a non exist flag
     fn test_not_existed_flag_query() {
-        let flag_table = create_test_flag_table().into_bytes();
+        let flag_table = create_test_flag_table(DEFAULT_FILE_VERSION).into_bytes();
         let flag_context = find_flag_read_context(&flag_table[..], 1, "disabled_fixed_ro").unwrap();
         assert_eq!(flag_context, None);
         let flag_context = find_flag_read_context(&flag_table[..], 2, "disabled_rw").unwrap();
@@ -111,7 +111,7 @@
     #[test]
     // this test point locks down query error when file has a higher version
     fn test_higher_version_storage_file() {
-        let mut table = create_test_flag_table();
+        let mut table = create_test_flag_table(DEFAULT_FILE_VERSION);
         table.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
         let flag_table = table.into_bytes();
         let error = find_flag_read_context(&flag_table[..], 0, "enabled_ro").unwrap_err();
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 12c1e83..35f5692 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,12 +48,12 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::test_utils::create_test_flag_value_list;
+    use aconfig_storage_file::{test_utils::create_test_flag_value_list, DEFAULT_FILE_VERSION};
 
     #[test]
     // this test point locks down flag value query
     fn test_flag_value_query() {
-        let flag_value_list = create_test_flag_value_list().into_bytes();
+        let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes();
         let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
         for (offset, expected_value) in baseline.into_iter().enumerate() {
             let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap();
@@ -64,7 +64,7 @@
     #[test]
     // this test point locks down query beyond the end of boolean section
     fn test_boolean_out_of_range() {
-        let flag_value_list = create_test_flag_value_list().into_bytes();
+        let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes();
         let error = find_boolean_flag_value(&flag_value_list[..], 8).unwrap_err();
         assert_eq!(
             format!("{:?}", error),
@@ -75,7 +75,7 @@
     #[test]
     // this test point locks down query error when file has a higher version
     fn test_higher_version_storage_file() {
-        let mut value_list = create_test_flag_value_list();
+        let mut value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
         value_list.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
         let flag_value = value_list.into_bytes();
         let error = find_boolean_flag_value(&flag_value[..], 4).unwrap_err();
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index 5104cd0..6e98fe9 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -413,10 +413,10 @@
         let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
         let flag_val = storage_dir.clone() + "/boot/mockup.val";
         let flag_info = storage_dir.clone() + "/boot/mockup.info";
-        fs::copy("./tests/data/v1/package.map", &package_map).unwrap();
-        fs::copy("./tests/data/v1/flag.map", &flag_map).unwrap();
-        fs::copy("./tests/data/v1/flag.val", &flag_val).unwrap();
-        fs::copy("./tests/data/v1/flag.info", &flag_info).unwrap();
+        fs::copy("./tests/data/v1/package_v1.map", &package_map).unwrap();
+        fs::copy("./tests/data/v1/flag_v1.map", &flag_map).unwrap();
+        fs::copy("./tests/data/v1/flag_v1.val", &flag_val).unwrap();
+        fs::copy("./tests/data/v1/flag_v1.info", &flag_info).unwrap();
 
         return storage_dir;
     }
@@ -508,9 +508,9 @@
     #[test]
     // this test point locks down flag storage file version number query api
     fn test_storage_version_query() {
-        assert_eq!(get_storage_file_version("./tests/data/v1/package.map").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./tests/data/v1/flag.map").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./tests/data/v1/flag.val").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./tests/data/v1/flag.info").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./tests/data/v1/package_v1.map").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./tests/data/v1/flag_v1.map").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./tests/data/v1/flag_v1.val").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./tests/data/v1/flag_v1.info").unwrap(), 1);
     }
 }
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 2c1884a..f4e269e 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
@@ -97,10 +97,10 @@
         let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
         let flag_val = storage_dir.clone() + "/boot/mockup.val";
         let flag_info = storage_dir.clone() + "/boot/mockup.info";
-        fs::copy("./tests/data/v1/package.map", &package_map).unwrap();
-        fs::copy("./tests/data/v1/flag.map", &flag_map).unwrap();
-        fs::copy("./tests/data/v1/flag.val", &flag_val).unwrap();
-        fs::copy("./tests/data/v1/flag.info", &flag_info).unwrap();
+        fs::copy("./tests/data/v1/package_v1.map", &package_map).unwrap();
+        fs::copy("./tests/data/v1/flag_v1.map", &flag_map).unwrap();
+        fs::copy("./tests/data/v1/flag_v1.val", &flag_val).unwrap();
+        fs::copy("./tests/data/v1/flag_v1.info", &flag_info).unwrap();
 
         return storage_dir;
     }
@@ -108,9 +108,9 @@
     #[test]
     fn test_mapped_file_contents() {
         let storage_dir = create_test_storage_files();
-        map_and_verify(&storage_dir, StorageFileType::PackageMap, "./tests/data/v1/package.map");
-        map_and_verify(&storage_dir, StorageFileType::FlagMap, "./tests/data/v1/flag.map");
-        map_and_verify(&storage_dir, StorageFileType::FlagVal, "./tests/data/v1/flag.val");
-        map_and_verify(&storage_dir, StorageFileType::FlagInfo, "./tests/data/v1/flag.info");
+        map_and_verify(&storage_dir, StorageFileType::PackageMap, "./tests/data/v1/package_v1.map");
+        map_and_verify(&storage_dir, StorageFileType::FlagMap, "./tests/data/v1/flag_v1.map");
+        map_and_verify(&storage_dir, StorageFileType::FlagVal, "./tests/data/v1/flag_v1.val");
+        map_and_verify(&storage_dir, StorageFileType::FlagInfo, "./tests/data/v1/flag_v1.info");
     }
 }
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 acb60f6..a4b63ab 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
@@ -74,12 +74,12 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::test_utils::create_test_package_table;
+    use aconfig_storage_file::{test_utils::create_test_package_table, DEFAULT_FILE_VERSION};
 
     #[test]
     // this test point locks down table query
     fn test_package_query() {
-        let package_table = create_test_package_table().into_bytes();
+        let package_table = create_test_package_table(DEFAULT_FILE_VERSION).into_bytes();
         let package_context =
             find_package_read_context(&package_table[..], "com.android.aconfig.storage.test_1")
                 .unwrap()
@@ -104,7 +104,7 @@
     // this test point locks down table query of a non exist package
     fn test_not_existed_package_query() {
         // this will land at an empty bucket
-        let package_table = create_test_package_table().into_bytes();
+        let package_table = create_test_package_table(DEFAULT_FILE_VERSION).into_bytes();
         let package_context =
             find_package_read_context(&package_table[..], "com.android.aconfig.storage.test_3")
                 .unwrap();
@@ -119,7 +119,7 @@
     #[test]
     // this test point locks down query error when file has a higher version
     fn test_higher_version_storage_file() {
-        let mut table = create_test_package_table();
+        let mut table = create_test_package_table(DEFAULT_FILE_VERSION);
         table.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
         let package_table = table.into_bytes();
         let error =
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
index c2bef31..6bf4e05 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
@@ -25,113 +25,98 @@
     private FlagTable mFlagTable;
     private FlagValueList mFlagValueList;
     private PackageTable.Node mPNode;
+    private final int mPackageId;
+    private final int mBooleanStartIndex;
 
-    /** @hide */
-    private AconfigPackageImpl() {}
+    private AconfigPackageImpl(
+            FlagTable flagTable,
+            FlagValueList flagValueList,
+            int packageId,
+            int booleanStartIndex) {
+        this.mFlagTable = flagTable;
+        this.mFlagValueList = flagValueList;
+        this.mPackageId = packageId;
+        this.mBooleanStartIndex = booleanStartIndex;
+    }
 
-    /** @hide */
     public static AconfigPackageImpl load(String packageName, StorageFileProvider fileProvider) {
-        AconfigPackageImpl impl = new AconfigPackageImpl();
-        impl.init(null, packageName, fileProvider);
-        return impl;
-    }
-
-    /** @hide */
-    public static AconfigPackageImpl load(
-            String container, String packageName, StorageFileProvider fileProvider) {
-        if (container == null) {
-            throw new AconfigStorageException(
-                    AconfigStorageException.ERROR_CONTAINER_NOT_FOUND,
-                    "container null cannot be found on the device");
-        }
-        AconfigPackageImpl impl = new AconfigPackageImpl();
-        impl.init(container, packageName, fileProvider);
-        return impl;
-    }
-
-    /** @hide */
-    public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
-        FlagTable.Node fNode = mFlagTable.get(mPNode.getPackageId(), flagName);
-        // no such flag in this package
-        if (fNode == null) return defaultValue;
-        int index = fNode.getFlagIndex() + mPNode.getBooleanStartIndex();
-        return mFlagValueList.getBoolean(index);
-    }
-
-    /** @hide */
-    public boolean getBooleanFlagValue(int index) {
-        return mFlagValueList.getBoolean(index + mPNode.getBooleanStartIndex());
-    }
-
-    /** @hide */
-    public long getPackageFingerprint() {
-        return mPNode.getPackageFingerprint();
-    }
-
-    /** @hide */
-    public boolean hasPackageFingerprint() {
-        return mPNode.hasPackageFingerprint();
-    }
-
-    private void init(String containerName, String packageName, StorageFileProvider fileProvider) {
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        String container = containerName;
+        PackageTable.Node pNode = null;
         try {
-            // for devices don't have new storage directly return
-            if (!fileProvider.containerFileExists(null)) {
-                throw new AconfigStorageException(
-                        AconfigStorageException.ERROR_STORAGE_SYSTEM_NOT_FOUND,
-                        "aconfig storage cannot be found on the device");
-            }
-            PackageTable.Node pNode = null;
-
-            if (container == null) {
-                // Check if the device has flag files on the system partition.
-                // If the device does, search the system partition first.
-                container = "system";
-                if (fileProvider.containerFileExists(container)) {
-                    pNode = fileProvider.getPackageTable(container).get(packageName);
-                }
-
-                if (pNode == null) {
-                    // Search all package map files if not found in the system partition.
-                    for (Path p : fileProvider.listPackageMapFiles()) {
-                        PackageTable pTable = StorageFileProvider.getPackageTable(p);
-                        pNode = pTable.get(packageName);
-                        if (pNode != null) {
-                            container = pTable.getHeader().getContainer();
-                            break;
-                        }
-                    }
-                }
-            } else {
-                if (!fileProvider.containerFileExists(container)) {
-                    throw new AconfigStorageException(
-                            AconfigStorageException.ERROR_CONTAINER_NOT_FOUND,
-                            "container " + container + " cannot be found on the device");
-                }
-                pNode = fileProvider.getPackageTable(container).get(packageName);
-            }
-
-            if (pNode == null) {
-                // for the case package is not found in all container, return instead of throwing
-                // error
-                throw new AconfigStorageException(
-                        AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
-                        "package "
-                                + packageName
-                                + " in container "
-                                + container
-                                + " cannot be found on the device");
-            }
-
-            mFlagTable = fileProvider.getFlagTable(container);
-            mFlagValueList = fileProvider.getFlagValueList(container);
-            mPNode = pNode;
+            // First try to find the package in the "system" container.
+            pNode = fileProvider.getPackageTable("system").get(packageName);
         } catch (Exception e) {
+            //
+        }
+        try {
+            if (pNode != null) {
+                return new AconfigPackageImpl(
+                        fileProvider.getFlagTable("system"),
+                        fileProvider.getFlagValueList("system"),
+                        pNode.getPackageId(),
+                        pNode.getBooleanStartIndex());
+            }
+
+            // If not found in "system", search all package map files.
+            for (Path p : fileProvider.listPackageMapFiles()) {
+                PackageTable pTable = fileProvider.getPackageTable(p);
+                pNode = pTable.get(packageName);
+                if (pNode != null) {
+                    return new AconfigPackageImpl(
+                            fileProvider.getFlagTable(pTable.getHeader().getContainer()),
+                            fileProvider.getFlagValueList(pTable.getHeader().getContainer()),
+                            pNode.getPackageId(),
+                            pNode.getBooleanStartIndex());
+                }
+            }
+        } catch (AconfigStorageException e) {
+            // Consider logging the exception.
             throw e;
         } finally {
             StrictMode.setThreadPolicy(oldPolicy);
         }
+        // Package not found.
+        throw new AconfigStorageException(
+                AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
+                "Package " + packageName + " not found.");
+    }
+
+    public static AconfigPackageImpl load(
+            String container, String packageName, StorageFileProvider fileProvider) {
+
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        try {
+            PackageTable.Node pNode = fileProvider.getPackageTable(container).get(packageName);
+            if (pNode != null) {
+                return new AconfigPackageImpl(
+                        fileProvider.getFlagTable(container),
+                        fileProvider.getFlagValueList(container),
+                        pNode.getPackageId(),
+                        pNode.getBooleanStartIndex());
+            }
+        } catch (AconfigStorageException e) {
+            // Consider logging the exception.
+            throw e;
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+
+        throw new AconfigStorageException(
+                AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
+                "package "
+                        + packageName
+                        + " in container "
+                        + container
+                        + " cannot be found on the device");
+    }
+
+    public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
+        FlagTable.Node fNode = mFlagTable.get(mPackageId, flagName);
+        if (fNode == null) return defaultValue;
+        return mFlagValueList.getBoolean(fNode.getFlagIndex() + mBooleanStartIndex);
+    }
+
+    public boolean getBooleanFlagValue(int index) {
+        return mFlagValueList.getBoolean(index + mBooleanStartIndex);
     }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
index b8e510d..6b8942b 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
@@ -1,10 +1,14 @@
 filegroup {
     name: "read_api_test_storage_files",
     srcs: [
-        "data/v1/package.map",
-        "data/v1/flag.map",
-        "data/v1/flag.val",
-        "data/v1/flag.info",
+        "data/v1/package_v1.map",
+        "data/v1/flag_v1.map",
+        "data/v1/flag_v1.val",
+        "data/v1/flag_v1.info",
+        "data/v2/package_v2.map",
+        "data/v2/flag_v2.map",
+        "data/v2/flag_v2.val",
+        "data/v2/flag_v2.info",
     ],
 }
 
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag.info b/tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag_v1.info
similarity index 100%
rename from tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag.info
rename to tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag_v1.info
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag.map b/tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag_v1.map
similarity index 100%
rename from tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag.map
rename to tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag_v1.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag.val b/tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag_v1.val
similarity index 100%
rename from tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag.val
rename to tools/aconfig/aconfig_storage_read_api/tests/data/v1/flag_v1.val
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v1/package.map b/tools/aconfig/aconfig_storage_read_api/tests/data/v1/package_v1.map
similarity index 100%
rename from tools/aconfig/aconfig_storage_read_api/tests/data/v1/package.map
rename to tools/aconfig/aconfig_storage_read_api/tests/data/v1/package_v1.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.info b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.info
new file mode 100644
index 0000000..9db7fde
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.info
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.map b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.map
new file mode 100644
index 0000000..cf4685c
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.val b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.val
new file mode 100644
index 0000000..37d4750
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/flag_v2.val
Binary files differ
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
new file mode 100644
index 0000000..16f4054
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/data/v2/package_v2.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
index 18f70e8..80c0994 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
@@ -57,13 +57,13 @@
     @Test
     public void testLoad_error() throws Exception {
         AconfigPackageImpl p;
+        // cannot find package
         AconfigStorageException e =
                 assertThrows(
                         AconfigStorageException.class,
                         () ->
                                 AconfigPackageImpl.load(
                                         "mockup", "com.android.aconfig.storage.test_10", pr));
-        // cannot find package
         assertEquals(AconfigStorageException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
         // cannot find package
         e =
@@ -78,14 +78,14 @@
                         () ->
                                 AconfigPackageImpl.load(
                                         null, "com.android.aconfig.storage.test_1", pr));
-        assertEquals(AconfigStorageException.ERROR_CONTAINER_NOT_FOUND, e.getErrorCode());
+        assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
         e =
                 assertThrows(
                         AconfigStorageException.class,
                         () ->
                                 AconfigPackageImpl.load(
                                         "test", "com.android.aconfig.storage.test_1", pr));
-        assertEquals(AconfigStorageException.ERROR_CONTAINER_NOT_FOUND, e.getErrorCode());
+        assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
 
         // new storage doesn't exist
         pr = new StorageFileProvider("fake/path/", "fake/path/");
@@ -93,7 +93,7 @@
                 assertThrows(
                         AconfigStorageException.class,
                         () -> AconfigPackageImpl.load("fake_package", pr));
-        assertEquals(AconfigStorageException.ERROR_STORAGE_SYSTEM_NOT_FOUND, e.getErrorCode());
+        assertEquals(AconfigStorageException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
 
         // file read issue
         pr = new StorageFileProvider(TestDataUtils.TESTDATA_PATH, "fake/path/");
@@ -124,11 +124,4 @@
         assertTrue(p.getBooleanFlagValue(1));
         assertTrue(p.getBooleanFlagValue(2));
     }
-
-    @Test
-    public void testHasPackageFingerprint() throws Exception {
-        AconfigPackageImpl p =
-                AconfigPackageImpl.load("mockup", "com.android.aconfig.storage.test_1", pr);
-        assertFalse(p.hasPackageFingerprint());
-    }
 }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
index 9c88122..0de34a6 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
@@ -28,7 +28,6 @@
     team: "trendy_team_android_core_experiments",
     srcs: [
         "AconfigPackageImplTest.java",
-        "StorageFileProviderTest.java",
         "TestDataUtils.java",
     ],
     static_libs: [
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml
index 3d5bb8e..861b9b5 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml
@@ -21,14 +21,14 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
-        <option name="push" value="package.map->/data/local/tmp/aconfig_storage_package/testdata/mockup.package.map" />
-        <option name="push" value="flag.map->/data/local/tmp/aconfig_storage_package/testdata/mockup.flag.map" />
-        <option name="push" value="flag.val->/data/local/tmp/aconfig_storage_package/testdata/mockup.val" />
-        <option name="push" value="flag.info->/data/local/tmp/aconfig_storage_package/testdata/mockup.info" />
+        <option name="push" value="package_v1.map->/data/local/tmp/aconfig_storage_package/testdata/mockup.package.map" />
+        <option name="push" value="flag_v1.map->/data/local/tmp/aconfig_storage_package/testdata/mockup.flag.map" />
+        <option name="push" value="flag_v1.val->/data/local/tmp/aconfig_storage_package/testdata/mockup.val" />
+        <option name="push" value="flag_v1.info->/data/local/tmp/aconfig_storage_package/testdata/mockup.info" />
         <option name="post-push" value="chmod +r /data/local/tmp/aconfig_storage_package/testdata/" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.aconfig.storage.test" />
         <option name="runtime-hint" value="1m" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
index 99c9e25..7ffa18c 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
@@ -35,11 +35,11 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="abort-on-push-failure" value="true" />
-        <option name="push-file" key="package.map"
+        <option name="push-file" key="package_v1.map"
                 value="/data/local/tmp/aconfig_java_api_test/maps/mockup.package.map" />
-        <option name="push-file" key="flag.map"
+        <option name="push-file" key="flag_v1.map"
                 value="/data/local/tmp/aconfig_java_api_test/maps/mockup.flag.map" />
-        <option name="push-file" key="flag.val"
+        <option name="push-file" key="flag_v1.val"
                 value="/data/local/tmp/aconfig_java_api_test/boot/mockup.val" />
     </target_preparer>
 
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 7537643..5289faa 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
@@ -56,10 +56,10 @@
     flag_map = std::string(maps_dir) + "/mockup.flag.map";
     flag_val = std::string(boot_dir) + "/mockup.val";
     flag_info = std::string(boot_dir) + "/mockup.info";
-    copy_file(test_dir + "/package.map", package_map);
-    copy_file(test_dir + "/flag.map", flag_map);
-    copy_file(test_dir + "/flag.val", flag_val);
-    copy_file(test_dir + "/flag.info", flag_info);
+    copy_file(test_dir + "/package_v1.map", package_map);
+    copy_file(test_dir + "/flag_v1.map", flag_map);
+    copy_file(test_dir + "/flag_v1.val", flag_val);
+    copy_file(test_dir + "/flag_v1.info", flag_info);
   }
 
   void TearDown() override {
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 0d943f8..5605a41 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
@@ -9,7 +9,7 @@
     use rand::Rng;
     use std::fs;
 
-    fn create_test_storage_files() -> String {
+    fn create_test_storage_files(version: u32) -> String {
         let mut rng = rand::thread_rng();
         let number: u32 = rng.gen();
         let storage_dir = String::from("/tmp/") + &number.to_string();
@@ -26,17 +26,17 @@
         let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
         let flag_val = storage_dir.clone() + "/boot/mockup.val";
         let flag_info = storage_dir.clone() + "/boot/mockup.info";
-        fs::copy("./data/v1/package.map", package_map).unwrap();
-        fs::copy("./data/v1/flag.map", flag_map).unwrap();
-        fs::copy("./data/v1/flag.val", flag_val).unwrap();
-        fs::copy("./data/v1/flag.info", flag_info).unwrap();
+        fs::copy(format!("./data/v{0}/package_v{0}.map", version), package_map).unwrap();
+        fs::copy(format!("./data/v{0}/flag_v{0}.map", version), flag_map).unwrap();
+        fs::copy(format!("./data/v{}/flag_v{0}.val", version), flag_val).unwrap();
+        fs::copy(format!("./data/v{}/flag_v{0}.info", version), flag_info).unwrap();
 
         storage_dir
     }
 
     #[test]
-    fn test_unavailable_stoarge() {
-        let storage_dir = create_test_storage_files();
+    fn test_unavailable_storage() {
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let err = unsafe {
@@ -53,7 +53,7 @@
 
     #[test]
     fn test_package_context_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let package_mapped_file = unsafe {
@@ -84,7 +84,7 @@
 
     #[test]
     fn test_none_exist_package_context_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let package_mapped_file = unsafe {
@@ -99,7 +99,7 @@
 
     #[test]
     fn test_flag_context_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_mapped_file =
@@ -125,7 +125,7 @@
 
     #[test]
     fn test_none_exist_flag_context_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_mapped_file =
@@ -141,7 +141,7 @@
 
     #[test]
     fn test_boolean_flag_value_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_value_file =
@@ -155,7 +155,7 @@
 
     #[test]
     fn test_invalid_boolean_flag_value_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_value_file =
@@ -169,7 +169,7 @@
 
     #[test]
     fn test_flag_info_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_info_file =
@@ -186,7 +186,7 @@
 
     #[test]
     fn test_invalid_boolean_flag_info_query() {
-        let storage_dir = create_test_storage_files();
+        let storage_dir = create_test_storage_files(1);
         // SAFETY:
         // The safety here is ensured as the test process will not write to temp storage file
         let flag_info_file =
@@ -199,10 +199,18 @@
     }
 
     #[test]
-    fn test_storage_version_query() {
-        assert_eq!(get_storage_file_version("./data/v1/package.map").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./data/v1/flag.map").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./data/v1/flag.val").unwrap(), 1);
-        assert_eq!(get_storage_file_version("./data/v1/flag.info").unwrap(), 1);
+    fn test_storage_version_query_v1() {
+        assert_eq!(get_storage_file_version("./data/v1/package_v1.map").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./data/v1/flag_v1.map").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./data/v1/flag_v1.val").unwrap(), 1);
+        assert_eq!(get_storage_file_version("./data/v1/flag_v1.info").unwrap(), 1);
+    }
+
+    #[test]
+    fn test_storage_version_query_v2() {
+        assert_eq!(get_storage_file_version("./data/v2/package_v2.map").unwrap(), 2);
+        assert_eq!(get_storage_file_version("./data/v2/flag_v2.map").unwrap(), 2);
+        assert_eq!(get_storage_file_version("./data/v2/flag_v2.val").unwrap(), 2);
+        assert_eq!(get_storage_file_version("./data/v2/flag_v2.info").unwrap(), 2);
     }
 }
diff --git a/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs b/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs
index 5640922..5721105 100644
--- a/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs
+++ b/tools/aconfig/aconfig_storage_write_api/src/flag_info_update.rs
@@ -94,13 +94,13 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::test_utils::create_test_flag_info_list;
+    use aconfig_storage_file::{test_utils::create_test_flag_info_list, DEFAULT_FILE_VERSION};
     use aconfig_storage_read_api::flag_info_query::find_flag_attribute;
 
     #[test]
     // this test point locks down has server override update
     fn test_update_flag_has_server_override() {
-        let flag_info_list = create_test_flag_info_list();
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
         let mut buf = flag_info_list.into_bytes();
         for i in 0..flag_info_list.header.num_flags {
             update_flag_has_server_override(&mut buf, FlagValueType::Boolean, i, true).unwrap();
@@ -115,7 +115,7 @@
     #[test]
     // this test point locks down has local override update
     fn test_update_flag_has_local_override() {
-        let flag_info_list = create_test_flag_info_list();
+        let flag_info_list = create_test_flag_info_list(DEFAULT_FILE_VERSION);
         let mut buf = flag_info_list.into_bytes();
         for i in 0..flag_info_list.header.num_flags {
             update_flag_has_local_override(&mut buf, FlagValueType::Boolean, i, true).unwrap();
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 06a9b15..9772db9 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
@@ -49,12 +49,12 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use aconfig_storage_file::test_utils::create_test_flag_value_list;
+    use aconfig_storage_file::{test_utils::create_test_flag_value_list, DEFAULT_FILE_VERSION};
 
     #[test]
     // this test point locks down flag value update
     fn test_boolean_flag_value_update() {
-        let flag_value_list = create_test_flag_value_list();
+        let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
         let value_offset = flag_value_list.header.boolean_value_offset;
         let mut content = flag_value_list.into_bytes();
         let true_byte = u8::from(true).to_le_bytes()[0];
@@ -72,7 +72,7 @@
     #[test]
     // this test point locks down update beyond the end of boolean section
     fn test_boolean_out_of_range() {
-        let mut flag_value_list = create_test_flag_value_list().into_bytes();
+        let mut flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes();
         let error = update_boolean_flag_value(&mut flag_value_list[..], 8, true).unwrap_err();
         assert_eq!(
             format!("{:?}", error),
@@ -83,7 +83,7 @@
     #[test]
     // this test point locks down query error when file has a higher version
     fn test_higher_version_storage_file() {
-        let mut value_list = create_test_flag_value_list();
+        let mut value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
         value_list.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
         let mut flag_value = value_list.into_bytes();
         let error = update_boolean_flag_value(&mut flag_value[..], 4, true).unwrap_err();
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index 68edf7d..3f593fe 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -93,7 +93,12 @@
         special_fields: SpecialFields::new(),
     };
 
-    let mut socket = UnixStream::connect("/dev/socket/aconfigd")?;
+    let socket_name = if aconfig_flags::auto_generated::enable_system_aconfigd_rust() {
+        "/dev/socket/aconfigd_system"
+    } else {
+        "/dev/socket/aconfigd"
+    };
+    let mut socket = UnixStream::connect(socket_name)?;
 
     let message_buffer = messages.write_to_bytes()?;
     let mut message_length_buffer: [u8; 4] = [0; 4];
diff --git a/tools/edit_monitor/daemon_manager.py b/tools/edit_monitor/daemon_manager.py
index afdefc5..ef2a309 100644
--- a/tools/edit_monitor/daemon_manager.py
+++ b/tools/edit_monitor/daemon_manager.py
@@ -33,7 +33,7 @@
 
 DEFAULT_PROCESS_TERMINATION_TIMEOUT_SECONDS = 5
 DEFAULT_MONITOR_INTERVAL_SECONDS = 5
-DEFAULT_MEMORY_USAGE_THRESHOLD = 2 * 1024  # 2GB
+DEFAULT_MEMORY_USAGE_THRESHOLD = 3 * 1024  # 3GB
 DEFAULT_CPU_USAGE_THRESHOLD = 200
 DEFAULT_REBOOT_TIMEOUT_SECONDS = 60 * 60 * 24
 BLOCK_SIGN_FILE = "edit_monitor_block_sign"
@@ -84,7 +84,7 @@
         "edit_monitor",
         self.user_name,
         "ENABLE_ANDROID_EDIT_MONITOR",
-        10,
+        50,
     ):
       logging.warning("Edit monitor is disabled, exiting...")
       return
@@ -141,17 +141,11 @@
         # Logging the error and continue.
         logging.warning("Failed to monitor daemon process with error: %s", e)
 
-      if (
-          self.max_memory_usage >= memory_threshold
-          or self.max_cpu_usage >= cpu_threshold
-      ):
-        logging.error(
-            "Daemon process is consuming too much resource, killing..."
-        ),
-        self._send_error_event_to_clearcut(
-            edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_RESOURCE_USAGE
-        )
-        self._terminate_process(self.daemon_process.pid)
+      if self.max_memory_usage >= memory_threshold:
+        self._handle_resource_exhausted_error("memory")
+
+      if self.max_cpu_usage >= cpu_threshold:
+        self._handle_resource_exhausted_error("cpu")
 
     logging.info(
         "Daemon process %d terminated. Max memory usage: %f, Max cpu"
@@ -392,6 +386,20 @@
 
     return pids
 
+  def _handle_resource_exhausted_error(self, resource_type:str):
+    if resource_type == "memory":
+      self._send_error_event_to_clearcut(
+          edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE
+      )
+    else:
+      self._send_error_event_to_clearcut(
+          edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_CPU_USAGE
+      )
+    logging.error(
+        "Daemon process is consuming too much %s, killing...", resource_type
+    ),
+    self._terminate_process(self.daemon_process.pid)
+
   def _send_error_event_to_clearcut(self, error_type):
     edit_monitor_error_event_proto = edit_event_pb2.EditEvent(
         user_name=self.user_name,
diff --git a/tools/edit_monitor/daemon_manager_test.py b/tools/edit_monitor/daemon_manager_test.py
index 8d18388..12aaab3 100644
--- a/tools/edit_monitor/daemon_manager_test.py
+++ b/tools/edit_monitor/daemon_manager_test.py
@@ -217,7 +217,7 @@
     self.assert_no_subprocess_running()
     self._assert_error_event_logged(
         fake_cclient,
-        edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_RESOURCE_USAGE,
+        edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE,
     )
 
   def test_monitor_daemon_subprocess_killed_high_cpu_usage(self):
@@ -235,7 +235,7 @@
     self.assert_no_subprocess_running()
     self._assert_error_event_logged(
         fake_cclient,
-        edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_RESOURCE_USAGE,
+        edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_CPU_USAGE,
     )
 
   @mock.patch('subprocess.check_output')
diff --git a/tools/edit_monitor/proto/edit_event.proto b/tools/edit_monitor/proto/edit_event.proto
index dc3d3f6..9acc2e7 100644
--- a/tools/edit_monitor/proto/edit_event.proto
+++ b/tools/edit_monitor/proto/edit_event.proto
@@ -16,8 +16,9 @@
     FAILED_TO_START_EDIT_MONITOR = 1;
     FAILED_TO_STOP_EDIT_MONITOR = 2;
     FAILED_TO_REBOOT_EDIT_MONITOR = 3;
-    KILLED_DUE_TO_EXCEEDED_RESOURCE_USAGE = 4;
+    KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE = 4;
     FORCE_CLEANUP = 5;
+    KILLED_DUE_TO_EXCEEDED_CPU_USAGE = 6;
   }
 
   // Event that logs a single edit
diff --git a/tools/filelistdiff/file_list_diff.py b/tools/filelistdiff/file_list_diff.py
index fbbfedf..a6408e8 100644
--- a/tools/filelistdiff/file_list_diff.py
+++ b/tools/filelistdiff/file_list_diff.py
@@ -76,7 +76,7 @@
     parser.add_argument('kati_installed_file_list')
     parser.add_argument('soong_installed_file_list')
     parser.add_argument('system_module_name')
-    parser.add_argument('--allowlists', nargs='+')
+    parser.add_argument('--allowlists', nargs='*', default=[])
     args = parser.parse_args()
 
     find_unique_items(args.kati_installed_file_list, args.soong_installed_file_list, args.system_module_name, args.allowlists)
\ No newline at end of file
diff --git a/tools/ide_query/prober_scripts/ide_query.out b/tools/ide_query/prober_scripts/ide_query.out
index cd7ce6d..be48da1 100644
--- a/tools/ide_query/prober_scripts/ide_query.out
+++ b/tools/ide_query/prober_scripts/ide_query.out
@@ -1,7 +1,9 @@
 
-out–a
-8build/make/tools/ide_query/prober_scripts/cpp/general.cc8prebuilts/clang/host/linux-x86/clang-r522817/bin/clang++-mthumb-Os-fomit-frame-pointer-mllvm-enable-shrink-wrap=false-O2-Wall-Wextra-Winit-self-Wpointer-arith-Wunguarded-availability-Werror=date-time-Werror=int-conversion-Werror=pragma-pack&-Werror=pragma-pack-suspicious-include-Werror=sizeof-array-div-Werror=string-plus-int'-Werror=unreachable-code-loop-increment"-Wno-error=deprecated-declarations-Wno-c99-designator-Wno-gnu-folding-constant"-Wno-inconsistent-missing-override-Wno-error=reorder-init-list-Wno-reorder-init-list-Wno-sign-compare-Wno-unused	-DANDROID-DNDEBUG-UDEBUG(-D__compiler_offsetof=__builtin_offsetof*-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__	-faddrsig-fdebug-default-version=5-fcolor-diagnostics-ffp-contract=off-fno-exceptions-fno-strict-aliasing-fmessage-length=0#-fno-relaxed-template-template-args-gsimple-template-names-gz=zstd-no-canonical-prefixes-Wno-error=format"-fdebug-prefix-map=/proc/self/cwd=-ftrivial-auto-var-init=zero-g-ffunction-sections-fdata-sections-fno-short-enums-funwind-tables-fstack-protector-strong-Wa,--noexecstack-D_FORTIFY_SOURCE=2-Wstrict-aliasing=2-Werror=return-type-Werror=non-virtual-dtor-Werror=address-Werror=sequence-point-Werror=format-security-nostdlibinc-fdebug-info-for-profiling-msoft-float-march=armv7-a-mfloat-abi=softfp
--mfpu=neon/-Ibuild/make/tools/ide_query/prober_scripts/cpp³-Iout/soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto/build/make/tools/ide_query/prober_scripts/cpp…-Iout/soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto-D__LIBC_API__=10000-D__LIBM_API__=10000-D__LIBDL_API__=10000-Iexternal/protobuf/srcY-Iprebuilts/clang/host/linux-x86/clang-r522817/android_libc++/platform/arm/include/c++/v1=-Iprebuilts/clang/host/linux-x86/clang-r522817/include/c++/v1 -Ibionic/libc/async_safe/include-Isystem/logging/liblog/include'-Ibionic/libc/system_properties/include<-Isystem/core/property_service/libpropertyinfoparser/include-isystembionic/libc/include-isystembionic/libc/kernel/uapi/asm-arm-isystembionic/libc/kernel/uapi-isystembionic/libc/kernel/android/scsi-isystembionic/libc/kernel/android/uapi-targetarmv7a-linux-androideabi10000-DANDROID_STRICT-fPIE-Werror-Wno-unused-parameter-DGOOGLE_PROTOBUF_NO_RTTI-Wimplicit-fallthrough*-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS-Wno-gnu-include-next-fvisibility-inlines-hidden-mllvm-enable-shrink-wrap=false-std=gnu++20	-fno-rtti-Isystem/core/include-Isystem/logging/liblog/include-Isystem/media/audio/include-Ihardware/libhardware/include%-Ihardware/libhardware_legacy/include-Ihardware/ril/include-Iframeworks/native/include"-Iframeworks/native/opengl/include-Iframeworks/av/include-Werror=bool-operation -Werror=format-insufficient-args%-Werror=implicit-int-float-conversion-Werror=int-in-bool-context-Werror=int-to-pointer-cast-Werror=pointer-to-int-cast-Werror=xor-used-as-pow-Wno-void-pointer-to-enum-cast-Wno-void-pointer-to-int-cast-Wno-pointer-to-int-cast-Werror=fortify-source-Wno-unused-variable-Wno-missing-field-initializers-Wno-packed-non-pod-Werror=address-of-temporary+-Werror=incompatible-function-pointer-types-Werror=null-dereference-Werror=return-type"-Wno-tautological-constant-compare$-Wno-tautological-type-limit-compare"-Wno-implicit-int-float-conversion!-Wno-tautological-overlap-compare-Wno-deprecated-copy-Wno-range-loop-construct"-Wno-zero-as-null-pointer-constant)-Wno-deprecated-anon-enum-enum-conversion$-Wno-deprecated-enum-enum-conversion-Wno-pessimizing-move-Wno-non-c-typedef-for-linkage-Wno-align-mismatch"-Wno-error=unused-but-set-variable#-Wno-error=unused-but-set-parameter-Wno-error=deprecated-builtins-Wno-error=deprecated2-Wno-error=single-bit-bitfield-constant-conversion$-Wno-error=enum-constexpr-conversion-Wno-error=invalid-offsetof&-Wno-deprecated-dynamic-exception-spec8build/make/tools/ide_query/prober_scripts/cpp/general.cc"Õ?
+out2x
+8build/make/tools/ide_query/prober_scripts/cpp/general.cc8build/make/tools/ide_query/prober_scripts/cpp/general.cc:—"
+8build/make/tools/ide_query/prober_scripts/cpp/general.cc8build/make/tools/ide_query/prober_scripts/cpp/general.cc"8prebuilts/clang/host/linux-x86/clang-r530567/bin/clang++"-nostdlibinc"-mthumb"-Os"-fomit-frame-pointer"-mllvm"-enable-shrink-wrap=false"-O2"-Wall"-Wextra"-Winit-self"-Wpointer-arith"-Wunguarded-availability"-Werror=date-time"-Werror=int-conversion"-Werror=pragma-pack"&-Werror=pragma-pack-suspicious-include"-Werror=sizeof-array-div"-Werror=string-plus-int"'-Werror=unreachable-code-loop-increment""-Wno-error=deprecated-declarations"-Wno-c23-extensions"-Wno-c99-designator"-Wno-gnu-folding-constant""-Wno-inconsistent-missing-override"-Wno-error=reorder-init-list"-Wno-reorder-init-list"-Wno-sign-compare"-Wno-unused"	-DANDROID"-DNDEBUG"-UDEBUG"(-D__compiler_offsetof=__builtin_offsetof"*-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__"	-faddrsig"-fdebug-default-version=5"-fcolor-diagnostics"-ffp-contract=off"-fno-exceptions"-fno-strict-aliasing"-fmessage-length=0"-gsimple-template-names"-gz=zstd"-no-canonical-prefixes""-fdebug-prefix-map=/proc/self/cwd="-ftrivial-auto-var-init=zero"-g"-ffunction-sections"-fdata-sections"-fno-short-enums"-funwind-tables"-fstack-protector-strong"-Wa,--noexecstack"-D_FORTIFY_SOURCE=2"-Wstrict-aliasing=2"-Werror=return-type"-Werror=non-virtual-dtor"-Werror=address"-Werror=sequence-point"-Werror=format-security"-msoft-float"-march=armv7-a"-mfloat-abi=softfp"
+-mfpu=neon"/-Ibuild/make/tools/ide_query/prober_scripts/cpp"³-Iout/soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto/build/make/tools/ide_query/prober_scripts/cpp"…-Iout/soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto"-D__LIBC_API__=10000"-D__LIBM_API__=10000"-D__LIBDL_API__=10000"-Iexternal/protobuf/src"Y-Iprebuilts/clang/host/linux-x86/clang-r530567/android_libc++/platform/arm/include/c++/v1"=-Iprebuilts/clang/host/linux-x86/clang-r530567/include/c++/v1" -Ibionic/libc/async_safe/include"-Isystem/logging/liblog/include"'-Ibionic/libc/system_properties/include"<-Isystem/core/property_service/libpropertyinfoparser/include"-isystem"bionic/libc/include"-isystem"bionic/libc/kernel/uapi/asm-arm"-isystem"bionic/libc/kernel/uapi"-isystem"bionic/libc/kernel/android/scsi"-isystem"bionic/libc/kernel/android/uapi"-target"armv7a-linux-androideabi10000"-DANDROID_STRICT"-fPIE"-Werror"-Wno-unused-parameter"-DGOOGLE_PROTOBUF_NO_RTTI"-Wimplicit-fallthrough"*-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS"-Wno-gnu-include-next"-fvisibility-inlines-hidden"-mllvm"-enable-shrink-wrap=false"-std=gnu++20"	-fno-rtti"-Isystem/core/include"-Isystem/logging/liblog/include"-Isystem/media/audio/include"-Ihardware/libhardware/include"%-Ihardware/libhardware_legacy/include"-Ihardware/ril/include"-Iframeworks/native/include""-Iframeworks/native/opengl/include"-Iframeworks/av/include"-Werror=bool-operation" -Werror=format-insufficient-args"%-Werror=implicit-int-float-conversion"-Werror=int-in-bool-context"-Werror=int-to-pointer-cast"-Werror=pointer-to-int-cast"-Werror=xor-used-as-pow"-Wno-void-pointer-to-enum-cast"-Wno-void-pointer-to-int-cast"-Wno-pointer-to-int-cast"-Werror=fortify-source"-Wno-unused-variable"-Wno-missing-field-initializers"-Wno-packed-non-pod"-Werror=address-of-temporary"+-Werror=incompatible-function-pointer-types"-Werror=null-dereference"-Werror=return-type""-Wno-tautological-constant-compare"$-Wno-tautological-type-limit-compare""-Wno-implicit-int-float-conversion"!-Wno-tautological-overlap-compare"-Wno-deprecated-copy"-Wno-range-loop-construct""-Wno-zero-as-null-pointer-constant")-Wno-deprecated-anon-enum-enum-conversion"$-Wno-deprecated-enum-enum-conversion"-Wno-error=pessimizing-move"-Wno-non-c-typedef-for-linkage"-Wno-align-mismatch""-Wno-error=unused-but-set-variable"#-Wno-error=unused-but-set-parameter"-Wno-error=deprecated-builtins"-Wno-error=deprecated"&-Wno-deprecated-dynamic-exception-spec"$-Wno-error=enum-constexpr-conversion"-Wno-error=invalid-offsetof")-Wno-error=thread-safety-reference-return"-Wno-vla-cxx-extension"8build/make/tools/ide_query/prober_scripts/cpp/general.cc2Egenfiles_for_build/make/tools/ide_query/prober_scripts/cpp/general.cc:Ÿ@
+Egenfiles_for_build/make/tools/ide_query/prober_scripts/cpp/general.cc*Õ?
 ¶soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto/build/make/tools/ide_query/prober_scripts/cpp/foo.pb.h™>// Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: build/make/tools/ide_query/prober_scripts/cpp/foo.proto
 
diff --git a/tools/ide_query/prober_scripts/regen.sh b/tools/ide_query/prober_scripts/regen.sh
index 2edfe53..04a0264 100755
--- a/tools/ide_query/prober_scripts/regen.sh
+++ b/tools/ide_query/prober_scripts/regen.sh
@@ -21,13 +21,8 @@
 # ide_query.sh. The prober doesn't check-out the full source code, so it
 # can't run ide_query.sh itself.
 
-cd $(dirname $BASH_SOURCE)
-source $(pwd)/../../../shell_utils.sh
-require_top
-
 files_to_build=(
   build/make/tools/ide_query/prober_scripts/cpp/general.cc
 )
 
-cd ${TOP}
 build/make/tools/ide_query/ide_query.sh --lunch_target=aosp_arm-trunk_staging-eng ${files_to_build[@]} > build/make/tools/ide_query/prober_scripts/ide_query.out
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index c25ff27..30a6acc 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -1100,7 +1100,7 @@
     vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(avb_custom_partitions)
 
     vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
-    if vbmeta_system:
+    if vbmeta_system and set(vbmeta_system.split()).intersection(partitions):
       banner("vbmeta_system")
       partitions["vbmeta_system"] = AddVBMeta(
           output_zip, partitions, "vbmeta_system", vbmeta_system.split())
@@ -1110,7 +1110,7 @@
       vbmeta_partitions.append("vbmeta_system")
 
     vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip()
-    if vbmeta_vendor:
+    if vbmeta_vendor and set(vbmeta_vendor.split()).intersection(partitions):
       banner("vbmeta_vendor")
       partitions["vbmeta_vendor"] = AddVBMeta(
           output_zip, partitions, "vbmeta_vendor", vbmeta_vendor.split())
@@ -1137,7 +1137,7 @@
             if item not in included_partitions]
         vbmeta_partitions.append(partition_name)
 
-    if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
+    if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true" and set(vbmeta_partitions).intersection(partitions):
       banner("vbmeta")
       AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)