Merge "Revert "Add a build_datetime_file arg to build_image.py"" into main
diff --git a/backported_fixes/Android.bp b/backported_fixes/Android.bp
index a20f3fc..243e77e 100644
--- a/backported_fixes/Android.bp
+++ b/backported_fixes/Android.bp
@@ -19,19 +19,24 @@
genrule {
name: "applied_backported_fixes",
- tools: ["applied_backported_fixes_main"],
+ tools: ["applied_backported_fixes_property_writer"],
srcs: [":applied_backported_fix_binpbs"],
out: ["applied_backported_fixes.prop"],
- cmd: "$(location applied_backported_fixes_main)" +
+ cmd: "$(location applied_backported_fixes_property_writer)" +
" -p $(location applied_backported_fixes.prop)" +
" $(in)",
}
-java_library {
- name: "backported_fixes_proto",
+filegroup {
+ name: "backported_fixes_proto_file",
srcs: [
"backported_fixes.proto",
],
+}
+
+java_library {
+ name: "backported_fixes_proto",
+ srcs: ["backported_fixes.proto"],
host_supported: true,
}
@@ -63,7 +68,7 @@
}
java_library {
- name: "applied_backported_fixes_lib",
+ name: "backported_fixes_main_lib",
srcs: ["src/java/com/android/build/backportedfixes/*.java"],
static_libs: [
"backported_fixes_common",
@@ -75,18 +80,35 @@
}
java_binary_host {
- name: "applied_backported_fixes_main",
- main_class: "com.android.build.backportedfixes.Main",
+ name: "applied_backported_fixes_property_writer",
+ main_class: "com.android.build.backportedfixes.WriteBackportedFixesPropFile",
static_libs: [
- "applied_backported_fixes_lib",
+ "backported_fixes_main_lib",
],
}
+java_binary_host {
+ name: "backported_fixes_combiner",
+ main_class: "com.android.build.backportedfixes.CombineBackportedFixes",
+ static_libs: [
+ "backported_fixes_main_lib",
+ ],
+}
+
+// Combines BackportedFix binary proto files into a single BackportedFixes binary proto file.
+genrule_defaults {
+ name: "default_backported_fixes_combiner",
+ tools: ["backported_fixes_combiner"],
+ cmd: "$(location backported_fixes_combiner)" +
+ " -o $(out)" +
+ " $(in)",
+}
+
java_test_host {
- name: "applied_backported_fixes_test",
+ name: "backported_fixes_main_lib_test",
srcs: ["tests/java/com/android/build/backportedfixes/*.java"],
static_libs: [
- "applied_backported_fixes_lib",
+ "backported_fixes_main_lib",
"backported_fixes_proto",
"junit",
"truth",
@@ -97,19 +119,25 @@
test_suites: ["general-tests"],
}
+// Converts BackprotedFix text protos to binary protos
+genrule_defaults {
+ name: "default_backported_fix_binpbs",
+ tools: ["aprotoc"],
+ tool_files: [
+ ":backported_fixes_proto_file",
+ ],
+ cmd: "$(location aprotoc) " +
+ " --encode=com.android.build.backportedfixes.BackportedFix" +
+ " $(location :backported_fixes_proto_file)" +
+ " < $(in)" +
+ " > $(out); echo $(out)",
+}
+
gensrcs {
name: "applied_backported_fix_binpbs",
- tools: ["aprotoc"],
+ defaults: ["default_backported_fix_binpbs"],
+ output_extension: "binpb",
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/src/java/com/android/build/backportedfixes/CombineBackportedFixes.java b/backported_fixes/src/java/com/android/build/backportedfixes/CombineBackportedFixes.java
new file mode 100644
index 0000000..0592cc1
--- /dev/null
+++ b/backported_fixes/src/java/com/android/build/backportedfixes/CombineBackportedFixes.java
@@ -0,0 +1,65 @@
+
+/*
+ * 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.android.build.backportedfixes.common.Parser;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.converters.FileConverter;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+
+/** Creates a BackportedFixes binary proto file from a list of BackportedFix proto binary files. */
+public final class CombineBackportedFixes {
+
+ @Parameter(description = "BackportedFix proto binary files",
+ converter = FileConverter.class,
+ required = true)
+ List<File> fixFiles;
+ @Parameter(description = "Write the BackportedFixes proto binary to this file",
+ names = {"--out","-o"},
+ converter = FileConverter.class,
+ required = true)
+ File outFile;
+
+ public static void main(String... argv) throws Exception {
+ CombineBackportedFixes main = new CombineBackportedFixes();
+ JCommander.newBuilder().addObject(main).build().parse(argv);
+ main.run();
+ }
+
+ CombineBackportedFixes() {
+ }
+
+ private void run() throws Exception {
+ try (var out = new FileOutputStream(outFile)) {
+ var fixes = Parser.parseBackportedFixFiles(fixFiles);
+ writeBackportedFixes(fixes, out);
+ }
+ }
+
+ static void writeBackportedFixes(BackportedFixes fixes, OutputStream out)
+ throws IOException {
+ fixes.writeTo(out);
+ }
+}
diff --git a/backported_fixes/src/java/com/android/build/backportedfixes/Main.java b/backported_fixes/src/java/com/android/build/backportedfixes/WriteBackportedFixesPropFile.java
similarity index 74%
rename from backported_fixes/src/java/com/android/build/backportedfixes/Main.java
rename to backported_fixes/src/java/com/android/build/backportedfixes/WriteBackportedFixesPropFile.java
index 79148cc..0ffb4ac 100644
--- a/backported_fixes/src/java/com/android/build/backportedfixes/Main.java
+++ b/backported_fixes/src/java/com/android/build/backportedfixes/WriteBackportedFixesPropFile.java
@@ -18,7 +18,6 @@
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;
@@ -33,27 +32,38 @@
import java.util.List;
import java.util.stream.Collectors;
-public final class Main {
- @Parameter(description = "BackportedFix proto binary files", converter = FileConverter.class,
+
+/**
+ * Creates backported fix properties file.
+ *
+ * <p>Writes BitSet of backported fix aliases from a list of BackportedFix proto binary files and
+ * writes the property {@value PROPERTY_NAME} to a file.
+ */
+public final class WriteBackportedFixesPropFile {
+
+ private static final String PROPERTY_NAME = "ro.build.backported_fixes.alias_bitset.long_list";
+ @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)
+ names = {"--property_file", "-p"},
+ converter = FileConverter.class,
+ required = true)
File propertyFile;
public static void main(String... argv) throws Exception {
- Main main = new Main();
+ WriteBackportedFixesPropFile main = new WriteBackportedFixesPropFile();
JCommander.newBuilder().addObject(main).build().parse(argv);
main.run();
}
- Main() {
+ WriteBackportedFixesPropFile() {
}
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());
+ try (var out = Files.newWriter(propertyFile, UTF_8)) {
+ var fixes = Parser.parseBackportedFixFiles(fixFiles);
writeFixesAsAliasBitSet(fixes, out);
}
}
@@ -70,7 +80,7 @@
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.printf("%s=%s", PROPERTY_NAME, 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
deleted file mode 100644
index 75b6730..0000000
--- a/backported_fixes/src/java/com/android/build/backportedfixes/common/ClosableCollection.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package 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
index 6b08b8f..6180fdc 100644
--- a/backported_fixes/src/java/com/android/build/backportedfixes/common/Parser.java
+++ b/backported_fixes/src/java/com/android/build/backportedfixes/common/Parser.java
@@ -15,9 +15,12 @@
*/
package com.android.build.backportedfixes.common;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.android.build.backportedfixes.BackportedFix;
import com.android.build.backportedfixes.BackportedFixes;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import java.io.File;
@@ -26,7 +29,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.BitSet;
+import java.util.Comparator;
import java.util.List;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
/** Static utilities for working with {@link BackportedFixes}. */
@@ -54,16 +60,79 @@
/**
* 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();
+ public static BackportedFixes parseBackportedFixFiles(List<File> fixFiles)
+ throws IOException {
+ try {
+ return fixFiles.stream().map(Parser::tunelFileInputStream)
+ .map(Parser::tunnelParse)
+ .sorted(Comparator.comparing(BackportedFix::getKnownIssue))
+ .collect(fixCollector());
+
+ } catch (TunnelException e) {
+ throw e.rethrow(FileNotFoundException.class, IOException.class);
}
- return fixes.build();
+ }
+
+
+ private static Collector<BackportedFix, ?, BackportedFixes> fixCollector() {
+ return Collectors.collectingAndThen(Collectors.toList(), fixList -> {
+ var result = BackportedFixes.newBuilder();
+ result.addAllFixes(fixList);
+ return result.build();
+ });
+ }
+
+ private static FileInputStream tunelFileInputStream(File file) throws TunnelException {
+ try {
+ return new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ throw new TunnelException(e);
+ }
+ }
+
+ private static BackportedFix tunnelParse(InputStream s) throws TunnelException {
+ try {
+ var fix = BackportedFix.parseFrom(s);
+ s.close();
+ return fix;
+ } catch (IOException e) {
+ throw new TunnelException(e);
+ }
+ }
+
+ private static class TunnelException extends RuntimeException {
+ TunnelException(Exception cause) {
+ super("If you see this TunnelException something went wrong. It should always be rethrown as the cause.", cause);
+ }
+
+ <X extends Exception> RuntimeException rethrow(Class<X> exceptionClazz) throws X {
+ checkNotNull(exceptionClazz);
+ Throwables.throwIfInstanceOf(getCause(), exceptionClazz);
+ throw exception(
+ getCause(),
+ "rethrow(%s) doesn't match underlying exception", exceptionClazz);
+ }
+
+ public <X1 extends Exception, X2 extends Exception> RuntimeException rethrow(
+ Class<X1> exceptionClazz1, Class<X2> exceptionClazz2) throws X1, X2 {
+ checkNotNull(exceptionClazz1);
+ checkNotNull(exceptionClazz2);
+ Throwables.throwIfInstanceOf(getCause(), exceptionClazz1);
+ Throwables.throwIfInstanceOf(getCause(), exceptionClazz2);
+ throw exception(
+ getCause(),
+ "rethrow(%s, %s) doesn't match underlying exception",
+ exceptionClazz1,
+ exceptionClazz2);
+ }
+
+ private static ClassCastException exception(
+ Throwable cause, String message, Object... formatArgs) {
+ ClassCastException result = new ClassCastException(String.format(message, formatArgs));
+ result.initCause(cause);
+ return result;
+ }
+
}
private Parser() {
diff --git a/backported_fixes/tests/java/com/android/build/backportedfixes/CombineBackportedFixesTest.java b/backported_fixes/tests/java/com/android/build/backportedfixes/CombineBackportedFixesTest.java
new file mode 100644
index 0000000..21d5f1e
--- /dev/null
+++ b/backported_fixes/tests/java/com/android/build/backportedfixes/CombineBackportedFixesTest.java
@@ -0,0 +1,41 @@
+
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.IOException;
+
+/** Tests for {@link CombineBackportedFixes}. */
+public class CombineBackportedFixesTest {
+
+
+ @Test
+ public void writeBackportedFixes_default() throws IOException {
+ // Not much of a test, but there is not much to test.
+ BackportedFixes fixes = BackportedFixes.newBuilder()
+ .addFixes(BackportedFix.newBuilder().setKnownIssue(123).build())
+ .build();
+ var result = new ByteArrayOutputStream();
+ CombineBackportedFixes.writeBackportedFixes(fixes, result);
+ Truth.assertThat(BackportedFixes.parseFrom(result.toByteArray()))
+ .isEqualTo(fixes);
+ }
+}
diff --git a/backported_fixes/tests/java/com/android/build/backportedfixes/MainTest.java b/backported_fixes/tests/java/com/android/build/backportedfixes/WriteBackportedFixesPropFileTest.java
similarity index 87%
rename from backported_fixes/tests/java/com/android/build/backportedfixes/MainTest.java
rename to backported_fixes/tests/java/com/android/build/backportedfixes/WriteBackportedFixesPropFileTest.java
index 84061e1..3209c15 100644
--- a/backported_fixes/tests/java/com/android/build/backportedfixes/MainTest.java
+++ b/backported_fixes/tests/java/com/android/build/backportedfixes/WriteBackportedFixesPropFileTest.java
@@ -23,8 +23,8 @@
import java.io.PrintWriter;
import java.io.StringWriter;
-/** Tests for {@link Main}. */
-public class MainTest {
+/** Tests for {@link WriteBackportedFixesPropFile}. */
+public class WriteBackportedFixesPropFileTest {
@Test
@@ -32,7 +32,7 @@
BackportedFixes fixes = BackportedFixes.newBuilder().build();
var result = new StringWriter();
- Main.writeFixesAsAliasBitSet(fixes, new PrintWriter(result));
+ WriteBackportedFixesPropFile.writeFixesAsAliasBitSet(fixes, new PrintWriter(result));
Truth.assertThat(result.toString())
.isEqualTo("""
@@ -50,7 +50,7 @@
.build();
var result = new StringWriter();
- Main.writeFixesAsAliasBitSet(fixes, new PrintWriter(result));
+ WriteBackportedFixesPropFile.writeFixesAsAliasBitSet(fixes, new PrintWriter(result));
Truth.assertThat(result.toString())
.isEqualTo("""
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
deleted file mode 100644
index d3d84a8..0000000
--- a/backported_fixes/tests/java/com/android/build/backportedfixes/common/CloseableCollectionTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package 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
index 444e694..57a0a40 100644
--- a/backported_fixes/tests/java/com/android/build/backportedfixes/common/ParserTest.java
+++ b/backported_fixes/tests/java/com/android/build/backportedfixes/common/ParserTest.java
@@ -23,15 +23,21 @@
import com.google.common.collect.ImmutableList;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
-import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
/** Tests for {@link Parser}.*/
public class ParserTest {
+ @Rule
+ public TemporaryFolder mTempFolder = new TemporaryFolder();
+
@Test
public void getFileInputStreams() throws IOException {
var results = Parser.getFileInputStreams(
@@ -53,15 +59,15 @@
}
@Test
- public void parseBackportedFixes_empty() throws IOException {
- var result = Parser.parseBackportedFixes(ImmutableList.of());
+ public void parseBackportedFixFiles_empty() throws IOException {
+ var result = Parser.parseBackportedFixFiles(ImmutableList.of());
assertThat(result).isEqualTo(BackportedFixes.getDefaultInstance());
}
+
@Test
- public void parseBackportedFixes_oneBlank() throws IOException {
- var result = Parser.parseBackportedFixes(
- ImmutableList.of(inputStream(BackportedFix.getDefaultInstance())));
+ public void parseBackportedFixFiles_oneBlank() throws IOException {
+ var result = Parser.parseBackportedFixFiles(ImmutableList.of(mTempFolder.newFile()));
assertThat(result).isEqualTo(
BackportedFixes.newBuilder()
@@ -70,7 +76,7 @@
}
@Test
- public void parseBackportedFixes_two() throws IOException {
+ public void parseBackportedFixFiles_two() throws IOException {
BackportedFix ki123 = BackportedFix.newBuilder()
.setKnownIssue(123)
.setAlias(1)
@@ -79,8 +85,8 @@
.setKnownIssue(456)
.setAlias(2)
.build();
- var result = Parser.parseBackportedFixes(
- ImmutableList.of(inputStream(ki123), inputStream(ki456)));
+ var result = Parser.parseBackportedFixFiles(
+ ImmutableList.of(tempFile(ki456), tempFile(ki123)));
assertThat(result).isEqualTo(
BackportedFixes.newBuilder()
.addFixes(ki123)
@@ -88,7 +94,11 @@
.build());
}
- private static ByteArrayInputStream inputStream(BackportedFix f) {
- return new ByteArrayInputStream(f.toByteArray());
+ private File tempFile(BackportedFix fix) throws IOException {
+ File f = mTempFolder.newFile();
+ try (FileOutputStream out = new FileOutputStream(f)) {
+ fix.writeTo(out);
+ return f;
+ }
}
}
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index 443e872..cdcba5a 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -35,7 +35,7 @@
LOG_PATH = 'logs/build_test_suites.log'
# Currently, this prevents the removal of those tags when they exist. In the future we likely
# want the script to supply 'dist directly
-REQUIRED_BUILD_TARGETS = frozenset(['dist', 'droid'])
+REQUIRED_BUILD_TARGETS = frozenset(['dist', 'droid', 'checkbuild'])
class Error(Exception):
@@ -84,43 +84,16 @@
packaging_commands_getters = []
# In order to roll optimizations out differently between test suites and
# device builds, we have separate flags.
- if (
- 'test_suites_zip_test_discovery'
+ enable_discovery = ('test_suites_zip_test_discovery'
in self.build_context.enabled_build_features
and not self.args.device_build
) or (
'device_zip_test_discovery'
in self.build_context.enabled_build_features
and self.args.device_build
- ):
- preliminary_build_targets = self._collect_preliminary_build_targets()
- else:
- preliminary_build_targets = self._legacy_collect_preliminary_build_targets()
-
- # Keep reporting metrics when test discovery is disabled.
- # To be removed once test discovery is fully rolled out.
- optimization_rationale = ''
- test_discovery_zip_regexes = set()
- try:
- 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)
- continue
- try:
- 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_unoptimized_target(target, 'Test artifact used.')
- continue
- get_metrics_agent().report_optimized_target(target)
- except Exception as e:
- logging.error(f'unable to parse test discovery output: {repr(e)}')
- get_metrics_agent().report_unoptimized_target(target, f'Error in parsing test discovery output for {target}: {repr(e)}')
+ )
+ logging.info(f'Discovery mode is enabled= {enable_discovery}')
+ preliminary_build_targets = self._collect_preliminary_build_targets(enable_discovery)
for target in preliminary_build_targets:
target_optimizer_getter = self.target_optimizations.get(target, None)
@@ -138,7 +111,7 @@
return BuildPlan(build_targets, packaging_commands_getters)
- def _collect_preliminary_build_targets(self):
+ def _collect_preliminary_build_targets(self, enable_discovery: bool):
build_targets = set()
try:
test_discovery_zip_regexes = self._get_test_discovery_zip_regexes()
@@ -154,6 +127,11 @@
for target in self.args.extra_targets:
if target in REQUIRED_BUILD_TARGETS:
build_targets.add(target)
+ get_metrics_agent().report_unoptimized_target(target, 'Required build target.')
+ continue
+ # If nothing is discovered without error, that means nothing is needed.
+ if not test_discovery_zip_regexes:
+ get_metrics_agent().report_optimized_target(target)
continue
regex = r'\b(%s.*)\b' % re.escape(target)
@@ -162,13 +140,18 @@
if re.search(regex, opt):
get_metrics_agent().report_unoptimized_target(target, 'Test artifact used.')
build_targets.add(target)
- continue
+ # proceed to next target evaluation
+ break
get_metrics_agent().report_optimized_target(target)
except Exception as e:
# In case of exception report as unoptimized
build_targets.add(target)
get_metrics_agent().report_unoptimized_target(target, f'Error in parsing test discovery output for {target}: {repr(e)}')
logging.error(f'unable to parse test discovery output: {repr(e)}')
+ break
+ # If discovery is not enabled, return the original list
+ if not enable_discovery:
+ return self._legacy_collect_preliminary_build_targets()
return build_targets
diff --git a/core/Makefile b/core/Makefile
index 1180073..a990caf 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -885,11 +885,6 @@
$(call declare-1p-target,$(SOONG_TO_CONVERT),build)
$(call dist-for-goals,droidcore-unbundled,$(SOONG_TO_CONVERT))
-$(PRODUCT_OUT)/product_packages.txt:
- @rm -f $@
- echo "" > $@
- $(foreach x,$(PRODUCT_PACKAGES),echo $(x) >> $@$(newline))
-
MK2BP_CATALOG_SCRIPT := build/make/tools/mk2bp_catalog.py
PRODUCT_PACKAGES_TXT := $(PRODUCT_OUT)/product_packages.txt
MK2BP_REMAINING_HTML := $(PRODUCT_OUT)/mk2bp_remaining.html
@@ -3504,18 +3499,20 @@
# Collect all available stub libraries installed in system and install with predefined linker configuration
# Also append LLNDK libraries in the APEX as required libs
SYSTEM_LINKER_CONFIG := $(TARGET_OUT)/etc/linker.config.pb
-SYSTEM_LINKER_CONFIG_SOURCE := $(call intermediates-dir-for,ETC,system_linker_config)/system_linker_config
+SYSTEM_LINKER_CONFIG_SOURCE := system/core/rootdir/etc/linker.config.json
$(SYSTEM_LINKER_CONFIG): PRIVATE_SYSTEM_LINKER_CONFIG_SOURCE := $(SYSTEM_LINKER_CONFIG_SOURCE)
$(SYSTEM_LINKER_CONFIG): $(INTERNAL_SYSTEMIMAGE_FILES) $(SYSTEM_LINKER_CONFIG_SOURCE) | conv_linker_config
@echo Creating linker config: $@
@mkdir -p $(dir $@)
- @rm -f $@
- $(HOST_OUT_EXECUTABLES)/conv_linker_config systemprovide --source $(PRIVATE_SYSTEM_LINKER_CONFIG_SOURCE) \
+ @rm -f $@ $@.step1
+ $(HOST_OUT_EXECUTABLES)/conv_linker_config proto --force -s $(PRIVATE_SYSTEM_LINKER_CONFIG_SOURCE) -o $@.step1
+ $(HOST_OUT_EXECUTABLES)/conv_linker_config systemprovide --source $@.step1 \
--output $@ --value "$(STUB_LIBRARIES)" --system "$(TARGET_OUT)"
$(HOST_OUT_EXECUTABLES)/conv_linker_config append --source $@ --output $@ --key requireLibs \
--value "$(foreach lib,$(LLNDK_MOVED_TO_APEX_LIBRARIES), $(lib).so)"
$(HOST_OUT_EXECUTABLES)/conv_linker_config append --source $@ --output $@ --key provideLibs \
--value "$(foreach lib,$(PRODUCT_EXTRA_STUB_LIBRARIES), $(lib).so)"
+ rm -f $@.step1
$(call declare-1p-target,$(SYSTEM_LINKER_CONFIG),)
$(call declare-license-deps,$(SYSTEM_LINKER_CONFIG),$(INTERNAL_SYSTEMIMAGE_FILES) $(SYSTEM_LINKER_CONFIG_SOURCE))
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 6040ad3..862fcb2 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -78,9 +78,11 @@
$(call soong_config_set_bool,art_module,art_build_host_debug,$(if $(filter false,$(ART_BUILD_HOST_DEBUG)),false,true))
# For chre
-$(call soong_config_set_bool,chre,chre_daemon_lama_enabled,$(if $(filter true,$(CHRE_DAEMON_LPMA_ENABLED)),true,false))
+$(call soong_config_set_bool,chre,chre_daemon_lpma_enabled,$(if $(filter true,$(CHRE_DAEMON_LPMA_ENABLED)),true,false))
$(call soong_config_set_bool,chre,chre_dedicated_transport_channel_enabled,$(if $(filter true,$(CHRE_DEDICATED_TRANSPORT_CHANNEL_ENABLED)),true,false))
$(call soong_config_set_bool,chre,chre_log_atom_extension_enabled,$(if $(filter true,$(CHRE_LOG_ATOM_EXTENSION_ENABLED)),true,false))
+$(call soong_config_set_bool,chre,building_vendor_image,$(if $(filter true,$(BUILDING_VENDOR_IMAGE)),true,false))
+$(call soong_config_set_bool,chre,chre_usf_daemon_enabled,$(if $(filter true,$(CHRE_USF_DAEMON_ENABLED)),true,false))
ifdef TARGET_BOARD_AUTO
$(call add_soong_config_var_value, ANDROID, target_board_auto, $(TARGET_BOARD_AUTO))
@@ -99,6 +101,9 @@
SYSTEMUI_OPTIMIZE_JAVA ?= true
$(call add_soong_config_var,ANDROID,SYSTEMUI_OPTIMIZE_JAVA)
+# Flag for enabling compose for Launcher.
+$(call soong_config_set,ANDROID,release_enable_compose_in_launcher,$(RELEASE_ENABLE_COMPOSE_IN_LAUNCHER))
+
ifdef PRODUCT_AVF_ENABLED
$(call add_soong_config_var_value,ANDROID,avf_enabled,$(PRODUCT_AVF_ENABLED))
endif
@@ -123,6 +128,8 @@
ifdef PRODUCT_CGROUP_V2_SYS_APP_ISOLATION_ENABLED
$(call add_soong_config_var_value,ANDROID,cgroup_v2_sys_app_isolation,$(PRODUCT_CGROUP_V2_SYS_APP_ISOLATION_ENABLED))
+else
+$(call add_soong_config_var_value,ANDROID,cgroup_v2_sys_app_isolation,true)
endif
$(call add_soong_config_var_value,ANDROID,release_avf_allow_preinstalled_apps,$(RELEASE_AVF_ALLOW_PREINSTALLED_APPS))
@@ -198,6 +205,17 @@
# Required as platform_bootclasspath is using this namespace
$(call soong_config_set,bootclasspath,release_crashrecovery_module,$(RELEASE_CRASHRECOVERY_MODULE))
+# Add uprobestats build flag to soong
+$(call soong_config_set,ANDROID,release_uprobestats_module,$(RELEASE_UPROBESTATS_MODULE))
+# Add uprobestats file move flags to soong, for both platform and module
+ifeq (true,$(RELEASE_UPROBESTATS_FILE_MOVE))
+ $(call soong_config_set,ANDROID,uprobestats_files_in_module,true)
+ $(call soong_config_set,ANDROID,uprobestats_files_in_platform,false)
+else
+ $(call soong_config_set,ANDROID,uprobestats_files_in_module,false)
+ $(call soong_config_set,ANDROID,uprobestats_files_in_platform,true)
+endif
+
# Enable Profiling module. Also used by platform_bootclasspath.
$(call soong_config_set,ANDROID,release_package_profiling_module,$(RELEASE_PACKAGE_PROFILING_MODULE))
$(call soong_config_set,bootclasspath,release_package_profiling_module,$(RELEASE_PACKAGE_PROFILING_MODULE))
diff --git a/core/config.mk b/core/config.mk
index 20ebeeb..454c0e5 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1333,3 +1333,58 @@
$(error SYSTEM_OPTIMIZE_JAVA must be enabled when FULL_SYSTEM_OPTIMIZE_JAVA is enabled)
endif
endif
+
+# -----------------------------------------------------------------
+# Define fingerprint, thumbprint, and version tags for the current build
+#
+# BUILD_VERSION_TAGS is a comma-separated list of tags chosen by the device
+# implementer that further distinguishes the build. It's basically defined
+# by the device implementer. Here, we are adding a mandatory tag that
+# identifies the signing config of the build.
+BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
+ifeq ($(TARGET_BUILD_TYPE),debug)
+ BUILD_VERSION_TAGS += debug
+endif
+# The "test-keys" tag marks builds signed with the old test keys,
+# which are available in the SDK. "dev-keys" marks builds signed with
+# non-default dev keys (usually private keys from a vendor directory).
+# Both of these tags will be removed and replaced with "release-keys"
+# when the target-files is signed in a post-build step.
+ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
+BUILD_KEYS := test-keys
+else
+BUILD_KEYS := dev-keys
+endif
+BUILD_VERSION_TAGS += $(BUILD_KEYS)
+BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
+
+# BUILD_FINGERPRINT is used used to uniquely identify the combined build and
+# product; used by the OTA server.
+ifeq (,$(strip $(BUILD_FINGERPRINT)))
+ BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+endif
+
+BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
+ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE).tmp && (if ! cmp -s $(BUILD_FINGERPRINT_FILE).tmp $(BUILD_FINGERPRINT_FILE); then mv $(BUILD_FINGERPRINT_FILE).tmp $(BUILD_FINGERPRINT_FILE); else rm $(BUILD_FINGERPRINT_FILE).tmp; fi) && grep " " $(BUILD_FINGERPRINT_FILE)))
+ $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))")
+endif
+BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE))
+# unset it for safety.
+BUILD_FINGERPRINT :=
+
+# BUILD_THUMBPRINT is used to uniquely identify the system build; used by the
+# OTA server. This purposefully excludes any product-specific variables.
+ifeq (,$(strip $(BUILD_THUMBPRINT)))
+ BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+endif
+
+BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt
+ifeq ($(strip $(HAS_BUILD_NUMBER)),true)
+$(BUILD_THUMBPRINT_FILE): $(BUILD_NUMBER_FILE)
+endif
+ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE)))
+ $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))")
+endif
+# unset it for safety.
+BUILD_THUMBPRINT_FILE :=
+BUILD_THUMBPRINT :=
diff --git a/core/main.mk b/core/main.mk
index 4b76971..624df49 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -277,7 +277,10 @@
# Include all of the makefiles in the system
#
-subdir_makefiles := $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT)$(COVERAGE_SUFFIX).mk $(SOONG_ANDROID_MK)
+subdir_makefiles := \
+ $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT)$(COVERAGE_SUFFIX).mk \
+ $(SOONG_ANDROID_MK) \
+ build/make/target/board/android-info.mk
# Android.mk files are only used on Linux builds, Mac only supports Android.bp
ifeq ($(HOST_OS),linux)
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index fd9dc9b..a371a00 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -109,10 +109,17 @@
define generate-partition-aconfig-storage-file
$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
$(eval $(strip $(1)): PRIVATE_IN := $(strip $(9)))
+
+ifneq (,$(RELEASE_FINGERPRINT_ACONFIG_PACKAGES))
+STORAGE_FILE_VERSION := 2
+else
+STORAGE_FILE_VERSION := 1
+endif
+
$(strip $(1)): $(ACONFIG) $(strip $(9))
mkdir -p $$(dir $$(PRIVATE_OUT))
$$(if $$(PRIVATE_IN), \
- $$(ACONFIG) create-storage --container $(10) --file package_map --out $$(PRIVATE_OUT) \
+ $$(ACONFIG) create-storage --container $(10) --file package_map --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
$$(addprefix --cache ,$$(PRIVATE_IN)), \
)
touch $$(PRIVATE_OUT)
@@ -121,7 +128,7 @@
$(strip $(2)): $(ACONFIG) $(strip $(9))
mkdir -p $$(dir $$(PRIVATE_OUT))
$$(if $$(PRIVATE_IN), \
- $$(ACONFIG) create-storage --container $(10) --file flag_map --out $$(PRIVATE_OUT) \
+ $$(ACONFIG) create-storage --container $(10) --file flag_map --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
$$(addprefix --cache ,$$(PRIVATE_IN)), \
)
touch $$(PRIVATE_OUT)
@@ -130,7 +137,7 @@
$(strip $(3)): $(ACONFIG) $(strip $(9))
mkdir -p $$(dir $$(PRIVATE_OUT))
$$(if $$(PRIVATE_IN), \
- $$(ACONFIG) create-storage --container $(10) --file flag_val --out $$(PRIVATE_OUT) \
+ $$(ACONFIG) create-storage --container $(10) --file flag_val --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
$$(addprefix --cache ,$$(PRIVATE_IN)), \
)
touch $$(PRIVATE_OUT)
@@ -139,7 +146,7 @@
$(strip $(4)): $(ACONFIG) $(strip $(9))
mkdir -p $$(dir $$(PRIVATE_OUT))
$$(if $$(PRIVATE_IN), \
- $$(ACONFIG) create-storage --container $(10) --file flag_info --out $$(PRIVATE_OUT) \
+ $$(ACONFIG) create-storage --container $(10) --file flag_info --out $$(PRIVATE_OUT) --version $$(STORAGE_FILE_VERSION) \
$$(addprefix --cache ,$$(PRIVATE_IN)), \
)
touch $$(PRIVATE_OUT)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index ace025e..ba59f5e 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -370,6 +370,7 @@
$(firstword $(OVERRIDE_ENABLE_UFFD_GC) $(PRODUCT_ENABLE_UFFD_GC) default)
$(call add_json_str, EnableUffdGc, $(_config_enable_uffd_gc))
_config_enable_uffd_gc :=
+$(call add_json_str, BoardKernelVersion, $(BOARD_KERNEL_VERSION))
$(call add_json_list, DeviceFrameworkCompatibilityMatrixFile, $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE))
$(call add_json_list, DeviceProductCompatibilityMatrixFile, $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE))
@@ -440,6 +441,7 @@
$(call add_json_str, BoardPrebuiltBootimage, $(BOARD_PREBUILT_BOOT_IMAGE))
$(call add_json_str, BoardPrebuiltInitBootimage, $(BOARD_PREBUILT_INIT_BOOT_IMAGE))
$(call add_json_str, BoardBootimagePartitionSize, $(BOARD_BOOTIMAGE_PARTITION_SIZE))
+ $(call add_json_str, BoardVendorBootimagePartitionSize, $(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
$(call add_json_str, BoardInitBootimagePartitionSize, $(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE))
$(call add_json_str, BoardBootHeaderVersion, $(BOARD_BOOT_HEADER_VERSION))
$(call add_json_str, TargetKernelPath, $(TARGET_KERNEL_PATH))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index e5f1267..e4f994f 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -122,11 +122,19 @@
ifneq ($(strip $(7)), true)
$(hide) $$(call generate-common-build-props,$(call to-lower,$(strip $(1))),$$@)
endif
+ # Make and Soong use different intermediate files to build vendor/build.prop.
+ # Although the sysprop contents are same, the absolute paths of android_info.prop are different.
+ # Print the filename for the intermediate files (files in OUT_DIR).
+ # This helps with validating mk->soong migration of android partitions.
$(hide) $(foreach file,$(strip $(3)),\
if [ -f "$(file)" ]; then\
echo "" >> $$@;\
echo "####################################" >> $$@;\
- echo "# from $(file)" >> $$@;\
+ $(if $(filter $(OUT_DIR)/%,$(file)), \
+ echo "# from $(notdir $(file))" >> $$@;\
+ ,\
+ echo "# from $(file)" >> $$@;\
+ )\
echo "####################################" >> $$@;\
cat $(file) >> $$@;\
fi;)
@@ -152,61 +160,6 @@
$(call declare-1p-target,$(2))
endef
-# -----------------------------------------------------------------
-# Define fingerprint, thumbprint, and version tags for the current build
-#
-# BUILD_VERSION_TAGS is a comma-separated list of tags chosen by the device
-# implementer that further distinguishes the build. It's basically defined
-# by the device implementer. Here, we are adding a mandatory tag that
-# identifies the signing config of the build.
-BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS)
-ifeq ($(TARGET_BUILD_TYPE),debug)
- BUILD_VERSION_TAGS += debug
-endif
-# The "test-keys" tag marks builds signed with the old test keys,
-# which are available in the SDK. "dev-keys" marks builds signed with
-# non-default dev keys (usually private keys from a vendor directory).
-# Both of these tags will be removed and replaced with "release-keys"
-# when the target-files is signed in a post-build step.
-ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey)
-BUILD_KEYS := test-keys
-else
-BUILD_KEYS := dev-keys
-endif
-BUILD_VERSION_TAGS += $(BUILD_KEYS)
-BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
-
-# BUILD_FINGERPRINT is used used to uniquely identify the combined build and
-# product; used by the OTA server.
-ifeq (,$(strip $(BUILD_FINGERPRINT)))
- BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
-endif
-
-BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
-ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE).tmp && (if ! cmp -s $(BUILD_FINGERPRINT_FILE).tmp $(BUILD_FINGERPRINT_FILE); then mv $(BUILD_FINGERPRINT_FILE).tmp $(BUILD_FINGERPRINT_FILE); else rm $(BUILD_FINGERPRINT_FILE).tmp; fi) && grep " " $(BUILD_FINGERPRINT_FILE)))
- $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))")
-endif
-BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE))
-# unset it for safety.
-BUILD_FINGERPRINT :=
-
-# BUILD_THUMBPRINT is used to uniquely identify the system build; used by the
-# OTA server. This purposefully excludes any product-specific variables.
-ifeq (,$(strip $(BUILD_THUMBPRINT)))
- BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
-endif
-
-BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt
-ifeq ($(strip $(HAS_BUILD_NUMBER)),true)
-$(BUILD_THUMBPRINT_FILE): $(BUILD_NUMBER_FILE)
-endif
-ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE)))
- $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))")
-endif
-# unset it for safety.
-BUILD_THUMBPRINT_FILE :=
-BUILD_THUMBPRINT :=
-
KNOWN_OEM_THUMBPRINT_PROPERTIES := \
ro.product.brand \
ro.product.name \
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 294cb57..d9f6150 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -97,12 +97,28 @@
coverage_out := $(HOST_OUT)/cts-api-coverage
api_map_out := $(HOST_OUT)/cts-api-map
-cts_jar_files := $(api_map_out)/api_map_files.txt
+cts_jar_files := $(api_map_out)/cts_jar_files.txt
+cts_interactive_jar_files := $(api_map_out)/cts_interactive_jar_files.txt
+cts_all_jar_files := $(api_map_out)/cts_all_jar_files.txt
+
$(cts_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts.API_MAP_FILES))
$(cts_jar_files):
mkdir -p $(dir $@)
echo $(PRIVATE_API_MAP_FILES) > $@
+$(cts_interactive_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts-interactive.API_MAP_FILES))
+$(cts_interactive_jar_files): $(SOONG_ANDROID_CTS_VERIFIER_APP_LIST)
+ mkdir -p $(dir $@)
+ cp $< $@
+ echo $(PRIVATE_API_MAP_FILES) >> $@
+
+$(cts_all_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts.API_MAP_FILES) \
+ $(COMPATIBILITY.cts-interactive.API_MAP_FILES))
+$(cts_all_jar_files): $(SOONG_ANDROID_CTS_VERIFIER_APP_LIST)
+ mkdir -p $(dir $@)
+ cp $< $@
+ echo $(PRIVATE_API_MAP_FILES) >> $@
+
api_xml_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/api.xml
napi_text_description := cts/tools/cts-api-coverage/etc/ndk-api.xml
@@ -124,13 +140,14 @@
cts_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(api_xml_description) $(napi_xml_description)
cts_system_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(system_api_xml_description)
-cts-api-xml-api-map-report := $(api_map_out)/api-map.xml
-cts-api-html-api-map-report := $(api_map_out)/api-map.html
-cts-system-api-xml-api-map-report := $(api_map_out)/system-api-map.xml
-cts-system-api-html-api-map-report := $(api_map_out)/system-api-map.html
+cts-system-api-map-xml-report := $(api_map_out)/cts-system-api-map.xml
+cts-interactive-system-api-map-xml-report := $(api_map_out)/cts-interactive-system-api-map.xml
+cts-combined-system-api-map-xml-report := $(api_map_out)/cts-combined-system-api-map.xml
+cts-combined-system-api-map-html-report := $(api_map_out)/cts-combined-system-api-map.html
cts_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_jar_files)
-cts_api_map_dependencies := $(cts_api_map_exe) $(api_xml_description) $(cts_jar_files)
+cts_interactive_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_interactive_jar_files)
+cts_combined_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_all_jar_files)
android_cts_zip := $(HOST_OUT)/cts/android-cts.zip
cts_verifier_apk := $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk
@@ -210,45 +227,42 @@
.PHONY: cts-coverage-report-all cts-api-coverage
cts-coverage-report-all: cts-test-coverage cts-verifier-coverage cts-combined-coverage cts-combined-xml-coverage
-$(cts-system-api-xml-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-system-api-xml-api-map-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
-$(cts-system-api-xml-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
-$(cts-system-api-xml-api-map-report) : $(android_cts_zip) $(cts_system_api_map_dependencies) | $(ACP)
+$(cts-system-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-system-api-map-xml-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-system-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_jar_files)
+$(cts-system-api-map-xml-report) : $(android_cts_zip) $(cts_system_api_map_dependencies) | $(ACP)
$(call generate-api-map-report-cts,"CTS System API MAP Report - XML",\
$(PRIVATE_JAR_FILES),xml)
-$(cts-system-api-html-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-system-api-html-api-map-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
-$(cts-system-api-html-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
-$(cts-system-api-html-api-map-report) : $(android_cts_zip) $(cts_system_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS System API MAP Report - HTML",\
- $(PRIVATE_JAR_FILES),html)
-
-$(cts-api-xml-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-api-xml-api-map-report): PRIVATE_API_XML_DESC := $(api_xml_description)
-$(cts-api-xml-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
-$(cts-api-xml-api-map-report) : $(android_cts_zip) $(cts_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS API MAP Report - XML",\
+$(cts-interactive-system-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-interactive-system-api-map-xml-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-interactive-system-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_interactive_jar_files)
+$(cts-interactive-system-api-map-xml-report) : $(verifier_zip) $(cts_interactive_system_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS Interactive System API MAP Report - XML",\
$(PRIVATE_JAR_FILES),xml)
-$(cts-api-html-api-map-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-api-html-api-map-report): PRIVATE_API_XML_DESC := $(api_xml_description)
-$(cts-api-html-api-map-report): PRIVATE_JAR_FILES := $(cts_jar_files)
-$(cts-api-html-api-map-report) : $(android_cts_zip) $(cts_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS API MAP Report - HTML",\
+$(cts-combined-system-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-combined-system-api-map-xml-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-combined-system-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
+$(cts-combined-system-api-map-xml-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_system_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS Combined System API MAP Report - XML",\
+ $(PRIVATE_JAR_FILES),xml)
+
+$(cts-combined-system-api-map-html-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-combined-system-api-map-html-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
+$(cts-combined-system-api-map-html-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
+$(cts-combined-system-api-map-html-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_system_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS Combined System API MAP Report - HTML",\
$(PRIVATE_JAR_FILES),html)
-.PHONY: cts-system-api-xml-api-map
-cts-system-api-xml-api-map : $(cts-system-api-xml-api-map-report)
+.PHONY: cts-system-api-map-xml
+cts-system-api-map-xml : $(cts-system-api-map-xml-report)
-.PHONY: cts-system-api-html-api-map
-cts-system-api-html-api-map : $(cts-system-api-html-api-map-report)
+.PHONY: cts-interactive-system-api-map-xml
+cts-interactive-system-api-map-xml: $(cts-interactive-system-api-map-xml-report)
-.PHONY: cts-api-xml-api-map
-cts-api-xml-api-map : $(cts-api-xml-api-map-report)
-
-.PHONY: cts-api-html-api-map
-cts-api-html-api-map : $(cts-api-html-api-map-report)
+.PHONY: cts-combined-system-api-map-xml
+cts-combined-system-api-map-xml : $(cts-combined-system-api-map-xml-report)
.PHONY: cts-api-map-all
@@ -268,15 +282,13 @@
ALL_TARGETS.$(cts-combined-xml-coverage-report).META_LIC:=$(module_license_metadata)
# Put the test api map report in the dist dir if "cts-api-map-all" is among the build goals.
-$(call dist-for-goals, cts-api-map-all, $(cts-system-api-xml-api-map-report):cts-system-api-xml-api-map-report.xml)
-$(call dist-for-goals, cts-api-map-all, $(cts-system-api-html-api-map-report):cts-system-api-html-api-map-report.html)
-$(call dist-for-goals, cts-api-map-all, $(cts-api-xml-api-map-report):cts-api-xml-api-map-report.xml)
-$(call dist-for-goals, cts-api-map-all, $(cts-api-html-api-map-report):cts-api-html-api-map-report.html)
+$(call dist-for-goals, cts-api-map-all, $(cts-combined-system-api-map-xml-report):cts-api-map-report.xml)
+$(call dist-for-goals, cts-api-map-all, $(cts-combined-system-api-map-html-report):cts-api-map-report.html)
-ALL_TARGETS.$(cts-system-api-xml-api-map-report).META_LIC:=$(module_license_metadata)
-ALL_TARGETS.$(cts-system-api-html-api-map-report).META_LIC:=$(module_license_metadata)
-ALL_TARGETS.$(cts-api-xml-api-map-report).META_LIC:=$(module_license_metadata)
-ALL_TARGETS.$(cts-api-html-api-map-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-system-api-map-xml-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-interactive-system-api-map-xml-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-system-api-map-xml-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-system-api-map-html-report).META_LIC:=$(module_license_metadata)
# Arguments;
# 1 - Name of the report printed out on the screen
@@ -301,18 +313,19 @@
# Reset temp vars
cts_api_coverage_dependencies :=
cts_system_api_coverage_dependencies :=
-cts_api_map_dependencies :=
cts_system_api_map_dependencies :=
+cts_interactive_system_api_map_dependencies :=
+cts_combined_system_api_map_dependencies :=
cts-combined-coverage-report :=
cts-combined-xml-coverage-report :=
cts-verifier-coverage-report :=
cts-test-coverage-report :=
cts-system-api-coverage-report :=
cts-system-api-xml-coverage-report :=
-cts-api-xml-api-map-report :=
-cts-api-html-api-map-report :=
-cts-system-api-xml-api-map-report :=
-cts-system-api-html-api-map-report :=
+cts-system-api-map-xml-report :=
+cts-interactive-system-api-map-xml-report :=
+cts-combined-system-api-map-xml-report :=
+cts-combined-system-api-map-html-report :=
api_xml_description :=
api_text_description :=
system_api_xml_description :=
diff --git a/core/tasks/mcts.mk b/core/tasks/mcts.mk
index 09a4191..02e916a 100644
--- a/core/tasks/mcts.mk
+++ b/core/tasks/mcts.mk
@@ -15,7 +15,8 @@
ifneq ($(wildcard test/mts/README.md),)
mcts_test_suites :=
-mcts_test_suites += mcts
+mcts_all_test_suites :=
+mcts_all_test_suites += mcts
$(foreach module, $(mts_modules), $(eval mcts_test_suites += mcts-$(module)))
@@ -29,4 +30,14 @@
$(eval $(call dist-for-goals, $(suite), $(compatibility_zip))) \
)
+$(foreach suite, $(mcts_all_test_suites), \
+ $(eval test_suite_name := $(suite)) \
+ $(eval test_suite_tradefed := mcts-tradefed) \
+ $(eval test_suite_readme := test/mts/README.md) \
+ $(eval include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk) \
+ $(eval .PHONY: $(suite)) \
+ $(eval $(suite): $(compatibility_zip)) \
+ $(eval $(call dist-for-goals, $(suite), $(compatibility_zip))) \
+)
+
endif
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index 9189c2d..f205cea 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -27,7 +27,6 @@
# compatibility_zip: the path to the output zip file.
special_mts_test_suites :=
-special_mts_test_suites += mcts
special_mts_test_suites += $(mts_modules)
ifneq ($(filter $(special_mts_test_suites),$(patsubst mcts-%,%,$(test_suite_name))),)
test_suite_subdir := android-mts
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 67e31df..8a62796 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -69,6 +69,11 @@
BOARD_SUPER_PARTITION_GROUPS := gsi_dynamic_partitions
BOARD_GSI_DYNAMIC_PARTITIONS_PARTITION_LIST := system
BOARD_GSI_DYNAMIC_PARTITIONS_SIZE := 3221225472
+
+# Build pvmfw with GSI: b/376363989
+ifeq (true,$(PRODUCT_BUILD_PVMFW_IMAGE))
+BOARD_PVMFWIMAGE_PARTITION_SIZE := 0x00100000
+endif
endif
# TODO(b/123695868, b/146149698):
diff --git a/target/board/Android.mk b/target/board/android-info.mk
similarity index 100%
rename from target/board/Android.mk
rename to target/board/android-info.mk
diff --git a/target/board/generic_64bitonly_x86_64/device.mk b/target/board/generic_64bitonly_x86_64/device.mk
index bb49057..5edf5e0 100644
--- a/target/board/generic_64bitonly_x86_64/device.mk
+++ b/target/board/generic_64bitonly_x86_64/device.mk
@@ -17,8 +17,3 @@
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
- bios.bin \
- vgabios-cirrus.bin \
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 60f0cc3..27fb310 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -17,8 +17,3 @@
ifdef NET_ETH0_STARTONBOOT
PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
- bios.bin \
- vgabios-cirrus.bin \
diff --git a/target/product/app_function_extensions.mk b/target/product/app_function_extensions.mk
new file mode 100644
index 0000000..a61afdc
--- /dev/null
+++ b/target/product/app_function_extensions.mk
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+# The app function sidecar extensions
+
+# /system_ext packages
+PRODUCT_PACKAGES += \
+ com.google.android.appfunctions.sidecar \
+ appfunctions.sidecar.xml
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 2907e07..b3b58d3 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -178,6 +178,7 @@
libmedia \
libmedia_jni \
libmediandk \
+ libmonkey_jni \
libmtp \
libnetd_client \
libnetlink \
@@ -204,6 +205,7 @@
libstdc++ \
libsysutils \
libui \
+ libuprobestats_client \
libusbhost \
libutils \
libvintf_jni \
@@ -293,7 +295,6 @@
uiautomator \
uinput \
uncrypt \
- uprobestats \
usbd \
vdc \
vintf \
@@ -311,6 +312,17 @@
endif
+# When we release uprobestats module
+ifeq ($(RELEASE_UPROBESTATS_MODULE),true)
+ PRODUCT_PACKAGES += \
+ com.android.uprobestats \
+
+else
+ PRODUCT_PACKAGES += \
+ uprobestats \
+
+endif
+
# These packages are not used on Android TV
ifneq ($(PRODUCT_IS_ATV),true)
PRODUCT_PACKAGES += \
@@ -477,6 +489,7 @@
PRODUCT_SYSTEM_PROPERTIES += debug.atrace.tags.enableflags=0
PRODUCT_SYSTEM_PROPERTIES += persist.traced.enable=1
+PRODUCT_SYSTEM_PROPERTIES += ro.surface_flinger.game_default_frame_rate_override=60
# Include kernel configs.
PRODUCT_PACKAGES += \
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index 07f6472..a1b71ca 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -32,11 +32,6 @@
PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
endif
-# Ensure we package the BIOS files too.
-PRODUCT_HOST_PACKAGES += \
- bios.bin \
- vgabios-cirrus.bin \
-
# Enable dynamic partition size
PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
diff --git a/target/product/fullmte.mk b/target/product/fullmte.mk
index b622496..fed66e7 100644
--- a/target/product/fullmte.mk
+++ b/target/product/fullmte.mk
@@ -20,7 +20,7 @@
# For more details, see:
# https://source.android.com/docs/security/test/memory-safety/arm-mte
ifeq ($(filter memtag_heap,$(SANITIZE_TARGET)),)
- SANITIZE_TARGET := $(strip $(SANITIZE_TARGET) memtag_heap memtag_stack)
+ SANITIZE_TARGET := $(strip $(SANITIZE_TARGET) memtag_heap memtag_stack memtag_globals)
SANITIZE_TARGET_DIAG := $(strip $(SANITIZE_TARGET_DIAG) memtag_heap)
endif
PRODUCT_PRODUCT_PROPERTIES += persist.arm64.memtag.default=sync
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index 66bf694..314816d 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -1,5 +1,4 @@
generic_rootdirs = [
- "acct",
"apex",
"bootstrap-apex",
"config",
@@ -347,6 +346,77 @@
}
android_filesystem_defaults {
+ name: "system_ext_image_defaults",
+ deps: [
+ ///////////////////////////////////////////
+ // 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",
+
+ ///////////////////////////////////////////
+ // base_system
+ ///////////////////////////////////////////
+ "charger",
+ ] + select(release_flag("RELEASE_APPFUNCTION_SIDECAR"), {
+ true: [
+ "com.android.extensions.appfunctions",
+ "appfunctions.extension.xml",
+ ],
+ default: [],
+ }),
+}
+
+android_filesystem_defaults {
+ name: "product_image_defaults",
+ deps: [
+ ///////////////////////////////////////////
+ // 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",
+ ] + select(product_variable("debuggable"), {
+ // Packages included only for eng or userdebug builds, previously debug tagged
+ true: ["adb_keys"],
+ default: [],
+ }),
+}
+
+android_filesystem_defaults {
name: "system_image_defaults",
partition_name: "system",
base_dir: "system",
@@ -471,7 +541,6 @@
"locksettings", // base_system
"logcat", // base_system
"logd", // base_system
- "logpersist.start",
"lpdump", // base_system
"lshal", // base_system
"make_f2fs", // media_system
@@ -528,7 +597,6 @@
"sfdo", // base_system
"sgdisk", // base_system
"sm", // base_system
- "snapshotctl", // base_system
"snapuserd", // base_system
"storaged", // base_system
"surfaceflinger", // base_system
@@ -574,6 +642,7 @@
default: [],
}) + select(product_variable("debuggable"), {
true: [
+ "alloctop",
"adevice_fingerprint",
"arping",
"avbctl",
@@ -586,6 +655,7 @@
"iperf3",
"iw",
"layertracegenerator",
+ "logpersist.start",
"logtagd.rc",
"ot-cli-ftd",
"ot-ctl",
@@ -596,6 +666,7 @@
"sanitizer-status",
"servicedispatcher",
"showmap",
+ "snapshotctl",
"sqlite3",
"ss",
"start_with_lockagent",
@@ -743,6 +814,11 @@
"AvatarPicker", // generic_system (RELEASE_AVATAR_PICKER_APP)
],
default: [],
+ }) + select(release_flag("RELEASE_UPROBESTATS_MODULE"), {
+ true: [
+ "com.android.uprobestats", // base_system (RELEASE_UPROBESTATS_MODULE)
+ ],
+ default: [],
}),
},
prefer32: {
@@ -757,7 +833,12 @@
"android.system.virtualizationservice-ndk",
"libgsi",
"servicemanager",
- ],
+ ] + select(release_flag("RELEASE_UPROBESTATS_MODULE"), {
+ true: [],
+ default: [
+ "uprobestats", // base_system internal
+ ],
+ }),
},
both: {
deps: [
@@ -830,6 +911,7 @@
"libmedia_jni", // base_system
"libmediandk", // base_system
"libminui", // generic_system
+ "libmonkey_jni", // base_system - internal
"libmtp", // base_system
"libnetd_client", // base_system
"libnetlink", // base_system
@@ -873,6 +955,11 @@
}) + select(soong_config_variable("ANDROID", "TARGET_DYNAMIC_64_32_MEDIASERVER"), {
"true": ["mediaserver"],
default: [],
+ }) + select(release_flag("RELEASE_UPROBESTATS_MODULE"), {
+ true: [],
+ default: [
+ "libuprobestats_client", // base_system internal
+ ],
}),
},
},
@@ -896,4 +983,9 @@
compressor: "lz4hc,9",
compress_hints: "erofs_compress_hints.txt",
},
+ deps: [
+ // DO NOT update this list. Instead, update the system_image_defaults to
+ // sync with the base_system.mk
+ "logpersist.start", // cf only
+ ],
}
diff --git a/target/product/gsi/Android.bp b/target/product/gsi/Android.bp
index 9e8946d..c6fc021 100644
--- a/target/product/gsi/Android.bp
+++ b/target/product/gsi/Android.bp
@@ -83,7 +83,11 @@
android_system_image {
name: "android_gsi",
- defaults: ["system_image_defaults"],
+ defaults: [
+ "system_image_defaults",
+ "system_ext_image_defaults",
+ "product_image_defaults",
+ ],
symlinks: gsi_symlinks,
dirs: ["cache"],
deps: [
@@ -107,28 +111,6 @@
"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",
@@ -161,40 +143,7 @@
"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
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index f00c38c..115b355 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -79,6 +79,11 @@
PRODUCT_BUILD_SYSTEM_DLKM_IMAGE := false
PRODUCT_EXPORT_BOOT_IMAGE_TO_DIST := true
+# Build pvmfw with GSI: b/376363989, pvmfw currently only supports AArch64
+ifneq (,$(filter %_arm64,$(TARGET_PRODUCT)))
+PRODUCT_BUILD_PVMFW_IMAGE := true
+endif
+
# Additional settings used in all GSI builds
PRODUCT_PRODUCT_PROPERTIES += \
ro.crypto.metadata_init_delete_all_keys.enabled=false \
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index 546bbe7..2b055c7 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -69,13 +69,19 @@
SharedStorageBackup \
SimAppDialog \
Telecom \
- TelephonyProvider \
TeleService \
Traceur \
UserDictionaryProvider \
VpnDialogs \
vr \
+# Choose the correct products based on HSUM status
+ifeq ($(PRODUCT_USE_HSUM),true)
+ PRODUCT_PACKAGES += TelephonyProviderHsum
+else
+ PRODUCT_PACKAGES += TelephonyProvider
+endif
+
PRODUCT_PACKAGES += $(RELEASE_PACKAGE_VIRTUAL_CAMERA)
# Set virtual_camera_service_enabled soong config variable based on the
# RELEASE_PACKAGE_VIRTUAL_CAMERA build. virtual_camera_service_enabled soong config
diff --git a/target/product/hsum_common.mk b/target/product/hsum_common.mk
new file mode 100644
index 0000000..b19bc65
--- /dev/null
+++ b/target/product/hsum_common.mk
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+# Contains common default elements for devices running in Headless System User Mode.
+
+# Should generally be inherited first as using an HSUM configuration can affect downstream choices
+# (such as ensuring that the HSUM-variants of packages are selected).
+
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ ro.fw.mu.headless_system_user=true
+
+# Variable for elsewhere choosing the appropriate products based on HSUM status.
+PRODUCT_USE_HSUM := true
+
+PRODUCT_PACKAGES += \
+ HsumDefaultConfigOverlay
diff --git a/target/product/media_system_ext.mk b/target/product/media_system_ext.mk
index e79a7eb..1179966 100644
--- a/target/product/media_system_ext.mk
+++ b/target/product/media_system_ext.mk
@@ -22,3 +22,8 @@
# Window Extensions
$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions_base.mk)
+
+# AppFunction Extensions
+ifneq (,$(RELEASE_APPFUNCTION_SIDECAR))
+ $(call inherit-product, $(SRC_TARGET_DIR)/product/app_function_extensions.mk)
+endif
diff --git a/tools/aconfig/aconfig/src/codegen/cpp.rs b/tools/aconfig/aconfig/src/codegen/cpp.rs
index ae18679..d7d77c5 100644
--- a/tools/aconfig/aconfig/src/codegen/cpp.rs
+++ b/tools/aconfig/aconfig/src/codegen/cpp.rs
@@ -24,7 +24,7 @@
use crate::codegen;
use crate::codegen::CodegenMode;
-use crate::commands::OutputFile;
+use crate::commands::{should_include_flag, OutputFile};
pub fn generate_cpp_code<I>(
package: &str,
@@ -127,10 +127,7 @@
flag_ids: HashMap<String, u16>,
rw_count: &mut i32,
) -> ClassElement {
- let no_assigned_offset =
- (pf.container() == "system" || pf.container() == "vendor" || pf.container() == "product")
- && pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::DISABLED;
+ let no_assigned_offset = !should_include_flag(pf);
let flag_offset = match flag_ids.get(pf.name()) {
Some(offset) => offset,
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 0d528d2..81340f2 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -22,7 +22,7 @@
use crate::codegen;
use crate::codegen::CodegenMode;
-use crate::commands::OutputFile;
+use crate::commands::{should_include_flag, OutputFile};
use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
use std::collections::HashMap;
@@ -162,10 +162,7 @@
let device_config_flag = codegen::create_device_config_ident(package, pf.name())
.expect("values checked at flag parse time");
- let no_assigned_offset =
- (pf.container() == "system" || pf.container() == "vendor" || pf.container() == "product")
- && pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::DISABLED;
+ let no_assigned_offset = !should_include_flag(pf);
let flag_offset = match flag_offsets.get(pf.name()) {
Some(offset) => offset,
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index 2bf565a..74da1bc 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -24,7 +24,7 @@
use crate::codegen;
use crate::codegen::CodegenMode;
-use crate::commands::OutputFile;
+use crate::commands::{should_include_flag, OutputFile};
pub fn generate_rust_code<I>(
package: &str,
@@ -88,18 +88,12 @@
impl TemplateParsedFlag {
#[allow(clippy::nonminimal_bool)]
fn new(package: &str, flag_offsets: HashMap<String, u16>, pf: &ProtoParsedFlag) -> Self {
- let no_assigned_offset = (pf.container() == "system"
- || pf.container() == "vendor"
- || pf.container() == "product")
- && pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::DISABLED;
-
let flag_offset = match flag_offsets.get(pf.name()) {
Some(offset) => offset,
None => {
// System/vendor/product RO+disabled flags have no offset in storage files.
// Assign placeholder value.
- if no_assigned_offset {
+ if !should_include_flag(pf) {
&0
}
// All other flags _must_ have an offset.
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 4c06462..2f96015 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -221,13 +221,13 @@
new_exported: bool,
) -> Result<Vec<OutputFile>> {
let parsed_flags = input.try_parse_flags()?;
- let modified_parsed_flags = modify_parsed_flags_based_on_mode(parsed_flags, codegen_mode)?;
+ let modified_parsed_flags =
+ modify_parsed_flags_based_on_mode(parsed_flags.clone(), codegen_mode)?;
let Some(package) = find_unique_package(&modified_parsed_flags) else {
bail!("no parsed flags, or the parsed flags use different packages");
};
let package = package.to_string();
- let mut flag_names =
- modified_parsed_flags.iter().map(|pf| pf.name().to_string()).collect::<Vec<_>>();
+ let mut flag_names = extract_flag_names(parsed_flags)?;
let package_fingerprint = compute_flags_fingerprint(&mut flag_names);
let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
generate_java_code(
@@ -436,14 +436,7 @@
return Err(anyhow::anyhow!("the number of flags in a package cannot exceed 65535"));
}
- // Exclude system/vendor/product flags that are RO+disabled.
- let should_filter_container = pf.container == Some("vendor".to_string())
- || pf.container == Some("system".to_string())
- || pf.container == Some("vendor".to_string());
- if !(should_filter_container
- && pf.state == Some(ProtoFlagState::DISABLED.into())
- && pf.permission == Some(ProtoFlagPermission::READ_ONLY.into()))
- {
+ if should_include_flag(pf) {
flag_ids.insert(pf.name().to_string(), flag_idx as u16);
flag_idx += 1;
}
@@ -451,10 +444,8 @@
Ok(flag_ids)
}
-#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
- // protect hardcoded offset reads.
- // Creates a fingerprint of the flag names (which requires sorting the vector).
- // Fingerprint is used by both codegen and storage files.
+// Creates a fingerprint of the flag names (which requires sorting the vector).
+// Fingerprint is used by both codegen and storage files.
pub fn compute_flags_fingerprint(flag_names: &mut Vec<String>) -> u64 {
flag_names.sort();
@@ -465,11 +456,9 @@
hasher.finish()
}
-#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
- // protect hardcoded offset reads.
- // Converts ProtoParsedFlags into a vector of strings containing all of the flag
- // names. Helper fn for creating fingerprint for codegen files. Flags must all
- // belong to the same package.
+// Converts ProtoParsedFlags into a vector of strings containing all of the flag
+// names. Helper fn for creating fingerprint for codegen files. Flags must all
+// belong to the same package.
fn extract_flag_names(flags: ProtoParsedFlags) -> Result<Vec<String>> {
let separated_flags: Vec<ProtoParsedFlag> = flags.parsed_flag.into_iter().collect::<Vec<_>>();
@@ -478,7 +467,23 @@
bail!("No parsed flags, or the parsed flags use different packages.");
};
- Ok(separated_flags.into_iter().map(|flag| flag.name.unwrap()).collect::<Vec<_>>())
+ Ok(separated_flags
+ .into_iter()
+ .filter(should_include_flag)
+ .map(|flag| flag.name.unwrap())
+ .collect::<Vec<_>>())
+}
+
+// Exclude system/vendor/product flags that are RO+disabled.
+pub fn should_include_flag(pf: &ProtoParsedFlag) -> bool {
+ let should_filter_container = pf.container == Some("vendor".to_string())
+ || pf.container == Some("system".to_string())
+ || pf.container == Some("product".to_string());
+
+ let disabled_ro = pf.state == Some(ProtoFlagState::DISABLED.into())
+ && pf.permission == Some(ProtoFlagPermission::READ_ONLY.into());
+
+ !should_filter_container || !disabled_ro
}
#[cfg(test)]
@@ -489,7 +494,7 @@
#[test]
fn test_offset_fingerprint() {
let parsed_flags = crate::test::parse_test_flags();
- let expected_fingerprint: u64 = 5801144784618221668;
+ let expected_fingerprint: u64 = 11551379960324242360;
let mut extracted_flags = extract_flag_names(parsed_flags).unwrap();
let hash_result = compute_flags_fingerprint(&mut extracted_flags);
@@ -509,6 +514,7 @@
.parsed_flag
.clone()
.into_iter()
+ .filter(should_include_flag)
.map(|flag| flag.name.unwrap())
.map(String::from)
.collect::<Vec<_>>();
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index 3b245a7..a3b4e8f 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-use crate::commands::assign_flag_ids;
+use crate::commands::{assign_flag_ids, should_include_flag};
use crate::storage::FlagPackage;
-use aconfig_protos::{ProtoFlagPermission, ProtoFlagState};
+use aconfig_protos::ProtoFlagPermission;
use aconfig_storage_file::{
get_table_size, FlagTable, FlagTableHeader, FlagTableNode, StorageFileType, StoredFlagType,
};
@@ -64,13 +64,7 @@
fn create_nodes(package: &FlagPackage, num_buckets: u32) -> Result<Vec<Self>> {
// Exclude system/vendor/product flags that are RO+disabled.
let mut filtered_package = package.clone();
- filtered_package.boolean_flags.retain(|f| {
- !((f.container == Some("system".to_string())
- || f.container == Some("vendor".to_string())
- || f.container == Some("product".to_string()))
- && f.permission == Some(ProtoFlagPermission::READ_ONLY.into())
- && f.state == Some(ProtoFlagState::DISABLED.into()))
- });
+ filtered_package.boolean_flags.retain(|pf| should_include_flag(pf));
let flag_ids =
assign_flag_ids(package.package_name, filtered_package.boolean_flags.iter().copied())?;
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 8b3d3e1..c390574 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -73,7 +73,7 @@
private static final String TAG = "{package_name}.FeatureFlagsImpl_exported";
private static volatile boolean isCached = false;
{{ for flag in flag_elements }}
- private static boolean {flag.method_name} = {flag.default_value};
+ private static boolean {flag.method_name} = false;
{{ -endfor }}
private void init() \{
try \{
diff --git a/tools/aconfig/aconfig/templates/cpp_source_file.template b/tools/aconfig/aconfig/templates/cpp_source_file.template
index 9be59e0..325dbdc 100644
--- a/tools/aconfig/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/aconfig/templates/cpp_source_file.template
@@ -29,25 +29,103 @@
private:
std::unordered_map<std::string, bool> overrides_;
+ {{ if allow_instrumentation- }}
+ uint32_t boolean_start_index_;
+
+ std::unique_ptr<aconfig_storage::MappedStorageFile> flag_value_file_;
+
+ bool package_exists_in_storage_;
+ {{ -endif }}
+
public:
+ {{ if allow_instrumentation- }}
+ flag_provider()
+ : overrides_()
+ , boolean_start_index_()
+ , flag_value_file_(nullptr)
+ , package_exists_in_storage_(true) \{
+
+ auto package_map_file = aconfig_storage::get_mapped_file(
+ "{container}",
+ aconfig_storage::StorageFileType::package_map);
+
+ if (!package_map_file.ok()) \{
+ ALOGE("error: failed to get package map file: %s", package_map_file.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ auto context = aconfig_storage::get_package_read_context(
+ **package_map_file, "{package}");
+
+ if (!context.ok()) \{
+ ALOGE("error: failed to get package read context: %s", context.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ if (!(context->package_exists)) \{
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ // cache package boolean flag start index
+ boolean_start_index_ = context->boolean_start_index;
+
+ // unmap package map file and free memory
+ delete *package_map_file;
+
+ auto flag_value_file = aconfig_storage::get_mapped_file(
+ "{container}",
+ aconfig_storage::StorageFileType::flag_val);
+ if (!flag_value_file.ok()) \{
+ ALOGE("error: failed to get flag value file: %s", flag_value_file.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ // cache flag value file
+ flag_value_file_ = std::unique_ptr<aconfig_storage::MappedStorageFile>(
+ *flag_value_file);
+
+ }
+ {{ -else }}
flag_provider()
: overrides_()
\{}
+ {{ -endif }}
{{ for item in class_elements }}
virtual bool {item.flag_name}() override \{
auto it = overrides_.find("{item.flag_name}");
- if (it != overrides_.end()) \{
- return it->second;
+ if (it != overrides_.end()) \{
+ return it->second;
} else \{
- {{ if item.readwrite- }}
- return server_configurable_flags::GetServerConfigurableFlag(
+ {{ if item.readwrite- }}
+ {{ if allow_instrumentation- }}
+ if (!package_exists_in_storage_) \{
+ return {item.default_value};
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + {item.flag_offset});
+
+ if (!value.ok()) \{
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return {item.default_value};
+ } else \{
+ return *value;
+ }
+ {{ -else }}
+ return server_configurable_flags::GetServerConfigurableFlag(
"aconfig_flags.{item.device_config_namespace}",
"{item.device_config_flag}",
"{item.default_value}") == "true";
- {{ -else }}
- return {item.default_value};
- {{ -endif }}
+ {{ -endif }}
+ {{ -else }}
+ return {item.default_value};
+ {{ -endif }}
}
}
@@ -66,15 +144,11 @@
class flag_provider : public flag_provider_interface \{
public:
- {{ if allow_instrumentation- }}
{{ if readwrite- }}
+ {{ if allow_instrumentation- }}
flag_provider()
- {{ if readwrite- }}
: cache_({readwrite_count}, -1)
, boolean_start_index_()
- {{ -else- }}
- : boolean_start_index_()
- {{ -endif }}
, flag_value_file_(nullptr)
, package_exists_in_storage_(true) \{
@@ -138,6 +212,7 @@
if (!value.ok()) \{
ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return {item.default_value};
}
cache_[{item.readwrite_idx}] = *value;
diff --git a/tools/aconfig/aconfig_device_paths/Android.bp b/tools/aconfig/aconfig_device_paths/Android.bp
index bdf96ed..c75a12a 100644
--- a/tools/aconfig/aconfig_device_paths/Android.bp
+++ b/tools/aconfig/aconfig_device_paths/Android.bp
@@ -73,3 +73,23 @@
name: "aconfig_host_device_paths_java",
srcs: [":libaconfig_java_host_device_paths_src"],
}
+
+genrule {
+ name: "java_device_paths_test_util_src",
+ srcs: ["src/DeviceProtosTestUtilTemplate.java"],
+ out: ["DeviceProtosTestUtil.java"],
+ tool_files: ["partition_aconfig_flags_paths.txt"],
+ cmd: "sed -e '/TEMPLATE/{r$(location partition_aconfig_flags_paths.txt)' -e 'd}' $(in) > $(out)",
+}
+
+java_library {
+ name: "aconfig_device_paths_java_util",
+ srcs: [":java_device_paths_test_util_src"],
+ static_libs: [
+ "libaconfig_java_proto_nano",
+ ],
+ sdk_version: "core_platform",
+ apex_available: [
+ "//apex_available:platform",
+ ],
+}
diff --git a/tools/aconfig/aconfig_device_paths/src/DeviceProtosTestUtilTemplate.java b/tools/aconfig/aconfig_device_paths/src/DeviceProtosTestUtilTemplate.java
new file mode 100644
index 0000000..1c5f5f0
--- /dev/null
+++ b/tools/aconfig/aconfig_device_paths/src/DeviceProtosTestUtilTemplate.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.aconfig;
+
+import android.aconfig.nano.Aconfig.parsed_flag;
+import android.aconfig.nano.Aconfig.parsed_flags;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/** @hide */
+public class DeviceProtosTestUtil {
+ public static final String[] PATHS = {
+ TEMPLATE
+ };
+
+ private static final String APEX_DIR = "/apex/";
+ private static final String APEX_ACONFIG_PATH_SUFFIX = "/etc/aconfig_flags.pb";
+ private static final String SYSTEM_APEX_DIR = "/system/apex";
+
+ /**
+ * Returns a list of all on-device aconfig protos.
+ *
+ * <p>May throw an exception if the protos can't be read at the call site. For example, some of
+ * the protos are in the apex/ partition, which is mounted somewhat late in the boot process.
+ *
+ * @throws IOException if we can't read one of the protos yet
+ * @return a list of all on-device aconfig protos
+ */
+ public static List<parsed_flag> loadAndParseFlagProtos() throws IOException {
+ ArrayList<parsed_flag> result = new ArrayList();
+
+ for (String path : parsedFlagsProtoPaths()) {
+ try (FileInputStream inputStream = new FileInputStream(path)) {
+ parsed_flags parsedFlags = parsed_flags.parseFrom(inputStream.readAllBytes());
+ for (parsed_flag flag : parsedFlags.parsedFlag) {
+ result.add(flag);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the list of all on-device aconfig protos paths.
+ *
+ * @hide
+ */
+ public static List<String> parsedFlagsProtoPaths() {
+ ArrayList<String> paths = new ArrayList(Arrays.asList(PATHS));
+
+ File apexDirectory = new File(SYSTEM_APEX_DIR);
+ if (!apexDirectory.isDirectory()) {
+ return paths;
+ }
+
+ File[] subdirs = apexDirectory.listFiles();
+ if (subdirs == null) {
+ return paths;
+ }
+
+ for (File prefix : subdirs) {
+ // For each mainline modules, there are two directories, one <modulepackage>/,
+ // and one <modulepackage>@<versioncode>/. Just read the former.
+ if (!prefix.getAbsolutePath().endsWith(".apex")) {
+ continue;
+ }
+
+ String apexName = prefix.getName();
+ apexName = apexName.substring(0, apexName.length() - 5);
+
+ File protoPath = new File(APEX_DIR + apexName + APEX_ACONFIG_PATH_SUFFIX);
+ if (!protoPath.exists()) {
+ continue;
+ }
+
+ paths.add(protoPath.getAbsolutePath());
+ }
+ return paths;
+ }
+}
diff --git a/tools/aconfig/aconfig_device_paths/test/Android.bp b/tools/aconfig/aconfig_device_paths/test/Android.bp
new file mode 100644
index 0000000..37f561f
--- /dev/null
+++ b/tools/aconfig/aconfig_device_paths/test/Android.bp
@@ -0,0 +1,35 @@
+// 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 {
+ default_team: "trendy_team_android_core_experiments",
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "aconfig_device_paths_java_test",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.test.runner",
+ "junit",
+ "aconfig_device_paths_java_util",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tools/aconfig/aconfig_device_paths/test/AndroidManifest.xml b/tools/aconfig/aconfig_device_paths/test/AndroidManifest.xml
new file mode 100644
index 0000000..5e01879
--- /dev/null
+++ b/tools/aconfig/aconfig_device_paths/test/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.aconfig.storage.test">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.aconfig.storage.test" />
+
+</manifest>
diff --git a/tools/aconfig/aconfig_device_paths/test/src/DeviceProtosTestUtilTest.java b/tools/aconfig/aconfig_device_paths/test/src/DeviceProtosTestUtilTest.java
new file mode 100644
index 0000000..8829822
--- /dev/null
+++ b/tools/aconfig/aconfig_device_paths/test/src/DeviceProtosTestUtilTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.test;
+
+import static org.junit.Assert.assertTrue;
+
+import android.aconfig.DeviceProtosTestUtil;
+import android.aconfig.nano.Aconfig.parsed_flag;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public class DeviceProtosTestUtilTest {
+
+ private static final Set<String> PLATFORM_CONTAINERS = Set.of("system", "vendor", "product");
+
+ @Test
+ public void testDeviceProtos_loadAndParseFlagProtos() throws Exception {
+ List<parsed_flag> flags = DeviceProtosTestUtil.loadAndParseFlagProtos();
+ int platformFlags = 0;
+ int mainlineFlags = 0;
+ for (parsed_flag pf : flags) {
+ if (PLATFORM_CONTAINERS.contains(pf.container)) {
+ platformFlags++;
+ } else {
+ mainlineFlags++;
+ }
+ }
+
+ assertTrue(platformFlags > 0);
+ assertTrue(mainlineFlags > 0);
+ }
+}
diff --git a/tools/aconfig/aconfig_flags/flags.aconfig b/tools/aconfig/aconfig_flags/flags.aconfig
index 0a004ca..96bb81a 100644
--- a/tools/aconfig/aconfig_flags/flags.aconfig
+++ b/tools/aconfig/aconfig_flags/flags.aconfig
@@ -14,3 +14,20 @@
bug: "369808805"
description: "When enabled, launch aconfigd from config infra module."
}
+
+flag {
+ name: "tools_read_from_new_storage"
+ namespace: "core_experiments_team_internal"
+ bug: "370499640"
+ description: "When enabled, tools read directly from the new aconfig storage."
+}
+
+flag {
+ name: "tools_read_from_new_storage_bugfix"
+ namespace: "core_experiments_team_internal"
+ bug: "370499640"
+ description: "When enabled, tools read directly from the new aconfig storage."
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 6214e2c..16341b9 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -154,19 +154,15 @@
java_library {
name: "aconfig_storage_reader_java",
srcs: [
- "srcs/android/aconfig/storage/StorageInternalReader.java",
- "srcs/android/os/flagging/PlatformAconfigPackageInternal.java",
+ "srcs/android/os/flagging/*.java",
],
libs: [
"unsupportedappusage",
- "strict_mode_stub",
- "aconfig_storage_stub",
],
static_libs: [
"aconfig_storage_file_java",
],
- sdk_version: "core_current",
- host_supported: true,
+ sdk_version: "current",
visibility: [
"//frameworks/base",
"//build/make/tools/aconfig/aconfig_storage_read_api/tests",
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java
deleted file mode 100644
index 6fbcdb3..0000000
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.aconfig.storage;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.StrictMode;
-
-import java.io.Closeable;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-
-/** @hide */
-public class StorageInternalReader {
-
- private static final String MAP_PATH = "/metadata/aconfig/maps/";
- private static final String BOOT_PATH = "/metadata/aconfig/boot/";
-
- private PackageTable mPackageTable;
- private FlagValueList mFlagValueList;
-
- private int mPackageBooleanStartOffset;
-
- @UnsupportedAppUsage
- public StorageInternalReader(String container, String packageName) {
- this(packageName, MAP_PATH + container + ".package.map", BOOT_PATH + container + ".val");
- }
-
- @UnsupportedAppUsage
- public StorageInternalReader(String packageName, String packageMapFile, String flagValueFile) {
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- mPackageTable = PackageTable.fromBytes(mapStorageFile(packageMapFile));
- mFlagValueList = FlagValueList.fromBytes(mapStorageFile(flagValueFile));
- StrictMode.setThreadPolicy(oldPolicy);
- mPackageBooleanStartOffset = getPackageBooleanStartOffset(packageName);
- }
-
- @UnsupportedAppUsage
- public boolean getBooleanFlagValue(int index) {
- index += mPackageBooleanStartOffset;
- return mFlagValueList.getBoolean(index);
- }
-
- private int getPackageBooleanStartOffset(String packageName) {
- PackageTable.Node pNode = mPackageTable.get(packageName);
- if (pNode == null) {
- PackageTable.Header header = mPackageTable.getHeader();
- throw new AconfigStorageException(
- String.format(
- "Fail to get package %s from container %s",
- packageName, header.getContainer()));
- }
- return pNode.getBooleanStartIndex();
- }
-
- // Map a storage file given file path
- private static MappedByteBuffer mapStorageFile(String file) {
- FileChannel channel = null;
- try {
- channel = FileChannel.open(Paths.get(file), StandardOpenOption.READ);
- return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
- } catch (Exception e) {
- throw new AconfigStorageException(
- String.format("Fail to mmap storage file %s", file), e);
- } finally {
- quietlyDispose(channel);
- }
- }
-
- private static void quietlyDispose(Closeable closable) {
- try {
- if (closable != null) {
- closable.close();
- }
- } catch (Exception e) {
- // no need to care, at least as of now
- }
- }
-}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackage.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackage.java
new file mode 100644
index 0000000..5fbe567
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackage.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.flagging;
+
+import android.aconfig.storage.AconfigStorageException;
+import android.aconfig.storage.FlagTable;
+import android.aconfig.storage.FlagValueList;
+import android.aconfig.storage.PackageTable;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An {@code aconfig} package containing the enabled state of its flags.
+ *
+ * <p><strong>Note: this is intended only to be used by generated code. To determine if a given flag
+ * is enabled in app code, the generated android flags should be used.</strong>
+ *
+ * <p>This class is used to read the flag from platform Aconfig Package.Each instance of this class
+ * will cache information related to one package. To read flags from a different package, a new
+ * instance of this class should be {@link #load loaded}.
+ *
+ * @hide
+ */
+public class PlatformAconfigPackage {
+ private static final String TAG = "PlatformAconfigPackage";
+ private static final String MAP_PATH = "/metadata/aconfig/maps/";
+ private static final String BOOT_PATH = "/metadata/aconfig/boot/";
+
+ private static final Map<String, PackageTable> sPackageTableCache = new HashMap<>();
+
+ private FlagTable mFlagTable;
+ private FlagValueList mFlagValueList;
+
+ private int mPackageBooleanStartOffset = -1;
+ private int mPackageId = -1;
+
+ private PlatformAconfigPackage() {}
+
+ /** @hide */
+ @UnsupportedAppUsage
+ public static final Set<String> PLATFORM_PACKAGE_MAP_FILES =
+ Set.of("system.package.map", "vendor.package.map", "product.package.map");
+
+ static {
+ for (String pf : PLATFORM_PACKAGE_MAP_FILES) {
+ try {
+ PackageTable pTable = PackageTable.fromBytes(mapStorageFile(MAP_PATH + pf));
+ for (String packageName : pTable.getPackageList()) {
+ sPackageTableCache.put(packageName, pTable);
+ }
+ } catch (Exception e) {
+ // pass
+ Log.w(TAG, e.toString());
+ }
+ }
+ }
+
+ /**
+ * Loads a platform Aconfig Package from Aconfig Storage.
+ *
+ * <p>This method attempts to load the specified platform Aconfig package.
+ *
+ * @param packageName The name of the Aconfig package to load.
+ * @return An instance of {@link PlatformAconfigPackage}, which may be empty if the package is
+ * not found in the container. Null if the package is not found in platform partitions.
+ * @throws AconfigStorageReadException if there is an error reading from Aconfig Storage, such
+ * as if the storage system is not found, or there is an error reading the storage file. The
+ * specific error code can be got using {@link AconfigStorageReadException#getErrorCode()}.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static PlatformAconfigPackage load(String packageName) {
+ try {
+ PlatformAconfigPackage aconfigPackage = new PlatformAconfigPackage();
+ PackageTable pTable = sPackageTableCache.get(packageName);
+ if (pTable == null) {
+ return null;
+ }
+ PackageTable.Node pNode = pTable.get(packageName);
+ String container = pTable.getHeader().getContainer();
+ aconfigPackage.mFlagTable =
+ FlagTable.fromBytes(mapStorageFile(MAP_PATH + container + ".flag.map"));
+ aconfigPackage.mFlagValueList =
+ FlagValueList.fromBytes(mapStorageFile(BOOT_PATH + container + ".val"));
+ aconfigPackage.mPackageBooleanStartOffset = pNode.getBooleanStartIndex();
+ aconfigPackage.mPackageId = pNode.getPackageId();
+ return aconfigPackage;
+ } catch (AconfigStorageException e) {
+ throw new AconfigStorageReadException(
+ e.getErrorCode(), "Fail to create AconfigPackage", e);
+ } catch (Exception e) {
+ throw new AconfigStorageReadException(
+ AconfigStorageReadException.ERROR_GENERIC,
+ "Fail to create PlatformAconfigPackage",
+ e);
+ }
+ }
+
+ /**
+ * Retrieves the value of a boolean flag.
+ *
+ * <p>This method retrieves the value of the specified flag. If the flag exists within the
+ * loaded Aconfig Package, its value is returned. Otherwise, the provided `defaultValue` is
+ * returned.
+ *
+ * @param flagName The name of the flag (excluding any package name prefix).
+ * @param defaultValue The value to return if the flag is not found.
+ * @return The boolean value of the flag, or `defaultValue` if the flag is not found.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
+ FlagTable.Node fNode = mFlagTable.get(mPackageId, flagName);
+ if (fNode == null) {
+ return defaultValue;
+ }
+ return mFlagValueList.getBoolean(fNode.getFlagIndex() + mPackageBooleanStartOffset);
+ }
+
+ // Map a storage file given file path
+ private static MappedByteBuffer mapStorageFile(String file) {
+ FileChannel channel = null;
+ try {
+ channel = FileChannel.open(Paths.get(file), StandardOpenOption.READ);
+ return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+ } catch (Exception e) {
+ throw new AconfigStorageReadException(
+ AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE,
+ "Fail to mmap storage",
+ e);
+ } finally {
+ quietlyDispose(channel);
+ }
+ }
+
+ private static void quietlyDispose(Closeable closable) {
+ try {
+ if (closable != null) {
+ closable.close();
+ }
+ } catch (Exception e) {
+ // no need to care, at least as of now
+ }
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
index d73d9eb..854e68b 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/os/flagging/PlatformAconfigPackageInternal.java
@@ -84,15 +84,13 @@
try {
pNode = fileProvider.getPackageTable(container).get(packageName);
vList = fileProvider.getFlagValueList(container);
- } catch (AconfigStorageException e) {
- throw new AconfigStorageReadException(e.getErrorCode(), e.toString());
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
if (pNode == null || vList == null) {
- throw new AconfigStorageReadException(
- AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND,
+ throw new AconfigStorageException(
+ AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
String.format(
"package "
+ packageName
@@ -102,8 +100,8 @@
}
if (pNode.hasPackageFingerprint() && packageFingerprint != pNode.getPackageFingerprint()) {
- throw new AconfigStorageReadException(
- 5, // AconfigStorageReadException.ERROR_FILE_FINGERPRINT_MISMATCH,
+ throw new AconfigStorageException(
+ AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
String.format(
"package "
+ packageName
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/AconfigStorageReadAPITest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/AconfigStorageReadAPITest.java
index 6dd1bce..2557048 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/AconfigStorageReadAPITest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/AconfigStorageReadAPITest.java
@@ -26,7 +26,6 @@
import android.aconfig.storage.FlagReadContext.StoredFlagType;
import android.aconfig.storage.PackageReadContext;
import android.aconfig.storage.SipHasher13;
-import android.aconfig.storage.StorageInternalReader;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -225,46 +224,4 @@
assertEquals(rHash, jHash);
}
}
-
- @Test
- public void testRustJavaEqualFlag() throws IOException {
- List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
-
- String mapPath = "/metadata/aconfig/maps/";
- String flagsPath = "/metadata/aconfig/boot/";
-
- for (parsed_flag flag : flags) {
-
- String container = flag.container;
- String packageName = flag.package_;
- String flagName = flag.name;
- String fullFlagName = packageName + "/" + flagName;
-
- MappedByteBuffer packageMap =
- AconfigStorageReadAPI.mapStorageFile(mapPath + container + ".package.map");
- MappedByteBuffer flagMap =
- AconfigStorageReadAPI.mapStorageFile(mapPath + container + ".flag.map");
- MappedByteBuffer flagValList =
- AconfigStorageReadAPI.mapStorageFile(flagsPath + container + ".val");
-
- PackageReadContext packageContext =
- AconfigStorageReadAPI.getPackageReadContext(packageMap, packageName);
-
- FlagReadContext flagContext =
- AconfigStorageReadAPI.getFlagReadContext(
- flagMap, packageContext.mPackageId, flagName);
-
- boolean rVal =
- AconfigStorageReadAPI.getBooleanFlagValue(
- flagValList,
- packageContext.mBooleanStartIndex + flagContext.mFlagIndex);
-
- StorageInternalReader reader = new StorageInternalReader(container, packageName);
- boolean jVal = reader.getBooleanFlagValue(flagContext.mFlagIndex);
-
- long rHash = AconfigStorageReadAPI.hash(packageName);
- long jHash = SipHasher13.hash(packageName.getBytes());
- assertEquals(rVal, jVal);
- }
- }
-}
\ No newline at end of file
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
index 69e224b..e532ff6 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageInternalTest.java
@@ -26,7 +26,7 @@
import android.aconfig.storage.FlagValueList;
import android.aconfig.storage.PackageTable;
import android.aconfig.storage.StorageFileProvider;
-import android.os.flagging.AconfigStorageReadException;
+import android.internal.aconfig.storage.AconfigStorageException;
import android.os.flagging.PlatformAconfigPackageInternal;
import org.junit.Test;
@@ -45,7 +45,7 @@
private static final Set<String> PLATFORM_CONTAINERS = Set.of("system", "vendor", "product");
@Test
- public void testAconfigPackageInternal_load() throws IOException {
+ public void testPlatformAconfigPackageInternal_load() throws IOException {
List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
Map<String, PlatformAconfigPackageInternal> readerMap = new HashMap<>();
StorageFileProvider fp = StorageFileProvider.getDefaultProvider();
@@ -82,22 +82,22 @@
}
@Test
- public void testAconfigPackage_load_withError() throws IOException {
+ public void testPlatformAconfigPackage_load_withError() throws IOException {
// container not found fake_container
- AconfigStorageReadException e =
+ AconfigStorageException e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
"fake_container", "fake_package", 0));
- assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
// package not found
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() -> PlatformAconfigPackageInternal.load("system", "fake_container", 0));
- assertEquals(AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
// fingerprint doesn't match
List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
@@ -116,13 +116,11 @@
long fingerprint = pNode.getPackageFingerprint();
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
container, packageName, fingerprint + 1));
- assertEquals(
- // AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH,
- 5, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_FILE_FINGERPRINT_MISMATCH, e.getErrorCode());
}
}
}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageTest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageTest.java
new file mode 100644
index 0000000..fabc2c9
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/PlatformAconfigPackageTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.aconfig.DeviceProtos;
+import android.aconfig.nano.Aconfig;
+import android.aconfig.nano.Aconfig.parsed_flag;
+import android.aconfig.storage.FlagTable;
+import android.aconfig.storage.FlagValueList;
+import android.aconfig.storage.PackageTable;
+import android.aconfig.storage.StorageFileProvider;
+import android.os.flagging.PlatformAconfigPackage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public class PlatformAconfigPackageTest {
+
+ private static final Set<String> PLATFORM_CONTAINERS = Set.of("system", "vendor", "product");
+
+ @Test
+ public void testPlatformAconfigPackage_load() throws IOException {
+ List<parsed_flag> flags = DeviceProtos.loadAndParseFlagProtos();
+ Map<String, PlatformAconfigPackage> readerMap = new HashMap<>();
+ StorageFileProvider fp = StorageFileProvider.getDefaultProvider();
+
+ for (parsed_flag flag : flags) {
+ if (flag.permission == Aconfig.READ_ONLY && flag.state == Aconfig.DISABLED) {
+ continue;
+ }
+ String container = flag.container;
+ String packageName = flag.package_;
+ String flagName = flag.name;
+ if (!PLATFORM_CONTAINERS.contains(container)) continue;
+
+ PackageTable pTable = fp.getPackageTable(container);
+ PackageTable.Node pNode = pTable.get(packageName);
+ FlagTable fTable = fp.getFlagTable(container);
+ FlagTable.Node fNode = fTable.get(pNode.getPackageId(), flagName);
+ FlagValueList fList = fp.getFlagValueList(container);
+
+ int index = pNode.getBooleanStartIndex() + fNode.getFlagIndex();
+ boolean rVal = fList.getBoolean(index);
+
+ long fingerprint = pNode.getPackageFingerprint();
+
+ PlatformAconfigPackage reader = readerMap.get(packageName);
+ if (reader == null) {
+ reader = PlatformAconfigPackage.load(packageName);
+ readerMap.put(packageName, reader);
+ }
+ boolean jVal = reader.getBooleanFlagValue(flagName, !rVal);
+
+ assertEquals(rVal, jVal);
+ }
+ }
+
+ @Test
+ public void testPlatformAconfigPackage_load_withError() throws IOException {
+ // package not found
+ assertNull(PlatformAconfigPackage.load("fake_container"));
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/StorageInternalReaderTest.java b/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/StorageInternalReaderTest.java
deleted file mode 100644
index 8a8f054..0000000
--- a/tools/aconfig/aconfig_storage_read_api/tests/functional/srcs/StorageInternalReaderTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.aconfig.storage.test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.aconfig.storage.StorageInternalReader;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class StorageInternalReaderTest {
-
- private String mStorageDir = "/data/local/tmp/aconfig_java_api_test";
-
- @Test
- public void testStorageInternalReader_getFlag() {
-
- String packageMapFile = mStorageDir + "/maps/mockup.package.map";
- String flagValueFile = mStorageDir + "/boot/mockup.val";
-
- StorageInternalReader reader =
- new StorageInternalReader(
- "com.android.aconfig.storage.test_1", packageMapFile, flagValueFile);
- assertFalse(reader.getBooleanFlagValue(0));
- assertTrue(reader.getBooleanFlagValue(1));
- }
-}
\ No newline at end of file
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java b/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
index 961f0ea..cac3de2 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/unit/srcs/PlatformAconfigPackageInternalTest.java
@@ -21,9 +21,9 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import android.aconfig.storage.AconfigStorageException;
import android.aconfig.storage.PackageTable;
import android.aconfig.storage.StorageFileProvider;
-import android.os.flagging.AconfigStorageReadException;
import android.os.flagging.PlatformAconfigPackageInternal;
import org.junit.Before;
@@ -62,44 +62,44 @@
PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
long fingerprint = node1.getPackageFingerprint();
// cannot find package
- AconfigStorageReadException e =
+ AconfigStorageException e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
"mockup",
"com.android.aconfig.storage.test_10",
fingerprint,
pr));
- assertEquals(AconfigStorageReadException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
// cannot find container
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
null,
"com.android.aconfig.storage.test_1",
fingerprint,
pr));
- assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
"test",
"com.android.aconfig.storage.test_1",
fingerprint,
pr));
- assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
// fingerprint doesn't match
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
"mockup",
@@ -114,27 +114,27 @@
pr = new StorageFileProvider("fake/path/", "fake/path/");
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
"mockup",
"com.android.aconfig.storage.test_1",
fingerprint,
pr));
- assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
// file read issue
pr = new StorageFileProvider(TESTDATA_PATH, "fake/path/");
e =
assertThrows(
- AconfigStorageReadException.class,
+ AconfigStorageException.class,
() ->
PlatformAconfigPackageInternal.load(
"mockup",
"com.android.aconfig.storage.test_1",
fingerprint,
pr));
- assertEquals(AconfigStorageReadException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
+ assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
}
@Test
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index aef7d7e..766807a 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -17,6 +17,23 @@
pub struct AconfigStorageSource {}
+static ACONFIGD_SYSTEM_SOCKET_NAME: &str = "/dev/socket/aconfigd_system";
+static ACONFIGD_MAINLINE_SOCKET_NAME: &str = "/dev/socket/aconfigd_mainline";
+
+enum AconfigdSocket {
+ System,
+ Mainline,
+}
+
+impl AconfigdSocket {
+ pub fn name(&self) -> &str {
+ match self {
+ AconfigdSocket::System => ACONFIGD_SYSTEM_SOCKET_NAME,
+ AconfigdSocket::Mainline => ACONFIGD_MAINLINE_SOCKET_NAME,
+ }
+ }
+}
+
fn load_flag_to_container() -> Result<HashMap<String, String>> {
Ok(load_protos::load()?.into_iter().map(|p| (p.qualified_name(), p.container)).collect())
}
@@ -81,7 +98,7 @@
})
}
-fn read_from_socket() -> Result<Vec<ProtoFlagQueryReturnMessage>> {
+fn read_from_socket(socket: AconfigdSocket) -> Result<Vec<ProtoFlagQueryReturnMessage>> {
let messages = ProtoStorageRequestMessages {
msgs: vec![ProtoStorageRequestMessage {
msg: Some(ProtoStorageRequestMessageMsg::ListStorageMessage(ProtoListStorageMessage {
@@ -93,8 +110,7 @@
special_fields: SpecialFields::new(),
};
- let socket_name = "/dev/socket/aconfigd_system";
- let mut socket = UnixStream::connect(socket_name)?;
+ let mut socket = UnixStream::connect(socket.name())?;
let message_buffer = messages.write_to_bytes()?;
let mut message_length_buffer: [u8; 4] = [0; 4];
@@ -128,14 +144,20 @@
impl FlagSource for AconfigStorageSource {
fn list_flags() -> Result<Vec<Flag>> {
let containers = load_flag_to_container()?;
- read_from_socket()
- .map(|query_messages| {
- query_messages
- .iter()
- .map(|message| convert(message.clone(), &containers))
- .collect::<Vec<_>>()
- })?
+ let system_messages = read_from_socket(AconfigdSocket::System);
+ let mainline_messages = read_from_socket(AconfigdSocket::Mainline);
+
+ let mut all_messages = vec![];
+ if let Ok(system_messages) = system_messages {
+ all_messages.extend_from_slice(&system_messages);
+ }
+ if let Ok(mainline_messages) = mainline_messages {
+ all_messages.extend_from_slice(&mainline_messages);
+ }
+
+ all_messages
.into_iter()
+ .map(|query_message| convert(query_message.clone(), &containers))
.collect()
}
diff --git a/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigStorageReadException.java b/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigStorageReadException.java
deleted file mode 100644
index bfec98c..0000000
--- a/tools/aconfig/fake_device_config/src/android/os/flagging/AconfigStorageReadException.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.flagging;
-
-public class AconfigStorageReadException extends RuntimeException {
-
- /** Generic error code indicating an unspecified Aconfig Storage error. */
- public static final int ERROR_GENERIC = 0;
-
- /** Error code indicating that the Aconfig Storage system is not found on the device. */
- public static final int ERROR_STORAGE_SYSTEM_NOT_FOUND = 1;
-
- /** Error code indicating that the requested configuration package is not found. */
- public static final int ERROR_PACKAGE_NOT_FOUND = 2;
-
- /** Error code indicating that the specified container is not found. */
- public static final int ERROR_CONTAINER_NOT_FOUND = 3;
-
- /** Error code indicating that there was an error reading the Aconfig Storage file. */
- public static final int ERROR_CANNOT_READ_STORAGE_FILE = 4;
-
- public static final int ERROR_FILE_FINGERPRINT_MISMATCH = 5;
-
- public AconfigStorageReadException(int errorCode, String msg) {
- super(msg);
- throw new UnsupportedOperationException("Stub!");
- }
-
- public AconfigStorageReadException(int errorCode, String msg, Throwable cause) {
- super(msg, cause);
- throw new UnsupportedOperationException("Stub!");
- }
-
- public AconfigStorageReadException(int errorCode, Throwable cause) {
- super(cause);
- throw new UnsupportedOperationException("Stub!");
- }
-
- public int getErrorCode() {
- throw new UnsupportedOperationException("Stub!");
- }
-
- @Override
- public String getMessage() {
- throw new UnsupportedOperationException("Stub!");
- }
-}
diff --git a/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackage.java b/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackage.java
new file mode 100644
index 0000000..ec79f7d
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/os/flagging/PlatformAconfigPackage.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.flagging;
+
+import java.util.Set;
+
+/*
+ * This class allows generated aconfig code to compile independently of the framework.
+ */
+public class PlatformAconfigPackage {
+
+ public static final Set<String> PLATFORM_PACKAGE_MAP_FILES =
+ Set.of("system.package.map", "vendor.package.map", "product.package.map");
+
+ public static PlatformAconfigPackage load(String packageName) {
+ throw new UnsupportedOperationException("Stub!");
+ }
+
+ public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
+ throw new UnsupportedOperationException("Stub!");
+ }
+}
diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py
index 1fd7950..0640041 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -42,8 +42,9 @@
_EM_X86_64 = 62
_EM_AARCH64 = 183
-_KNOWN_MACHINES = {_EM_386, _EM_ARM, _EM_X86_64, _EM_AARCH64}
-
+_32_BIT_MACHINES = {_EM_386, _EM_ARM}
+_64_BIT_MACHINES = {_EM_X86_64, _EM_AARCH64}
+_KNOWN_MACHINES = _32_BIT_MACHINES | _64_BIT_MACHINES
# ELF header struct
_ELF_HEADER_STRUCT = (
@@ -483,6 +484,11 @@
sys.exit(2)
def check_max_page_size(self, max_page_size):
+ if self._file_under_test.header.e_machine in _32_BIT_MACHINES:
+ # Skip test on 32-bit machines. 16 KB pages is an arm64 feature
+ # and no 32-bit systems in Android use it.
+ return
+
for alignment in self._file_under_test.alignments:
if alignment % max_page_size != 0:
self._error(f'Load segment has alignment {alignment} but '
diff --git a/tools/finalization/build-step-0-and-m.sh b/tools/finalization/build-step-0-and-m.sh
new file mode 100755
index 0000000..4843800
--- /dev/null
+++ b/tools/finalization/build-step-0-and-m.sh
@@ -0,0 +1,20 @@
+
+#!/bin/bash
+# Copyright 2024 Google Inc. All rights reserved.
+set -ex
+function help() {
+ echo "Finalize VINTF and build a target for test."
+ echo "usage: $(basename "$0") target [goals...]"
+}
+function finalize_main_step0_and_m() {
+ if [ $# == 0 ] ; then
+ help
+ exit 1
+ fi;
+ local top="$(dirname "$0")"/../../../..
+ source $top/build/make/tools/finalization/build-step-0.sh
+ local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=$1 TARGET_RELEASE=fina_0 TARGET_BUILD_VARIANT=userdebug"
+ # This command tests the release state for AIDL.
+ AIDL_FROZEN_REL=true $m ${@:2}
+}
+finalize_main_step0_and_m $@
diff --git a/tools/finalization/build-step-0.sh b/tools/finalization/build-step-0.sh
index f81b720..8826b35 100755
--- a/tools/finalization/build-step-0.sh
+++ b/tools/finalization/build-step-0.sh
@@ -7,11 +7,26 @@
local top="$(dirname "$0")"/../../../..
source $top/build/make/tools/finalization/environment.sh
+ local need_vintf_finalize=false
if [ "$FINAL_STATE" = "unfinalized" ] ; then
- # VINTF finalization
+ need_vintf_finalize=true
+ else
+ # build-step-0.sh tests the vintf finalization step (step-0) when the
+ # FINAL_BOARD_API_LEVEL is the same as the RELEASE_BOARD_API_LEVEL; and
+ # RELEASE_BOARD_API_LEVEL_FROZEN is not true from the fina_0 configuration.
+ # The FINAL_BOARD_API_LEVEL must be the next vendor API level to be finalized.
+ local board_api_level_vars=$(TARGET_RELEASE=fina_0 $top/build/soong/soong_ui.bash --dumpvars-mode -vars "RELEASE_BOARD_API_LEVEL_FROZEN RELEASE_BOARD_API_LEVEL")
+ local target_board_api_level_vars="RELEASE_BOARD_API_LEVEL_FROZEN=''
+RELEASE_BOARD_API_LEVEL='$FINAL_BOARD_API_LEVEL'"
+ if [ "$board_api_level_vars" = "$target_board_api_level_vars" ] ; then
+ echo The target is a finalization candidate.
+ need_vintf_finalize=true
+ fi;
+ fi;
+
+ if [ "$need_vintf_finalize" = true ] ; then # VINTF finalization
source $top/build/make/tools/finalization/finalize-vintf-resources.sh
fi;
}
finalize_main_step0
-
diff --git a/tools/finalization/command-line-options.sh b/tools/finalization/command-line-options.sh
index d9397c2..3a1e049 100644
--- a/tools/finalization/command-line-options.sh
+++ b/tools/finalization/command-line-options.sh
@@ -3,6 +3,7 @@
while true; do
case "$1" in
--dry-run) repo_upload_dry_run_arg="--dry-run"; repo_branch="finalization-dry-run"; shift ;;
+ --) shift; break;;
*) break
esac
done
diff --git a/tools/finalization/environment.sh b/tools/finalization/environment.sh
index f68a68b..0d3a9e1 100755
--- a/tools/finalization/environment.sh
+++ b/tools/finalization/environment.sh
@@ -29,4 +29,8 @@
# FINAL versions for VINTF
# TODO(b/323985297): The version must match with that from the release configuration.
# Instead of hardcoding the version here, read it from a release configuration.
-export FINAL_BOARD_API_LEVEL='202404'
+export FINAL_BOARD_API_LEVEL='202504'
+export FINAL_CORRESPONDING_VERSION_LETTER='B'
+export FINAL_CORRESPONDING_PLATFORM_VERSION='16'
+export FINAL_NEXT_BOARD_API_LEVEL='202604'
+export FINAL_NEXT_CORRESPONDING_VERSION_LETTER='C'
diff --git a/tools/finalization/finalize-vintf-resources.sh b/tools/finalization/finalize-vintf-resources.sh
index d532b25..6f1a6f6 100755
--- a/tools/finalization/finalize-vintf-resources.sh
+++ b/tools/finalization/finalize-vintf-resources.sh
@@ -33,18 +33,18 @@
function create_new_compat_matrix_and_kernel_configs() {
# The compatibility matrix versions are bumped during vFRC
# These will change every time we have a new vFRC
- local CURRENT_COMPATIBILITY_MATRIX_LEVEL='202404'
- local NEXT_COMPATIBILITY_MATRIX_LEVEL='202504'
+ local CURRENT_COMPATIBILITY_MATRIX_LEVEL="$FINAL_BOARD_API_LEVEL"
+ local NEXT_COMPATIBILITY_MATRIX_LEVEL="$FINAL_NEXT_BOARD_API_LEVEL"
# The kernel configs need the letter of the Android release
- local CURRENT_RELEASE_LETTER='v'
- local NEXT_RELEASE_LETTER='w'
+ local CURRENT_RELEASE_LETTER="$FINAL_CORRESPONDING_VERSION_LETTER"
+ local NEXT_RELEASE_LETTER="$FINAL_NEXT_CORRESPONDING_VERSION_LETTER"
# build the targets required before touching the Android.bp/Android.mk files
local build_cmd="$top/build/soong/soong_ui.bash --make-mode"
$build_cmd bpmodify
- "$top/prebuilts/build-tools/path/linux-x86/python3" "$top/hardware/interfaces/compatibility_matrices/bump.py" "$CURRENT_COMPATIBILITY_MATRIX_LEVEL" "$NEXT_COMPATIBILITY_MATRIX_LEVEL" "$CURRENT_RELEASE_LETTER" "$NEXT_RELEASE_LETTER"
+ "$top/prebuilts/build-tools/path/linux-x86/python3" "$top/hardware/interfaces/compatibility_matrices/bump.py" "$CURRENT_COMPATIBILITY_MATRIX_LEVEL" "$NEXT_COMPATIBILITY_MATRIX_LEVEL" "$CURRENT_RELEASE_LETTER" "$NEXT_RELEASE_LETTER" "$FINAL_CORRESPONDING_PLATFORM_VERSION"
# Freeze the current framework manifest file. This relies on the
# aosp_cf_x86_64-trunk_staging build target to get the right manifest
diff --git a/tools/releasetools/merge_ota.py b/tools/releasetools/merge_ota.py
index fb5957a..e8732a2 100644
--- a/tools/releasetools/merge_ota.py
+++ b/tools/releasetools/merge_ota.py
@@ -226,9 +226,21 @@
logger.setLevel(logging.INFO)
logger.info(args)
+ if args.java_path:
+ common.OPTIONS.java_path = args.java_path
+
if args.search_path:
common.OPTIONS.search_path = args.search_path
+ if args.signapk_path:
+ common.OPTIONS.signapk_path = args.signapk_path
+
+ if args.extra_signapk_args:
+ common.OPTIONS.extra_signapk_args = args.extra_signapk_args
+
+ if args.signapk_shared_library_path:
+ common.OPTIONS.signapk_shared_library_path = args.signapk_shared_library_path
+
metadata_ota = args.packages[-1]
if args.metadata_ota is not None:
metadata_ota = args.metadata_ota
diff --git a/tools/releasetools/ota_signing_utils.py b/tools/releasetools/ota_signing_utils.py
index 60c8c94..9d04c3b 100644
--- a/tools/releasetools/ota_signing_utils.py
+++ b/tools/releasetools/ota_signing_utils.py
@@ -23,10 +23,18 @@
def AddSigningArgumentParse(parser: argparse.ArgumentParser):
+ parser.add_argument('--java_path', type=str,
+ help='Path to JVM if other than default')
parser.add_argument('--package_key', type=str,
help='Paths to private key for signing payload')
parser.add_argument('--search_path', '--path', type=str,
help='Search path for framework/signapk.jar')
+ parser.add_argument('--signapk_path', type=str,
+ help='Path to signapk.jar, relative to search_path')
+ parser.add_argument('--extra_signapk_args', type=ParseSignerArgs,
+ help='Extra arguments for signapk.jar')
+ parser.add_argument('--signapk_shared_library_path', type=str,
+ help='Path to lib64 libraries used by signapk.jar')
parser.add_argument('--payload_signer', type=str,
help='Path to custom payload signer')
parser.add_argument('--payload_signer_args', type=ParseSignerArgs,
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 4ad97e0..2378539 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -862,21 +862,32 @@
# Updates pvmfw embedded public key with the virt APEX payload key.
elif filename == "PREBUILT_IMAGES/pvmfw.img":
- # Find the name of the virt APEX in the target files.
+ # Find the path of the virt APEX in the target files.
namelist = input_tf_zip.namelist()
- apex_gen = (GetApexFilename(f) for f in namelist if IsApexFile(f))
- virt_apex_re = re.compile("^com\.([^\.]+\.)?android\.virt\.apex$")
- virt_apex = next((a for a in apex_gen if virt_apex_re.match(a)), None)
- if not virt_apex:
+ apex_gen = (f for f in namelist if IsApexFile(f))
+ virt_apex_re = re.compile("^.*com\.([^\.]+\.)?android\.virt\.apex$")
+ virt_apex_path = next(
+ (a for a in apex_gen if virt_apex_re.match(a)), None)
+ if not virt_apex_path:
print("Removing %s from ramdisk: virt APEX not found" % filename)
else:
- print("Replacing %s embedded key with %s key" % (filename, virt_apex))
+ print("Replacing %s embedded key with %s key" % (filename,
+ virt_apex_path))
# Get the current and new embedded keys.
+ virt_apex = GetApexFilename(virt_apex_path)
payload_key, container_key, sign_tool = apex_keys[virt_apex]
- new_pubkey_path = common.ExtractAvbPublicKey(
- misc_info['avb_avbtool'], payload_key)
- with open(new_pubkey_path, 'rb') as f:
- new_pubkey = f.read()
+
+ # b/384813199: handles the pre-signed com.android.virt.apex in GSI.
+ if payload_key == 'PRESIGNED':
+ with input_tf_zip.open(virt_apex_path) as apex_fp:
+ with zipfile.ZipFile(apex_fp) as apex_zip:
+ new_pubkey = apex_zip.read('apex_pubkey')
+ else:
+ new_pubkey_path = common.ExtractAvbPublicKey(
+ misc_info['avb_avbtool'], payload_key)
+ with open(new_pubkey_path, 'rb') as f:
+ new_pubkey = f.read()
+
pubkey_info = copy.copy(
input_tf_zip.getinfo("PREBUILT_IMAGES/pvmfw_embedded.avbpubkey"))
old_pubkey = input_tf_zip.read(pubkey_info.filename)