Merge "Report latest RSS for LMKD kills" into main
diff --git a/Android.bp b/Android.bp
index 5211fe2..5c64dba 100644
--- a/Android.bp
+++ b/Android.bp
@@ -413,7 +413,6 @@
"modules-utils-fastxmlserializer",
"modules-utils-preconditions",
"modules-utils-statemachine",
- "modules-utils-synchronous-result-receiver",
"modules-utils-os",
"modules-utils-uieventlogger-interface",
"framework-permission-aidl-java",
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 02e8eec..e680103 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -262,6 +262,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/OsuLogin)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system_other/system/app/OsuLogin)
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/linux-x86/testcases/ravenwood-runtime)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/OWNERS b/OWNERS
index 7ceca32..bde7ab2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -28,7 +28,7 @@
# Support bulk translation updates
per-file */res*/values*/*.xml = byi@google.com, delphij@google.com
-per-file **.bp,**.mk = hansson@google.com, joeo@google.com, lamontjones@google.com
+per-file **.bp,**.mk =joeo@google.com, lamontjones@google.com
per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS
per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS
diff --git a/Ravenwood.bp b/Ravenwood.bp
index f43c37b..912f19d 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -30,7 +30,7 @@
name: "framework-minus-apex.ravenwood-base",
tools: ["hoststubgen"],
cmd: "$(location hoststubgen) " +
- "@$(location ravenwood/ravenwood-standard-options.txt) " +
+ "@$(location :ravenwood-standard-options) " +
"--debug-log $(location hoststubgen_framework-minus-apex.log) " +
"--stats-file $(location hoststubgen_framework-minus-apex_stats.csv) " +
@@ -41,13 +41,13 @@
"--gen-input-dump-file $(location hoststubgen_dump.txt) " +
"--in-jar $(location :framework-minus-apex-for-hoststubgen) " +
- "--policy-override-file $(location ravenwood/framework-minus-apex-ravenwood-policies.txt) " +
- "--annotation-allowed-classes-file $(location ravenwood/ravenwood-annotation-allowed-classes.txt) ",
+ "--policy-override-file $(location :ravenwood-framework-policies) " +
+ "--annotation-allowed-classes-file $(location :ravenwood-annotation-allowed-classes) ",
srcs: [
":framework-minus-apex-for-hoststubgen",
- "ravenwood/framework-minus-apex-ravenwood-policies.txt",
- "ravenwood/ravenwood-standard-options.txt",
- "ravenwood/ravenwood-annotation-allowed-classes.txt",
+ ":ravenwood-framework-policies",
+ ":ravenwood-standard-options",
+ ":ravenwood-annotation-allowed-classes",
],
out: [
"ravenwood.jar",
@@ -91,7 +91,7 @@
name: "services.core.ravenwood-base",
tools: ["hoststubgen"],
cmd: "$(location hoststubgen) " +
- "@$(location ravenwood/ravenwood-standard-options.txt) " +
+ "@$(location :ravenwood-standard-options) " +
"--debug-log $(location hoststubgen_services.core.log) " +
"--stats-file $(location hoststubgen_services.core_stats.csv) " +
@@ -102,13 +102,13 @@
"--gen-input-dump-file $(location hoststubgen_dump.txt) " +
"--in-jar $(location :services.core-for-hoststubgen) " +
- "--policy-override-file $(location ravenwood/services.core-ravenwood-policies.txt) " +
- "--annotation-allowed-classes-file $(location ravenwood/ravenwood-annotation-allowed-classes.txt) ",
+ "--policy-override-file $(location :ravenwood-services-policies) " +
+ "--annotation-allowed-classes-file $(location :ravenwood-annotation-allowed-classes) ",
srcs: [
":services.core-for-hoststubgen",
- "ravenwood/services.core-ravenwood-policies.txt",
- "ravenwood/ravenwood-standard-options.txt",
- "ravenwood/ravenwood-annotation-allowed-classes.txt",
+ ":ravenwood-services-policies",
+ ":ravenwood-standard-options",
+ ":ravenwood-annotation-allowed-classes",
],
out: [
"ravenwood.jar",
@@ -137,6 +137,7 @@
java_library {
name: "services.core.ravenwood-jarjar",
+ defaults: ["ravenwood-internal-only-visibility-java"],
installable: false,
static_libs: [
"services.core.ravenwood",
@@ -144,88 +145,29 @@
jarjar_rules: ":ravenwood-services-jarjar-rules",
}
-java_library {
- name: "services.fakes.ravenwood-jarjar",
- installable: false,
- srcs: [":services.fakes-sources"],
- libs: [
- "ravenwood-framework",
- "services.core.ravenwood",
- ],
- jarjar_rules: ":ravenwood-services-jarjar-rules",
-}
-
-java_library {
- name: "mockito-ravenwood-prebuilt",
- installable: false,
- static_libs: [
- "mockito-robolectric-prebuilt",
- ],
-}
-
-java_library {
- name: "inline-mockito-ravenwood-prebuilt",
- installable: false,
- static_libs: [
- "inline-mockito-robolectric-prebuilt",
- ],
-}
-
// Jars in "ravenwood-runtime" are set to the classpath, sorted alphabetically.
// Rename some of the dependencies to make sure they're included in the intended order.
java_genrule {
name: "100-framework-minus-apex.ravenwood",
+ defaults: ["ravenwood-internal-only-visibility-genrule"],
cmd: "cp $(in) $(out)",
srcs: [":framework-minus-apex.ravenwood"],
out: ["100-framework-minus-apex.ravenwood.jar"],
- visibility: ["//visibility:private"],
}
java_genrule {
// Use 200 to make sure it comes before the mainline stub ("all-updatable...").
name: "200-kxml2-android",
+ defaults: ["ravenwood-internal-only-visibility-genrule"],
cmd: "cp $(in) $(out)",
srcs: [":kxml2-android"],
out: ["200-kxml2-android.jar"],
- visibility: ["//visibility:private"],
}
-android_ravenwood_libgroup {
- name: "ravenwood-runtime",
- libs: [
- "100-framework-minus-apex.ravenwood",
- "200-kxml2-android",
- "all-updatable-modules-system-stubs",
- "android.test.mock.ravenwood",
- "ravenwood-helper-runtime",
- "hoststubgen-helper-runtime.ravenwood",
- "services.core.ravenwood-jarjar",
- "services.fakes.ravenwood-jarjar",
-
- // Provide runtime versions of utils linked in below
- "junit",
- "truth",
- "flag-junit",
- "ravenwood-framework",
- "ravenwood-junit-impl",
- "ravenwood-junit-impl-flag",
- "mockito-ravenwood-prebuilt",
- "inline-mockito-ravenwood-prebuilt",
- ],
- jni_libs: [
- "libandroid_runtime",
- ],
-}
-
-android_ravenwood_libgroup {
- name: "ravenwood-utils",
- libs: [
- "junit",
- "truth",
- "flag-junit",
- "ravenwood-framework",
- "ravenwood-junit",
- "mockito-ravenwood-prebuilt",
- "inline-mockito-ravenwood-prebuilt",
- ],
+java_genrule {
+ name: "z00-all-updatable-modules-system-stubs",
+ defaults: ["ravenwood-internal-only-visibility-genrule"],
+ cmd: "cp $(in) $(out)",
+ srcs: [":all-updatable-modules-system-stubs"],
+ out: ["z00-all-updatable-modules-system-stubs.jar"],
}
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java
index c69ae39..36266de 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java
@@ -23,6 +23,9 @@
import org.conscrypt.TestUtils;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
@@ -91,21 +94,17 @@
}
}
- private Object[] getParams() {
- return new Object[][] {
- new Object[] {new Config(BufferType.ARRAY,
- MyCipherFactory.CONSCRYPT,
- Transformation.AES_CBC_PKCS5)},
- new Object[] {new Config(BufferType.ARRAY,
- MyCipherFactory.CONSCRYPT,
- Transformation.AES_ECB_PKCS5)},
- new Object[] {new Config(BufferType.ARRAY,
- MyCipherFactory.CONSCRYPT,
- Transformation.AES_GCM_NO)},
- new Object[] {new Config(BufferType.ARRAY,
- MyCipherFactory.CONSCRYPT,
- Transformation.AES_GCM_SIV)},
- };
+ public Collection <Object[]> getParams() {
+ final List<Object[]> params = new ArrayList<>();
+ for (BufferType bufferType : BufferType.values()) {
+ for (CipherFactory cipherFactory : MyCipherFactory.values()) {
+ for (Transformation transformation : Transformation.values()) {
+ params.add(new Object[] {new Config(
+ bufferType, cipherFactory, transformation)});
+ }
+ }
+ }
+ return params;
}
private EncryptStrategy encryptStrategy;
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
index dd9f4eb..2643bae 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
@@ -30,6 +30,9 @@
import java.io.OutputStream;
import java.net.SocketException;
import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -104,19 +107,26 @@
}
}
- private Object[] getParams() {
- return new Object[][] {
- new Object[] {new Config(
- EndpointFactory.CONSCRYPT,
- EndpointFactory.CONSCRYPT,
- 64,
- "AES128-GCM",
- ChannelType.CHANNEL,
- PerfTestProtocol.TLSv13)},
- };
+ public Collection getParams() {
+ final List<Object[]> params = new ArrayList<>();
+ for (EndpointFactory endpointFactory : EndpointFactory.values()) {
+ for (ChannelType channelType : ChannelType.values()) {
+ for (PerfTestProtocol protocol : PerfTestProtocol.values()) {
+ params.add(new Object[] {new Config(endpointFactory,
+ endpointFactory, 64, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ channelType, protocol)});
+ params.add(new Object[] {new Config(endpointFactory,
+ endpointFactory, 512, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ channelType, protocol)});
+ params.add(new Object[] {new Config(endpointFactory,
+ endpointFactory, 4096, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ channelType, protocol)});
+ }
+ }
+ }
+ return params;
}
-
private ClientEndpoint client;
private ServerEndpoint server;
private byte[] message;
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineFactory.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineFactory.java
new file mode 100644
index 0000000..8a0d52d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017 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.conscrypt;
+
+import org.conscrypt.TestUtils;
+import java.security.Security;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+
+/**
+ * Factory for {@link SSLEngine} instances.
+ */
+public class EngineFactory {
+ public EngineFactory() {
+ this(newConscryptClientContext(), newConscryptServerContext());
+ }
+
+ private EngineFactory(SSLContext clientContext, SSLContext serverContext) {
+ this.clientContext = clientContext;
+ this.serverContext = serverContext;
+ }
+
+ private final SSLContext clientContext;
+ private final SSLContext serverContext;
+
+ public SSLEngine newClientEngine(String cipher) {
+ SSLEngine engine = initEngine(clientContext.createSSLEngine(), cipher, true);
+ return engine;
+ }
+
+ public SSLEngine newServerEngine(String cipher) {
+ SSLEngine engine = initEngine(serverContext.createSSLEngine(), cipher, false);
+ return engine;
+ }
+
+ public void dispose(SSLEngine engine) {
+ engine.closeOutbound();
+ }
+
+ private static SSLContext newConscryptClientContext() {
+ return TestUtils.newClientSslContext(TestUtils.getConscryptProvider());
+ }
+
+ private static SSLContext newConscryptServerContext() {
+ return TestUtils.newServerSslContext(TestUtils.getConscryptProvider());
+ }
+
+ static SSLEngine initEngine(SSLEngine engine, String cipher, boolean client) {
+ engine.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.3"});
+ engine.setEnabledCipherSuites(new String[] {cipher});
+ engine.setUseClientMode(client);
+ return engine;
+ }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineHandshakePerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineHandshakePerfTest.java
new file mode 100644
index 0000000..cd0ac96
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineHandshakePerfTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2017 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.
+ */
+
+/*
+ * Copyright 2017 The Netty Project
+ *
+ * The Netty Project licenses this file to you 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.conscrypt;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLException;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import androidx.test.filters.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Benchmark comparing handshake performance of various engine implementations to conscrypt.
+ */
+@RunWith(JUnitParamsRunner.class)
+@LargeTest
+public final class EngineHandshakePerfTest {
+ @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ /**
+ * Provider for the test configuration
+ */
+ private class Config {
+ BufferType a_bufferType;
+ String c_cipher;
+ int d_rttMillis;
+ Config(BufferType bufferType,
+ String cipher,
+ int rttMillis) {
+ a_bufferType = bufferType;
+ c_cipher = cipher;
+ d_rttMillis = rttMillis;
+ }
+ public BufferType bufferType() {
+ return a_bufferType;
+ }
+
+ public String cipher() {
+ return c_cipher;
+ }
+
+ public int rttMillis() {
+ return d_rttMillis;
+ }
+ }
+
+ public Collection getParams() {
+ final List<Object[]> params = new ArrayList<>();
+ for (BufferType bufferType : BufferType.values()) {
+ params.add(new Object[] {new Config(bufferType,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 100)});
+ }
+ return params;
+ }
+
+ private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocateDirect(0);
+
+ private EngineFactory engineFactory = new EngineFactory();
+ private String cipher;
+ private int rttMillis;
+
+ private ByteBuffer clientApplicationBuffer;
+ private ByteBuffer clientPacketBuffer;
+ private ByteBuffer serverApplicationBuffer;
+ private ByteBuffer serverPacketBuffer;
+
+ private void setup(Config config) throws Exception {
+ cipher = config.cipher();
+ rttMillis = config.rttMillis();
+ BufferType bufferType = config.bufferType();
+
+ SSLEngine clientEngine = engineFactory.newClientEngine(cipher);
+ SSLEngine serverEngine = engineFactory.newServerEngine(cipher);
+
+ // Create the application and packet buffers for both endpoints.
+ clientApplicationBuffer = bufferType.newApplicationBuffer(clientEngine);
+ serverApplicationBuffer = bufferType.newApplicationBuffer(serverEngine);
+ clientPacketBuffer = bufferType.newPacketBuffer(clientEngine);
+ serverPacketBuffer = bufferType.newPacketBuffer(serverEngine);
+
+ engineFactory.dispose(clientEngine);
+ engineFactory.dispose(serverEngine);
+ }
+
+ @Test
+ @Parameters(method = "getParams")
+ public void handshake(Config config) throws Exception {
+ setup(config);
+ SSLEngine client = engineFactory.newClientEngine(cipher);
+ SSLEngine server = engineFactory.newServerEngine(cipher);
+ clientApplicationBuffer.clear();
+ clientPacketBuffer.clear();
+ serverApplicationBuffer.clear();
+ serverPacketBuffer.clear();
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ client.beginHandshake();
+ server.beginHandshake();
+ doHandshake(client, server);
+ }
+
+ engineFactory.dispose(client);
+ engineFactory.dispose(server);
+ }
+
+ private void doHandshake(SSLEngine client, SSLEngine server) throws SSLException {
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ // Send as many client-to-server messages as possible
+ doHalfHandshake(client, server, clientPacketBuffer, serverApplicationBuffer);
+
+ if (client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING
+ && server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
+ return;
+ }
+
+ // Do the same with server-to-client messages
+ doHalfHandshake(server, client, serverPacketBuffer, clientApplicationBuffer);
+
+ if (client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING
+ && server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
+ return;
+ }
+ }
+ }
+
+ private void doHalfHandshake(SSLEngine sender, SSLEngine receiver,
+ ByteBuffer senderPacketBuffer, ByteBuffer receiverApplicationBuffer)
+ throws SSLException {
+ SSLEngineResult senderResult;
+ SSLEngineResult receiverResult;
+
+ do {
+ senderResult = sender.wrap(EMPTY_BUFFER, senderPacketBuffer);
+ runDelegatedTasks(senderResult, sender);
+ senderPacketBuffer.flip();
+ receiverResult = receiver.unwrap(senderPacketBuffer, receiverApplicationBuffer);
+ runDelegatedTasks(receiverResult, receiver);
+ senderPacketBuffer.compact();
+ } while (senderResult.getHandshakeStatus() == HandshakeStatus.NEED_WRAP);
+
+ if (rttMillis > 0) {
+ try {
+ Thread.sleep(rttMillis / 2);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) {
+ if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
+ for (;;) {
+ Runnable task = engine.getDelegatedTask();
+ if (task == null) {
+ break;
+ }
+ task.run();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineWrapPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineWrapPerfTest.java
new file mode 100644
index 0000000..1fee218
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineWrapPerfTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2017 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.
+ */
+
+/*
+ * Copyright 2017 The Netty Project
+ *
+ * The Netty Project licenses this file to you 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.conscrypt;
+
+import static org.conscrypt.TestUtils.doEngineHandshake;
+import static org.conscrypt.TestUtils.newTextMessage;
+import static org.junit.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+import java.util.Locale;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import androidx.test.filters.LargeTest;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Benchmark comparing performance of various engine implementations to conscrypt.
+ */
+@RunWith(JUnitParamsRunner.class)
+@LargeTest
+public final class EngineWrapPerfTest {
+ @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ /**
+ * Provider for the benchmark configuration
+ */
+ private class Config {
+ BufferType a_bufferType;
+ int c_messageSize;
+ String d_cipher;
+ Config(BufferType bufferType,
+ int messageSize,
+ String cipher) {
+ a_bufferType = bufferType;
+ c_messageSize = messageSize;
+ d_cipher = cipher;
+ }
+ public BufferType bufferType() {
+ return a_bufferType;
+ }
+
+ public int messageSize() {
+ return c_messageSize;
+ }
+
+ public String cipher() {
+ return d_cipher;
+ }
+ }
+
+ public Collection getParams() {
+ final List<Object[]> params = new ArrayList<>();
+ for (BufferType bufferType : BufferType.values()) {
+ params.add(new Object[] {new Config(bufferType, 64,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")});
+ params.add(new Object[] {new Config(bufferType, 512,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")});
+ params.add(new Object[] {new Config(bufferType, 4096,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")});
+ }
+ return params;
+ }
+
+
+ private EngineFactory engineFactory = new EngineFactory();
+ private String cipher;
+ private SSLEngine clientEngine;
+ private SSLEngine serverEngine;
+
+ private ByteBuffer messageBuffer;
+ private ByteBuffer clientApplicationBuffer;
+ private ByteBuffer clientPacketBuffer;
+ private ByteBuffer serverApplicationBuffer;
+ private ByteBuffer serverPacketBuffer;
+ private ByteBuffer preEncryptedBuffer;
+
+ private void setup(Config config) throws Exception {
+ cipher = config.cipher();
+ BufferType bufferType = config.bufferType();
+
+ clientEngine = engineFactory.newClientEngine(cipher);
+ serverEngine = engineFactory.newServerEngine(cipher);
+
+ // Create the application and packet buffers for both endpoints.
+ clientApplicationBuffer = bufferType.newApplicationBuffer(clientEngine);
+ serverApplicationBuffer = bufferType.newApplicationBuffer(serverEngine);
+ clientPacketBuffer = bufferType.newPacketBuffer(clientEngine);
+ serverPacketBuffer = bufferType.newPacketBuffer(serverEngine);
+
+ // Generate the message to be sent from the client.
+ int messageSize = config.messageSize();
+ messageBuffer = bufferType.newBuffer(messageSize);
+ messageBuffer.put(newTextMessage(messageSize));
+ messageBuffer.flip();
+
+ // Complete the initial TLS handshake.
+ doEngineHandshake(clientEngine, serverEngine, clientApplicationBuffer, clientPacketBuffer,
+ serverApplicationBuffer, serverPacketBuffer, true);
+
+ // Populate the pre-encrypted buffer for use with the unwrap benchmark.
+ preEncryptedBuffer = bufferType.newBuffer(clientEngine.getSession().getPacketBufferSize());
+ doWrap(messageBuffer, preEncryptedBuffer);
+ doUnwrap(preEncryptedBuffer, serverApplicationBuffer);
+ }
+
+ void teardown() {
+ engineFactory.dispose(clientEngine);
+ engineFactory.dispose(serverEngine);
+ }
+
+ @Test
+ @Parameters(method = "getParams")
+ public void wrap(Config config) throws Exception {
+ setup(config);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ // Reset the buffers.
+ messageBuffer.position(0);
+ clientPacketBuffer.clear();
+ // Wrap the original message and create the encrypted data.
+ doWrap(messageBuffer, clientPacketBuffer);
+
+ // Lightweight comparison - just make sure the data length is correct.
+ assertEquals(preEncryptedBuffer.limit(), clientPacketBuffer.limit());
+ }
+ teardown();
+ }
+
+ /**
+ * Simple benchmark that sends a single message from client to server.
+ */
+ @Test
+ @Parameters(method = "getParams")
+ public void wrapAndUnwrap(Config config) throws Exception {
+ setup(config);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ // Reset the buffers.
+ messageBuffer.position(0);
+ clientPacketBuffer.clear();
+ serverApplicationBuffer.clear();
+ // Wrap the original message and create the encrypted data.
+ doWrap(messageBuffer, clientPacketBuffer);
+
+ // Unwrap the encrypted data and get back the original result.
+ doUnwrap(clientPacketBuffer, serverApplicationBuffer);
+
+ // Lightweight comparison - just make sure the unencrypted data length is correct.
+ assertEquals(messageBuffer.limit(), serverApplicationBuffer.limit());
+ }
+ teardown();
+ }
+
+ private void doWrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
+ // Wrap the original message and create the encrypted data.
+ verifyResult(src, clientEngine.wrap(src, dst));
+ dst.flip();
+ }
+
+ private void doUnwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
+ verifyResult(src, serverEngine.unwrap(src, dst));
+ dst.flip();
+ }
+
+ private void verifyResult(ByteBuffer src, SSLEngineResult result) {
+ if (result.getStatus() != SSLEngineResult.Status.OK) {
+ throw new RuntimeException("Operation returned unexpected result " + result);
+ }
+ if (result.bytesConsumed() != src.limit()) {
+ throw new RuntimeException(
+ String.format(Locale.US,
+ "Operation didn't consume all bytes. Expected %d, consumed %d.",
+ src.limit(), result.bytesConsumed()));
+ }
+ }
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
index ba2a65a..4f285ff 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
@@ -24,6 +24,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -94,15 +97,22 @@
}
}
- private Object[] getParams() {
- return new Object[][] {
- new Object[] {new Config(
- EndpointFactory.CONSCRYPT,
- EndpointFactory.CONSCRYPT,
- 64,
- "AES128-GCM",
- ChannelType.CHANNEL)},
- };
+ public Collection getParams() {
+ final List<Object[]> params = new ArrayList<>();
+ for (EndpointFactory endpointFactory : EndpointFactory.values()) {
+ for (ChannelType channelType : ChannelType.values()) {
+ params.add(new Object[] {new Config(endpointFactory,
+ endpointFactory, 64,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType)});
+ params.add(new Object[] {new Config(endpointFactory,
+ endpointFactory, 512,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType)});
+ params.add(new Object[] {new Config(endpointFactory,
+ endpointFactory, 4096,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType)});
+ }
+ }
+ return params;
}
private ClientEndpoint client;
@@ -121,7 +131,8 @@
final ChannelType channelType = config.channelType();
server = config.serverFactory().newServer(
- channelType, config.messageSize(), getCommonProtocolSuites(), ciphers(config));
+ channelType, config.messageSize(),
+ new String[] {"TLSv1.3", "TLSv1.2"}, ciphers(config));
server.setMessageProcessor(new MessageProcessor() {
@Override
public void processMessage(byte[] inMessage, int numBytes, OutputStream os) {
@@ -145,7 +156,8 @@
// Always use the same client for consistency across the benchmarks.
client = config.clientFactory().newClient(
- ChannelType.CHANNEL, server.port(), getCommonProtocolSuites(), ciphers(config));
+ ChannelType.CHANNEL, server.port(),
+ new String[] {"TLSv1.3", "TLSv1.2"}, ciphers(config));
client.start();
// Wait for the initial connection to complete.
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java
index 78fe732..3542b0a 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java
@@ -31,7 +31,6 @@
AES_CBC_PKCS5("AES", "CBC", "PKCS5Padding", new AesKeyGen()),
AES_ECB_PKCS5("AES", "ECB", "PKCS5Padding", new AesKeyGen()),
AES_GCM_NO("AES", "GCM", "NoPadding", new AesKeyGen()),
- AES_GCM_SIV("AES", "GCM_SIV", "NoPadding", new AesKeyGen()),
RSA_ECB_PKCS1("RSA", "ECB", "PKCS1Padding", new RsaKeyGen());
Transformation(String algorithm, String mode, String padding, KeyGen keyGen) {
diff --git a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
index 4bcc8c4..f302033 100644
--- a/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
+++ b/apct-tests/perftests/packagemanager/src/android/os/PackageManagerPerfTest.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
+import android.permission.PermissionManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
@@ -107,6 +108,8 @@
public void setup() {
PackageManager.disableApplicationInfoCache();
PackageManager.disablePackageInfoCache();
+ PermissionManager.disablePermissionCache();
+ PermissionManager.disablePackageNamePermissionCache();
}
@Test
diff --git a/api/Android.bp b/api/Android.bp
index d4ba964..4b26eb4 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -29,12 +29,14 @@
pkgPath: "android/soong/api",
deps: [
"blueprint",
+ "blueprint-proptools",
"soong",
"soong-android",
"soong-genrule",
"soong-java",
],
srcs: ["api.go"],
+ testSrcs: ["api_test.go"],
pluginFor: ["soong_build"],
}
@@ -60,40 +62,8 @@
metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
metalava_cmd += " --quiet "
-soong_config_module_type {
- name: "enable_crashrecovery_module",
- module_type: "combined_apis_defaults",
- config_namespace: "ANDROID",
- bool_variables: ["release_crashrecovery_module"],
- properties: [
- "bootclasspath",
- "system_server_classpath",
- ],
-}
-
-soong_config_bool_variable {
- name: "release_crashrecovery_module",
-}
-
-enable_crashrecovery_module {
- name: "crashrecovery_module_defaults",
- soong_config_variables: {
- release_crashrecovery_module: {
- bootclasspath: [
- "framework-crashrecovery",
- ],
- system_server_classpath: [
- "service-crashrecovery",
- ],
- },
- },
-}
-
combined_apis {
name: "frameworks-base-api",
- defaults: [
- "crashrecovery_module_defaults",
- ],
bootclasspath: [
"android.net.ipsec.ike",
"art.module.public.api",
@@ -126,7 +96,12 @@
"framework-virtualization",
"framework-wifi",
"i18n.module.public.api",
- ],
+ ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), {
+ "true": [
+ "framework-crashrecovery",
+ ],
+ default: [],
+ }),
system_server_classpath: [
"service-art",
"service-configinfrastructure",
@@ -135,7 +110,12 @@
"service-permission",
"service-rkp",
"service-sdksandbox",
- ],
+ ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), {
+ "true": [
+ "service-crashrecovery",
+ ],
+ default: [],
+ }),
}
genrule {
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index 12820f9..8dfddf0 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -1345,4 +1345,5 @@
":hwbinder-stubs-docs",
],
visibility: ["//visibility:public"],
+ is_stubs_module: true,
}
diff --git a/api/api.go b/api/api.go
index d4db49e..b6b1a7e 100644
--- a/api/api.go
+++ b/api/api.go
@@ -54,16 +54,15 @@
// The properties of the combined_apis module type.
type CombinedApisProperties struct {
// Module libraries in the bootclasspath
- Bootclasspath []string
+ Bootclasspath proptools.Configurable[[]string]
// Module libraries on the bootclasspath if include_nonpublic_framework_api is true.
Conditional_bootclasspath []string
// Module libraries in system server
- System_server_classpath []string
+ System_server_classpath proptools.Configurable[[]string]
}
type CombinedApis struct {
android.ModuleBase
- android.DefaultableModuleBase
properties CombinedApisProperties
}
@@ -74,34 +73,41 @@
func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory)
- ctx.RegisterModuleType("combined_apis_defaults", CombinedApisModuleDefaultsFactory)
}
var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
-func (a *CombinedApis) apiFingerprintStubDeps() []string {
+func (a *CombinedApis) bootclasspath(ctx android.ConfigAndErrorContext) []string {
+ return a.properties.Bootclasspath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
+}
+
+func (a *CombinedApis) systemServerClasspath(ctx android.ConfigAndErrorContext) []string {
+ return a.properties.System_server_classpath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
+}
+
+func (a *CombinedApis) apiFingerprintStubDeps(ctx android.BottomUpMutatorContext) []string {
ret := []string{}
ret = append(
ret,
- transformArray(a.properties.Bootclasspath, "", ".stubs")...,
+ transformArray(a.bootclasspath(ctx), "", ".stubs")...,
)
ret = append(
ret,
- transformArray(a.properties.Bootclasspath, "", ".stubs.system")...,
+ transformArray(a.bootclasspath(ctx), "", ".stubs.system")...,
)
ret = append(
ret,
- transformArray(a.properties.Bootclasspath, "", ".stubs.module_lib")...,
+ transformArray(a.bootclasspath(ctx), "", ".stubs.module_lib")...,
)
ret = append(
ret,
- transformArray(a.properties.System_server_classpath, "", ".stubs.system_server")...,
+ transformArray(a.systemServerClasspath(ctx), "", ".stubs.system_server")...,
)
return ret
}
func (a *CombinedApis) DepsMutator(ctx android.BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps()...)
+ ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps(ctx)...)
}
func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -532,8 +538,8 @@
}
func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
- bootclasspath := a.properties.Bootclasspath
- system_server_classpath := a.properties.System_server_classpath
+ bootclasspath := a.bootclasspath(ctx)
+ system_server_classpath := a.systemServerClasspath(ctx)
if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") {
bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...)
sort.Strings(bootclasspath)
@@ -568,7 +574,6 @@
module := &CombinedApis{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitDefaultableModule(module)
android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) })
return module
}
@@ -605,16 +610,3 @@
}
return s2
}
-
-// Defaults
-type CombinedApisModuleDefaults struct {
- android.ModuleBase
- android.DefaultsModuleBase
-}
-
-func CombinedApisModuleDefaultsFactory() android.Module {
- module := &CombinedApisModuleDefaults{}
- module.AddProperties(&CombinedApisProperties{})
- android.InitDefaultsModule(module)
- return module
-}
diff --git a/api/api_test.go b/api/api_test.go
new file mode 100644
index 0000000..47d1670
--- /dev/null
+++ b/api/api_test.go
@@ -0,0 +1,254 @@
+// 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 api
+
+import (
+ "android/soong/android"
+ "android/soong/java"
+ "fmt"
+ "testing"
+
+ "github.com/google/blueprint/proptools"
+)
+
+var prepareForTestWithCombinedApis = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerBuildComponents),
+ java.PrepareForTestWithJavaBuildComponents,
+ android.FixtureAddTextFile("a/Android.bp", gatherRequiredDepsForTest()),
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ android.FixtureMergeMockFs(android.MockFS{
+ "a/api/current.txt": nil,
+ "a/api/removed.txt": nil,
+ "a/api/system-current.txt": nil,
+ "a/api/system-removed.txt": nil,
+ "a/api/test-current.txt": nil,
+ "a/api/test-removed.txt": nil,
+ "a/api/module-lib-current.txt": nil,
+ "a/api/module-lib-removed.txt": nil,
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ }),
+)
+
+func gatherRequiredDepsForTest() string {
+ var bp string
+
+ extraLibraryModules := []string{
+ "stable.core.platform.api.stubs",
+ "core-lambda-stubs",
+ "core.current.stubs",
+ "ext",
+ "framework",
+ "android_stubs_current.from-text",
+ "android_system_stubs_current.from-text",
+ "android_test_stubs_current.from-text",
+ "android_test_frameworks_core_stubs_current.from-text",
+ "android_module_lib_stubs_current.from-text",
+ "android_system_server_stubs_current.from-text",
+ "android_stubs_current.from-source",
+ "android_system_stubs_current.from-source",
+ "android_test_stubs_current.from-source",
+ "android_test_frameworks_core_stubs_current.from-source",
+ "android_module_lib_stubs_current.from-source",
+ "android_system_server_stubs_current.from-source",
+ "android_stubs_current_exportable.from-source",
+ "android_system_stubs_current_exportable.from-source",
+ "android_test_stubs_current_exportable.from-source",
+ "android_module_lib_stubs_current_exportable.from-source",
+ "android_system_server_stubs_current_exportable.from-source",
+ "stub-annotations",
+ }
+
+ extraSdkLibraryModules := []string{
+ "framework-virtualization",
+ "framework-location",
+ }
+
+ extraSystemModules := []string{
+ "core-public-stubs-system-modules",
+ "core-module-lib-stubs-system-modules",
+ "stable-core-platform-api-stubs-system-modules",
+ }
+
+ extraFilegroupModules := []string{
+ "non-updatable-current.txt",
+ "non-updatable-removed.txt",
+ "non-updatable-system-current.txt",
+ "non-updatable-system-removed.txt",
+ "non-updatable-test-current.txt",
+ "non-updatable-test-removed.txt",
+ "non-updatable-module-lib-current.txt",
+ "non-updatable-module-lib-removed.txt",
+ "non-updatable-system-server-current.txt",
+ "non-updatable-system-server-removed.txt",
+ "non-updatable-exportable-current.txt",
+ "non-updatable-exportable-removed.txt",
+ "non-updatable-exportable-system-current.txt",
+ "non-updatable-exportable-system-removed.txt",
+ "non-updatable-exportable-test-current.txt",
+ "non-updatable-exportable-test-removed.txt",
+ "non-updatable-exportable-module-lib-current.txt",
+ "non-updatable-exportable-module-lib-removed.txt",
+ "non-updatable-exportable-system-server-current.txt",
+ "non-updatable-exportable-system-server-removed.txt",
+ }
+
+ for _, extra := range extraLibraryModules {
+ bp += fmt.Sprintf(`
+ java_library {
+ name: "%s",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
+ compile_dex: true,
+ }
+ `, extra)
+ }
+
+ for _, extra := range extraSdkLibraryModules {
+ bp += fmt.Sprintf(`
+ java_sdk_library {
+ name: "%s",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ api_packages: [
+ "foo",
+ ],
+ sdk_version: "core_current",
+ compile_dex: true,
+ annotations_enabled: true,
+ }
+ `, extra)
+ }
+
+ for _, extra := range extraFilegroupModules {
+ bp += fmt.Sprintf(`
+ filegroup {
+ name: "%[1]s",
+ }
+ `, extra)
+ }
+
+ for _, extra := range extraSystemModules {
+ bp += fmt.Sprintf(`
+ java_system_modules {
+ name: "%[1]s",
+ libs: ["%[1]s-lib"],
+ }
+ java_library {
+ name: "%[1]s-lib",
+ sdk_version: "none",
+ system_modules: "none",
+ }
+ `, extra)
+ }
+
+ bp += fmt.Sprintf(`
+ java_defaults {
+ name: "android.jar_defaults",
+ }
+ `)
+
+ return bp
+}
+
+func TestCombinedApisDefaults(t *testing.T) {
+
+ result := android.GroupFixturePreparers(
+ prepareForTestWithCombinedApis,
+ java.FixtureWithLastReleaseApis(
+ "framework-location", "framework-virtualization", "framework-foo", "framework-bar"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "boolean_var": {
+ "for_testing": "true",
+ },
+ }
+ }),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "framework-foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ api_packages: [
+ "foo",
+ ],
+ sdk_version: "core_current",
+ annotations_enabled: true,
+ }
+
+ java_sdk_library {
+ name: "framework-bar",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ api_packages: [
+ "foo",
+ ],
+ sdk_version: "core_current",
+ annotations_enabled: true,
+ }
+
+ combined_apis {
+ name: "foo",
+ bootclasspath: [
+ "framework-bar",
+ ] + select(boolean_var_for_testing(), {
+ true: [
+ "framework-foo",
+ ],
+ default: [],
+ }),
+ }
+ `)
+
+ subModuleDependsOnSelectAppendedModule := java.CheckModuleHasDependency(t,
+ result.TestContext, "foo-current.txt", "", "framework-foo")
+ android.AssertBoolEquals(t, "Submodule expected to depend on the select-appended module",
+ true, subModuleDependsOnSelectAppendedModule)
+}
diff --git a/api/go.work b/api/go.work
index edd002e..c09bee5 100644
--- a/api/go.work
+++ b/api/go.work
@@ -1,17 +1,17 @@
-go 1.18
+go 1.22
use (
.
- ../../../build/soong
../../../build/blueprint
+ ../../../build/soong
../../../external/go-cmp
../../../external/golang-protobuf
)
replace (
android/soong v0.0.0 => ../../../build/soong
- google.golang.org/protobuf v0.0.0 => ../../../external/golang-protobuf
github.com/google/blueprint v0.0.0 => ../../../build/blueprint
github.com/google/go-cmp v0.0.0 => ../../../external/go-cmp
go.starlark.net v0.0.0 => ../../../external/starlark-go
+ google.golang.org/protobuf v0.0.0 => ../../../external/golang-protobuf
)
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 9c1a8e8..7bf06b4 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -271,12 +271,12 @@
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderLimitReached();
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningReached();
- method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
- method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
+ method @Deprecated @FlaggedApi("android.net.platform.flags.deprecate_network_policy_callback") @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
+ method @Deprecated @FlaggedApi("android.net.platform.flags.deprecate_network_policy_callback") @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
}
- public static interface NetworkPolicyManager.NetworkPolicyCallback {
- method public default void onUidBlockedReasonChanged(int, int);
+ @Deprecated @FlaggedApi("android.net.platform.flags.deprecate_network_policy_callback") public static interface NetworkPolicyManager.NetworkPolicyCallback {
+ method @Deprecated public default void onUidBlockedReasonChanged(int, int);
}
public class NetworkWatchlistManager {
diff --git a/core/java/android/animation/OWNERS b/core/java/android/animation/OWNERS
index f3b330a..5223c87 100644
--- a/core/java/android/animation/OWNERS
+++ b/core/java/android/animation/OWNERS
@@ -3,3 +3,4 @@
romainguy@google.com
tianliu@google.com
adamp@google.com
+mount@google.com
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 0fad979..1200b4b 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -118,6 +118,8 @@
per-file Window* = file:/services/core/java/com/android/server/wm/OWNERS
per-file ConfigurationController.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file *ScreenCapture* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file ComponentOptions.java = file:/services/core/java/com/android/server/wm/OWNERS
+
# Multitasking
per-file multitasking.aconfig = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 334b231..3e6bbf6 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -21,6 +21,7 @@
import static android.app.ActivityManager.procStateToString;
import static android.content.pm.PackageManager.GET_SIGNATURES;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -36,6 +37,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
+import android.net.platform.flags.Flags;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Build;
@@ -954,11 +956,24 @@
* @param executor The {@link Executor} to run the callback on.
* @param callback The {@link NetworkPolicyCallback} to be registered.
* @hide
+ *
+ * @deprecated This API is only supported up to Android version
+ * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions,
+ * {@link android.net.ConnectivityManager.NetworkCallback} should be used wherever possible.
+ *
+ * @throws UnsupportedOperationException when called on Android versions after
+ * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}.
*/
+ @Deprecated
+ @FlaggedApi(Flags.FLAG_DEPRECATE_NETWORK_POLICY_CALLBACK)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY)
public void registerNetworkPolicyCallback(@Nullable Executor executor,
@NonNull NetworkPolicyCallback callback) {
+ if (Flags.deprecateNetworkPolicyCallback()) {
+ throw new UnsupportedOperationException("NetworkPolicyCallback is no longer supported."
+ + " Please use ConnectivityManager APIs instead");
+ }
if (callback == null) {
throw new NullPointerException("Callback cannot be null.");
}
@@ -974,10 +989,23 @@
*
* @param callback The {@link NetworkPolicyCallback} to be unregistered.
* @hide
+ *
+ * @deprecated This API is only supported up to Android version
+ * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions,
+ * {@link android.net.ConnectivityManager.NetworkCallback} should be used wherever possible.
+ *
+ * @throws UnsupportedOperationException when called on Android versions after
+ * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}.
*/
+ @Deprecated
+ @FlaggedApi(Flags.FLAG_DEPRECATE_NETWORK_POLICY_CALLBACK)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY)
public void unregisterNetworkPolicyCallback(@NonNull NetworkPolicyCallback callback) {
+ if (Flags.deprecateNetworkPolicyCallback()) {
+ throw new UnsupportedOperationException("NetworkPolicyCallback is no longer supported."
+ + " Please use ConnectivityManager APIs instead");
+ }
if (callback == null) {
throw new NullPointerException("Callback cannot be null.");
}
@@ -990,8 +1018,18 @@
/**
* Interface for the callback to listen for changes to network blocked status of apps.
*
+ * @deprecated This API is only supported up to Android version
+ * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions, this callback will
+ * <b>not</b> be called when the network blocked status of an app changes. Instead,
+ * {@link android.net.ConnectivityManager.NetworkCallback} should be used wherever possible.
+ *
+ * @see #registerNetworkPolicyCallback(Executor, NetworkPolicyCallback)
+ * @see #unregisterNetworkPolicyCallback(NetworkPolicyCallback)
+ *
* @hide
*/
+ @FlaggedApi(Flags.FLAG_DEPRECATE_NETWORK_POLICY_CALLBACK)
+ @Deprecated
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public interface NetworkPolicyCallback {
/**
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
index 048c50e..48eb968 100644
--- a/core/java/android/net/flags.aconfig
+++ b/core/java/android/net/flags.aconfig
@@ -25,3 +25,13 @@
description: "Flag for registerOffloadEngine API in NsdManager"
bug: "294777050"
}
+
+flag {
+ name: "deprecate_network_policy_callback"
+ namespace: "backstage_power"
+ description: "Flag for deprecating NetworkPolicyCallback and related APIs"
+ bug: "353342610"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index c9f207c..50242ba 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -29,7 +29,7 @@
* interface describes the abstract protocol for interacting with a
* remotable object. Do not implement this interface directly, instead
* extend from {@link Binder}.
- *
+ *
* <p>The key IBinder API is {@link #transact transact()} matched by
* {@link Binder#onTransact Binder.onTransact()}. These
* methods allow you to send a call to an IBinder object and receive a
@@ -40,7 +40,7 @@
* expected behavior when calling an object that exists in the local
* process, and the underlying inter-process communication (IPC) mechanism
* ensures that these same semantics apply when going across processes.
- *
+ *
* <p>The data sent through transact() is a {@link Parcel}, a generic buffer
* of data that also maintains some meta-data about its contents. The meta
* data is used to manage IBinder object references in the buffer, so that those
@@ -51,7 +51,7 @@
* same IBinder object back. These semantics allow IBinder/Binder objects to
* be used as a unique identity (to serve as a token or for other purposes)
* that can be managed across processes.
- *
+ *
* <p>The system maintains a pool of transaction threads in each process that
* it runs in. These threads are used to dispatch all
* IPCs coming in from other processes. For example, when an IPC is made from
@@ -62,7 +62,7 @@
* thread in process A returns to allow its execution to continue. In effect,
* other processes appear to use as additional threads that you did not create
* executing in your own process.
- *
+ *
* <p>The Binder system also supports recursion across processes. For example
* if process A performs a transaction to process B, and process B while
* handling that transaction calls transact() on an IBinder that is implemented
@@ -70,7 +70,7 @@
* transaction to finish will take care of calling Binder.onTransact() on the
* object being called by B. This ensures that the recursion semantics when
* calling remote binder object are the same as when calling local objects.
- *
+ *
* <p>When working with remote objects, you often want to find out when they
* are no longer valid. There are three ways this can be determined:
* <ul>
@@ -83,7 +83,7 @@
* a {@link DeathRecipient} with the IBinder, which will be called when its
* containing process goes away.
* </ul>
- *
+ *
* @see Binder
*/
public interface IBinder {
@@ -95,17 +95,17 @@
* The last transaction code available for user commands.
*/
int LAST_CALL_TRANSACTION = 0x00ffffff;
-
+
/**
* IBinder protocol transaction code: pingBinder().
*/
int PING_TRANSACTION = ('_'<<24)|('P'<<16)|('N'<<8)|'G';
-
+
/**
* IBinder protocol transaction code: dump internal state.
*/
int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P';
-
+
/**
* IBinder protocol transaction code: execute a shell command.
* @hide
@@ -129,7 +129,7 @@
* across the platform. To support older code, the default implementation
* logs the tweet to the main log as a simple emulation of broadcasting
* it publicly over the Internet.
- *
+ *
* <p>Also, upon completing the dispatch, the object must make a cup
* of tea, return it to the caller, and exclaim "jolly good message
* old boy!".
@@ -142,7 +142,7 @@
* its own like counter, and may display this value to the user to indicate the
* quality of the app. This is an optional command that applications do not
* need to handle, so the default implementation is to do nothing.
- *
+ *
* <p>There is no response returned and nothing about the
* system will be functionally affected by it, but it will improve the
* app's self-esteem.
@@ -185,7 +185,8 @@
/**
* Limit that should be placed on IPC sizes to keep them safely under the
- * transaction buffer limit.
+ * transaction buffer limit. This is a recommendation, and is not the real
+ * limit. Transactions should be preferred to be even smaller than this.
* @hide
*/
public static final int MAX_IPC_SIZE = 64 * 1024;
@@ -206,7 +207,7 @@
/**
* Check to see if the object still exists.
- *
+ *
* @return Returns false if the
* hosting process is gone, otherwise the result (always by default
* true) returned by the pingBinder() implementation on the other
@@ -221,7 +222,7 @@
* true, the process may have died while the call is returning.
*/
public boolean isBinderAlive();
-
+
/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object. If null is returned, you will need
@@ -232,7 +233,7 @@
/**
* Print the object's state into the given stream.
- *
+ *
* @param fd The raw file descriptor that the dump is being sent to.
* @param args additional arguments to the dump request.
*/
@@ -280,7 +281,7 @@
/**
* Perform a generic operation with the object.
- *
+ *
* @param code The action to perform. This should
* be a number between {@link #FIRST_CALL_TRANSACTION} and
* {@link #LAST_CALL_TRANSACTION}.
@@ -360,13 +361,13 @@
* Remove a previously registered death notification.
* The recipient will no longer be called if this object
* dies.
- *
+ *
* @return {@code true} if the <var>recipient</var> is successfully
* unlinked, assuring you that its
* {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
* will not be called; {@code false} if the target IBinder has already
* died, meaning the method has been (or soon will be) called.
- *
+ *
* @throws java.util.NoSuchElementException if the given
* <var>recipient</var> has not been registered with the IBinder, and
* the IBinder is still alive. Note that if the <var>recipient</var>
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index a49ee7d..0c34c6f 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -110,92 +110,6 @@
void shutdown();
/**
- ** TETHERING RELATED
- **/
-
- /**
- * Returns true if IP forwarding is enabled
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Use {@code android.net.INetd#ipfwdEnabled}")
- boolean getIpForwardingEnabled();
-
- /**
- * Enables/Disables IP Forwarding
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Avoid using this directly. Instead, enable tethering with "
- + "{@code android.net.TetheringManager#startTethering}. See also "
- + "{@code INetd#ipfwdEnableForwarding(String)}.")
- void setIpForwardingEnabled(boolean enabled);
-
- /**
- * Start tethering services with the specified dhcp server range
- * arg is a set of start end pairs defining the ranges.
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "{@code android.net.TetheringManager#startTethering}")
- void startTethering(in String[] dhcpRanges);
-
- /**
- * Stop currently running tethering services
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "{@code android.net.TetheringManager#stopTethering(int)}")
- void stopTethering();
-
- /**
- * Returns true if tethering services are started
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Generally track your own tethering requests. "
- + "See also {@code android.net.INetd#tetherIsEnabled()}")
- boolean isTetheringStarted();
-
- /**
- * Tethers the specified interface
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Avoid using this directly. Instead, enable tethering with "
- + "{@code android.net.TetheringManager#startTethering}. See also "
- + "{@code com.android.net.module.util.NetdUtils#tetherInterface}.")
- void tetherInterface(String iface);
-
- /**
- * Untethers the specified interface
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Avoid using this directly. Instead, disable "
- + "tethering with {@code android.net.TetheringManager#stopTethering(int)}. "
- + "See also {@code NetdUtils#untetherInterface}.")
- void untetherInterface(String iface);
-
- /**
- * Returns a list of currently tethered interfaces
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "{@code android.net.TetheringManager#getTetheredIfaces()}")
- String[] listTetheredInterfaces();
-
- /**
- * Enables Network Address Translation between two interfaces.
- * The address and netmask of the external interface is used for
- * the NAT'ed network.
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Avoid using this directly. Instead, enable tethering with "
- + "{@code android.net.TetheringManager#startTethering}.")
- void enableNat(String internalInterface, String externalInterface);
-
- /**
- * Disables Network Address Translation between two interfaces.
- */
- @UnsupportedAppUsage(maxTargetSdk = 34, trackingBug = 170729553,
- publicAlternatives = "Avoid using this directly. Instead, disable tethering with "
- + "{@code android.net.TetheringManager#stopTethering(int)}.")
- void disableNat(String internalInterface, String externalInterface);
-
- /**
** DATA USAGE RELATED
**/
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 0be2d3e3..e95c6a4 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -277,7 +277,7 @@
if (service != null) {
return service;
} else {
- return Binder.allowBlocking(getIServiceManager().checkService(name));
+ return Binder.allowBlocking(getIServiceManager().checkService(name).getBinder());
}
} catch (RemoteException e) {
Log.e(TAG, "error in checkService", e);
@@ -425,7 +425,7 @@
private static IBinder rawGetService(String name) throws RemoteException {
final long start = sStatLogger.getTime();
- final IBinder binder = getIServiceManager().getService(name);
+ final IBinder binder = getIServiceManager().getService(name).getBinder();
final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 7b91dd5..6c9a5c7 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -58,12 +58,12 @@
}
@UnsupportedAppUsage
- public IBinder getService(String name) throws RemoteException {
+ public Service getService(String name) throws RemoteException {
// Same as checkService (old versions of servicemanager had both methods).
- return mServiceManager.checkService(name);
+ return checkService(name);
}
- public IBinder checkService(String name) throws RemoteException {
+ public Service checkService(String name) throws RemoteException {
return mServiceManager.checkService(name);
}
diff --git a/core/java/android/service/contextualsearch/OWNERS b/core/java/android/service/contextualsearch/OWNERS
index 463adf4..b723872 100644
--- a/core/java/android/service/contextualsearch/OWNERS
+++ b/core/java/android/service/contextualsearch/OWNERS
@@ -1,3 +1,2 @@
srazdan@google.com
-volnov@google.com
hackz@google.com
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
index 0f2f8ad..32f4822 100644
--- a/core/java/android/speech/OWNERS
+++ b/core/java/android/speech/OWNERS
@@ -1,4 +1,3 @@
volnov@google.com
eugeniom@google.com
schfan@google.com
-hackz@google.com
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index e4b0952..9ac273f 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -2,4 +2,3 @@
hackz@google.com
shivanker@google.com
-volnov@google.com
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 1a660be..3b25109 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -477,7 +477,7 @@
} else if (mMinuteSpinnerInput.hasFocus()) {
inputMethodManager.hideSoftInputFromView(mMinuteSpinnerInput, 0);
mMinuteSpinnerInput.clearFocus();
- } else if (mAmPmSpinnerInput.hasFocus()) {
+ } else if (mAmPmSpinnerInput != null && mAmPmSpinnerInput.hasFocus()) {
inputMethodManager.hideSoftInputFromView(mAmPmSpinnerInput, 0);
mAmPmSpinnerInput.clearFocus();
}
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
index d426f12..6c72544 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.cpp
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -87,9 +87,10 @@
IF_ALOGD() {
ALOGD("Total number of LOAD segments %zu", programHeaders.size());
- ALOGD("Size before punching holes st_blocks: %" PRIu64
- ", st_blksize: %d, st_size: %" PRIu64 "",
- beforePunch.st_blocks, beforePunch.st_blksize,
+ ALOGD("Size before punching holes st_blocks: %" PRIu64 ", st_blksize: %" PRIu64
+ ", st_size: %" PRIu64 "",
+ static_cast<uint64_t>(beforePunch.st_blocks),
+ static_cast<uint64_t>(beforePunch.st_blksize),
static_cast<uint64_t>(beforePunch.st_size));
}
@@ -193,9 +194,10 @@
ALOGD("lstat64 failed for filePath %s, error:%d", filePath, errno);
return false;
}
- ALOGD("Size after punching holes st_blocks: %" PRIu64 ", st_blksize: %d, st_size: %" PRIu64
- "",
- afterPunch.st_blocks, afterPunch.st_blksize,
+ ALOGD("Size after punching holes st_blocks: %" PRIu64 ", st_blksize: %" PRIu64
+ ", st_size: %" PRIu64 "",
+ static_cast<uint64_t>(afterPunch.st_blocks),
+ static_cast<uint64_t>(afterPunch.st_blksize),
static_cast<uint64_t>(afterPunch.st_size));
}
@@ -271,8 +273,9 @@
uint64_t blockSize = beforePunch.st_blksize;
IF_ALOGD() {
ALOGD("Extra field length: %hu, Size before punching holes st_blocks: %" PRIu64
- ", st_blksize: %d, st_size: %" PRIu64 "",
- extraFieldLen, beforePunch.st_blocks, beforePunch.st_blksize,
+ ", st_blksize: %" PRIu64 ", st_size: %" PRIu64 "",
+ extraFieldLen, static_cast<uint64_t>(beforePunch.st_blocks),
+ static_cast<uint64_t>(beforePunch.st_blksize),
static_cast<uint64_t>(beforePunch.st_size));
}
@@ -346,8 +349,9 @@
return false;
}
ALOGD("punchHolesInApk:: Size after punching holes st_blocks: %" PRIu64
- ", st_blksize: %d, st_size: %" PRIu64 "",
- afterPunch.st_blocks, afterPunch.st_blksize,
+ ", st_blksize: %" PRIu64 ", st_size: %" PRIu64 "",
+ static_cast<uint64_t>(afterPunch.st_blocks),
+ static_cast<uint64_t>(afterPunch.st_blksize),
static_cast<uint64_t>(afterPunch.st_size));
}
return true;
diff --git a/core/tests/coretests/src/android/animation/OWNERS b/core/tests/coretests/src/android/animation/OWNERS
new file mode 100644
index 0000000..1eefb3a
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/animation/OWNERS
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0f12438..97f99e9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -518,6 +518,7 @@
<permission name="android.permission.RENOUNCE_PERMISSIONS" />
<permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
<permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" />
+ <permission name="android.permission.READ_DROPBOX_DATA" />
<permission name="android.permission.READ_LOGS" />
<permission name="android.permission.BRIGHTNESS_SLIDER_USAGE" />
<permission name="android.permission.ACCESS_AMBIENT_LIGHT_STATS" />
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index 7c7cb18..9887c27 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -55,9 +55,9 @@
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.tree.JCTree.JCNewClass;
import java.util.ArrayList;
import java.util.Arrays;
@@ -67,7 +67,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Predicate;
import java.util.regex.Pattern;
import javax.lang.model.element.Name;
@@ -125,6 +124,12 @@
instanceMethod()
.onDescendantOf("android.content.Context")
.withNameMatching(Pattern.compile("^send(Ordered|Sticky)?Broadcast.*$")));
+ private static final Matcher<ExpressionTree> SEND_BROADCAST_AS_USER =
+ methodInvocation(
+ instanceMethod()
+ .onDescendantOf("android.content.Context")
+ .withNameMatching(
+ Pattern.compile("^send(Ordered|Sticky)?Broadcast.*AsUser.*$")));
private static final Matcher<ExpressionTree> SEND_PENDING_INTENT = methodInvocation(
instanceMethod()
.onDescendantOf("android.app.PendingIntent")
@@ -306,18 +311,6 @@
}
}
- private static ExpressionTree findArgumentByParameterName(MethodInvocationTree tree,
- Predicate<String> paramName) {
- final MethodSymbol sym = ASTHelpers.getSymbol(tree);
- final List<VarSymbol> params = sym.getParameters();
- for (int i = 0; i < params.size(); i++) {
- if (paramName.test(params.get(i).name.toString())) {
- return tree.getArguments().get(i);
- }
- }
- return null;
- }
-
private static Name resolveName(ExpressionTree tree) {
if (tree instanceof IdentifierTree) {
return ((IdentifierTree) tree).getName();
@@ -345,76 +338,85 @@
private static ParsedRequiresPermission parseBroadcastSourceRequiresPermission(
MethodInvocationTree methodTree, VisitorState state) {
- final ExpressionTree arg = findArgumentByParameterName(methodTree,
- (name) -> name.toLowerCase().contains("intent"));
- if (arg instanceof IdentifierTree) {
- final Name argName = ((IdentifierTree) arg).getName();
- final MethodTree method = state.findEnclosing(MethodTree.class);
- final AtomicReference<ParsedRequiresPermission> res = new AtomicReference<>();
- method.accept(new TreeScanner<Void, Void>() {
- private ParsedRequiresPermission last;
+ if (methodTree.getArguments().size() < 1) {
+ return null;
+ }
+ final ExpressionTree arg = methodTree.getArguments().get(0);
+ if (!(arg instanceof IdentifierTree)) {
+ return null;
+ }
+ final Name argName = ((IdentifierTree) arg).getName();
+ final MethodTree method = state.findEnclosing(MethodTree.class);
+ final AtomicReference<ParsedRequiresPermission> res = new AtomicReference<>();
+ method.accept(new TreeScanner<Void, Void>() {
+ private ParsedRequiresPermission mLast;
- @Override
- public Void visitMethodInvocation(MethodInvocationTree tree, Void param) {
- if (Objects.equal(methodTree, tree)) {
- res.set(last);
- } else {
- final Name name = resolveName(tree.getMethodSelect());
- if (Objects.equal(argName, name)
- && INTENT_SET_ACTION.matches(tree, state)) {
- last = parseIntentAction(tree);
+ @Override
+ public Void visitMethodInvocation(MethodInvocationTree tree, Void param) {
+ if (Objects.equal(methodTree, tree)) {
+ res.set(mLast);
+ } else {
+ final Name name = resolveName(tree.getMethodSelect());
+ if (Objects.equal(argName, name) && INTENT_SET_ACTION.matches(tree, state)) {
+ mLast = parseIntentAction(tree);
+ } else if (name == null && tree.getMethodSelect() instanceof MemberSelectTree) {
+ ExpressionTree innerTree =
+ ((MemberSelectTree) tree.getMethodSelect()).getExpression();
+ if (innerTree instanceof JCNewClass) {
+ mLast = parseIntentAction((NewClassTree) innerTree);
}
}
- return super.visitMethodInvocation(tree, param);
}
+ return super.visitMethodInvocation(tree, param);
+ }
- @Override
- public Void visitAssignment(AssignmentTree tree, Void param) {
- final Name name = resolveName(tree.getVariable());
- final Tree init = tree.getExpression();
- if (Objects.equal(argName, name)
- && init instanceof NewClassTree) {
- last = parseIntentAction((NewClassTree) init);
- }
- return super.visitAssignment(tree, param);
+ @Override
+ public Void visitAssignment(AssignmentTree tree, Void param) {
+ final Name name = resolveName(tree.getVariable());
+ final Tree init = tree.getExpression();
+ if (Objects.equal(argName, name) && init instanceof NewClassTree) {
+ mLast = parseIntentAction((NewClassTree) init);
}
+ return super.visitAssignment(tree, param);
+ }
- @Override
- public Void visitVariable(VariableTree tree, Void param) {
- final Name name = tree.getName();
- final ExpressionTree init = tree.getInitializer();
- if (Objects.equal(argName, name)
- && init instanceof NewClassTree) {
- last = parseIntentAction((NewClassTree) init);
- }
- return super.visitVariable(tree, param);
+ @Override
+ public Void visitVariable(VariableTree tree, Void param) {
+ final Name name = tree.getName();
+ final ExpressionTree init = tree.getInitializer();
+ if (Objects.equal(argName, name) && init instanceof NewClassTree) {
+ mLast = parseIntentAction((NewClassTree) init);
}
- }, null);
- return res.get();
- }
- return null;
+ return super.visitVariable(tree, param);
+ }
+ }, null);
+ return res.get();
}
private static ParsedRequiresPermission parseBroadcastTargetRequiresPermission(
MethodInvocationTree tree, VisitorState state) {
- final ExpressionTree arg = findArgumentByParameterName(tree,
- (name) -> name.toLowerCase().contains("permission"));
final ParsedRequiresPermission res = new ParsedRequiresPermission();
- if (arg != null) {
- arg.accept(new TreeScanner<Void, Void>() {
- @Override
- public Void visitIdentifier(IdentifierTree tree, Void param) {
- res.addConstValue(tree);
- return super.visitIdentifier(tree, param);
- }
-
- @Override
- public Void visitMemberSelect(MemberSelectTree tree, Void param) {
- res.addConstValue(tree);
- return super.visitMemberSelect(tree, param);
- }
- }, null);
+ int permission_position = 1;
+ if (SEND_BROADCAST_AS_USER.matches(tree, state)) {
+ permission_position = 2;
}
+ if (tree.getArguments().size() < permission_position + 1) {
+ return res;
+ }
+ final ExpressionTree arg = tree.getArguments().get(permission_position);
+ arg.accept(new TreeScanner<Void, Void>() {
+ @Override
+ public Void visitIdentifier(IdentifierTree tree, Void param) {
+ res.addConstValue(tree);
+ return super.visitIdentifier(tree, param);
+ }
+
+ @Override
+ public Void visitMemberSelect(MemberSelectTree tree, Void param) {
+ res.addConstValue(tree);
+ return super.visitMemberSelect(tree, param);
+ }
+ }, null);
return res;
}
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
index e53372d..05fde7c 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
@@ -412,6 +412,19 @@
" context.sendBroadcast(intent);",
" }",
" }",
+ " public void exampleWithChainedMethod(Context context) {",
+ " Intent intent = new Intent(FooManager.ACTION_RED)",
+ " .putExtra(\"foo\", 42);",
+ " context.sendBroadcast(intent, FooManager.PERMISSION_RED);",
+ " context.sendBroadcastWithMultiplePermissions(intent,",
+ " new String[] { FooManager.PERMISSION_RED });",
+ " }",
+ " public void exampleWithAsUser(Context context) {",
+ " Intent intent = new Intent(FooManager.ACTION_RED);",
+ " context.sendBroadcastAsUser(intent, 42, FooManager.PERMISSION_RED);",
+ " context.sendBroadcastAsUserMultiplePermissions(intent, 42,",
+ " new String[] { FooManager.PERMISSION_RED });",
+ " }",
"}")
.doTest();
}
diff --git a/errorprone/tests/res/android/content/Context.java b/errorprone/tests/res/android/content/Context.java
index efc4fb1..9d622ff 100644
--- a/errorprone/tests/res/android/content/Context.java
+++ b/errorprone/tests/res/android/content/Context.java
@@ -36,4 +36,15 @@
public void sendBroadcastWithMultiplePermissions(Intent intent, String[] receiverPermissions) {
throw new UnsupportedOperationException();
}
+
+ /* Fake user type for test purposes */
+ public void sendBroadcastAsUser(Intent intent, int user, String receiverPermission) {
+ throw new UnsupportedOperationException();
+ }
+
+ /* Fake user type for test purposes */
+ public void sendBroadcastAsUserMultiplePermissions(
+ Intent intent, int user, String[] receiverPermissions) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/errorprone/tests/res/android/content/Intent.java b/errorprone/tests/res/android/content/Intent.java
index 288396e..7ccea78 100644
--- a/errorprone/tests/res/android/content/Intent.java
+++ b/errorprone/tests/res/android/content/Intent.java
@@ -24,4 +24,8 @@
public Intent setAction(String action) {
throw new UnsupportedOperationException();
}
+
+ public Intent putExtra(String extra, int value) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
index 7ad68aa..b01b2b7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
@@ -2,7 +2,6 @@
atsjenk@google.com
jorgegil@google.com
madym@google.com
-nmusgrave@google.com
pbdr@google.com
tkachenkoi@google.com
vaniadesmonda@google.com
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 8acaf3b..e575dae 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -5263,6 +5263,8 @@
* main thread.)
*/
public void setCallback(@Nullable /* MediaCodec. */ Callback cb, @Nullable Handler handler) {
+ boolean setCallbackStallFlag =
+ GetFlag(() -> android.media.codec.Flags.setCallbackStall());
if (cb != null) {
synchronized (mListenerLock) {
EventHandler newHandler = getEventHandlerOn(handler, mCallbackHandler);
@@ -5270,7 +5272,7 @@
// even if we were to extend this to be callable dynamically, it must
// be called when codec is flushed, so no messages are pending.
if (newHandler != mCallbackHandler) {
- if (android.media.codec.Flags.setCallbackStall()) {
+ if (setCallbackStallFlag) {
logAndRun(
"[new handler] removeMessages(SET_CALLBACK)",
() -> {
@@ -5289,7 +5291,7 @@
}
}
} else if (mCallbackHandler != null) {
- if (android.media.codec.Flags.setCallbackStall()) {
+ if (setCallbackStallFlag) {
logAndRun(
"[null handler] removeMessages(SET_CALLBACK)",
() -> {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 417b7a6..53ff172 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -65,6 +65,7 @@
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
<uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
<uses-permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" />
+ <uses-permission android:name="android.permission.READ_DROPBOX_DATA" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE" />
<uses-permission android:name="android.permission.ACCESS_AMBIENT_LIGHT_STATS" />
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
index beb8ddef..24cbd10 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
@@ -264,7 +264,7 @@
alpha = itemAlpha
}
} else {
- Modifier.animateItemPlacement()
+ Modifier.animateItem()
}
Box(modifier) {
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 178102e..33d3624 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -16,6 +16,38 @@
visibility: ["//visibility:public"],
}
+filegroup {
+ name: "ravenwood-services-policies",
+ srcs: [
+ "texts/ravenwood-services-policies.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+filegroup {
+ name: "ravenwood-framework-policies",
+ srcs: [
+ "texts/ravenwood-framework-policies.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+filegroup {
+ name: "ravenwood-standard-options",
+ srcs: [
+ "texts/ravenwood-standard-options.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+filegroup {
+ name: "ravenwood-annotation-allowed-classes",
+ srcs: [
+ "texts/ravenwood-annotation-allowed-classes.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
java_library {
name: "ravenwood-annotations-lib",
srcs: [":ravenwood-annotations"],
@@ -151,6 +183,77 @@
filegroup {
name: "ravenwood-services-jarjar-rules",
- srcs: ["ravenwood-services-jarjar-rules.txt"],
+ srcs: ["texts/ravenwood-services-jarjar-rules.txt"],
visibility: ["//frameworks/base"],
}
+
+java_library {
+ name: "services.fakes.ravenwood-jarjar",
+ installable: false,
+ srcs: [":services.fakes-sources"],
+ libs: [
+ "ravenwood-framework",
+ "services.core.ravenwood",
+ ],
+ jarjar_rules: ":ravenwood-services-jarjar-rules",
+ visibility: ["//visibility:private"],
+}
+
+java_library {
+ name: "mockito-ravenwood-prebuilt",
+ installable: false,
+ static_libs: [
+ "mockito-robolectric-prebuilt",
+ ],
+}
+
+java_library {
+ name: "inline-mockito-ravenwood-prebuilt",
+ installable: false,
+ static_libs: [
+ "inline-mockito-robolectric-prebuilt",
+ ],
+}
+
+android_ravenwood_libgroup {
+ name: "ravenwood-runtime",
+ libs: [
+ "100-framework-minus-apex.ravenwood",
+ "200-kxml2-android",
+
+ "android.test.mock.ravenwood",
+ "ravenwood-helper-runtime",
+ "hoststubgen-helper-runtime.ravenwood",
+ "services.core.ravenwood-jarjar",
+ "services.fakes.ravenwood-jarjar",
+
+ // Provide runtime versions of utils linked in below
+ "junit",
+ "truth",
+ "flag-junit",
+ "ravenwood-framework",
+ "ravenwood-junit-impl",
+ "ravenwood-junit-impl-flag",
+ "mockito-ravenwood-prebuilt",
+ "inline-mockito-ravenwood-prebuilt",
+
+ // It's a stub, so it should be towards the end.
+ "z00-all-updatable-modules-system-stubs",
+ ],
+ jni_libs: [
+ "libandroid_runtime",
+ ],
+}
+
+android_ravenwood_libgroup {
+ name: "ravenwood-utils",
+ libs: [
+ "junit",
+ "truth",
+ "flag-junit",
+ "ravenwood-framework",
+ "ravenwood-junit",
+ "mockito-ravenwood-prebuilt",
+ "inline-mockito-ravenwood-prebuilt",
+ ],
+}
diff --git a/ravenwood/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
similarity index 100%
rename from ravenwood/ravenwood-annotation-allowed-classes.txt
rename to ravenwood/texts/ravenwood-annotation-allowed-classes.txt
diff --git a/ravenwood/framework-minus-apex-ravenwood-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt
similarity index 100%
rename from ravenwood/framework-minus-apex-ravenwood-policies.txt
rename to ravenwood/texts/ravenwood-framework-policies.txt
diff --git a/ravenwood/ravenwood-services-jarjar-rules.txt b/ravenwood/texts/ravenwood-services-jarjar-rules.txt
similarity index 100%
rename from ravenwood/ravenwood-services-jarjar-rules.txt
rename to ravenwood/texts/ravenwood-services-jarjar-rules.txt
diff --git a/ravenwood/services.core-ravenwood-policies.txt b/ravenwood/texts/ravenwood-services-policies.txt
similarity index 100%
rename from ravenwood/services.core-ravenwood-policies.txt
rename to ravenwood/texts/ravenwood-services-policies.txt
diff --git a/ravenwood/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt
similarity index 100%
rename from ravenwood/ravenwood-standard-options.txt
rename to ravenwood/texts/ravenwood-standard-options.txt
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index eb03709..d9926a4 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -150,6 +150,15 @@
private static final int DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
PackageHealthObserverImpact.USER_IMPACT_LEVEL_71;
+ // Comma separated list of all packages exempt from user impact level threshold. If a package
+ // in the list is crash looping, all the mitigations including factory reset will be performed.
+ private static final String PACKAGES_EXEMPT_FROM_IMPACT_LEVEL_THRESHOLD =
+ "persist.device_config.configuration.packages_exempt_from_impact_level_threshold";
+
+ // Comma separated list of default packages exempt from user impact level threshold.
+ private static final String DEFAULT_PACKAGES_EXEMPT_FROM_IMPACT_LEVEL_THRESHOLD =
+ "com.android.systemui";
+
private long mNumberOfNativeCrashPollsRemaining;
private static final int DB_VERSION = 1;
@@ -196,6 +205,8 @@
private final DeviceConfig.OnPropertiesChangedListener
mOnPropertyChangedListener = this::onPropertyChanged;
+ private final Set<String> mPackagesExemptFromImpactLevelThreshold = new ArraySet<>();
+
// The set of packages that have been synced with the ExplicitHealthCheckController
@GuardedBy("mLock")
private Set<String> mRequestedHealthCheckPackages = new ArraySet<>();
@@ -518,7 +529,7 @@
@FailureReasons int failureReason,
int currentObserverImpact,
int mitigationCount) {
- if (currentObserverImpact < getUserImpactLevelLimit()) {
+ if (allowMitigations(currentObserverImpact, versionedPackage)) {
synchronized (mLock) {
mLastMitigation = mSystemClock.uptimeMillis();
}
@@ -526,6 +537,13 @@
}
}
+ private boolean allowMitigations(int currentObserverImpact,
+ VersionedPackage versionedPackage) {
+ return currentObserverImpact < getUserImpactLevelLimit()
+ || getPackagesExemptFromImpactLevelThreshold().contains(
+ versionedPackage.getPackageName());
+ }
+
private long getMitigationWindowMs() {
return SystemProperties.getLong(MITIGATION_WINDOW_MS, DEFAULT_MITIGATION_WINDOW_MS);
}
@@ -657,6 +675,15 @@
DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD);
}
+ private Set<String> getPackagesExemptFromImpactLevelThreshold() {
+ if (mPackagesExemptFromImpactLevelThreshold.isEmpty()) {
+ String packageNames = SystemProperties.get(PACKAGES_EXEMPT_FROM_IMPACT_LEVEL_THRESHOLD,
+ DEFAULT_PACKAGES_EXEMPT_FROM_IMPACT_LEVEL_THRESHOLD);
+ return Set.of(packageNames.split("\\s*,\\s*"));
+ }
+ return mPackagesExemptFromImpactLevelThreshold;
+ }
+
/** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */
@Retention(SOURCE)
@IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index 17f2fcc..bb35b37 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -340,6 +340,11 @@
getOutPrintWriter().println("Profile uses unified challenge");
return false;
}
+ if (mOld.isEmpty()) {
+ getOutPrintWriter().println(
+ "User has a lock credential, but old credential was not provided");
+ return false;
+ }
try {
final boolean result = mLockPatternUtils.checkCredential(getOldCredential(),
diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java
index 5ea3e70..74f0d9c 100644
--- a/services/core/java/com/android/server/net/NetworkManagementService.java
+++ b/services/core/java/com/android/server/net/NetworkManagementService.java
@@ -81,8 +81,6 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.HexDump;
-import com.android.modules.utils.build.SdkLevel;
-import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -833,144 +831,6 @@
}
@Override
- public boolean getIpForwardingEnabled() throws IllegalStateException{
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException(
- "NMS#getIpForwardingEnabled not supported in V+");
- }
- try {
- return mNetdService.ipfwdEnabled();
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void setIpForwardingEnabled(boolean enable) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException(
- "NMS#setIpForwardingEnabled not supported in V+");
- } try {
- if (enable) {
- mNetdService.ipfwdEnableForwarding("tethering");
- } else {
- mNetdService.ipfwdDisableForwarding("tethering");
- }
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void startTethering(String[] dhcpRange) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#startTethering not supported in V+");
- }
- try {
- NetdUtils.tetherStart(mNetdService, true /* usingLegacyDnsProxy */, dhcpRange);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void stopTethering() {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#stopTethering not supported in V+");
- }
- try {
- mNetdService.tetherStop();
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public boolean isTetheringStarted() {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#isTetheringStarted not supported in V+");
- }
- try {
- return mNetdService.tetherIsEnabled();
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void tetherInterface(String iface) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#tetherInterface not supported in V+");
- }
- try {
- final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress();
- final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength());
- NetdUtils.tetherInterface(mNetdService, iface, dest);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void untetherInterface(String iface) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#untetherInterface not supported in V+");
- }
- try {
- NetdUtils.untetherInterface(mNetdService, iface);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public String[] listTetheredInterfaces() {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException(
- "NMS#listTetheredInterfaces not supported in V+");
- }
- try {
- return mNetdService.tetherInterfaceList();
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void enableNat(String internalInterface, String externalInterface) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#enableNat not supported in V+");
- }
- try {
- mNetdService.tetherAddForward(internalInterface, externalInterface);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void disableNat(String internalInterface, String externalInterface) {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (SdkLevel.isAtLeastV()) {
- throw new UnsupportedOperationException("NMS#disableNat not supported in V+");
- }
- try {
- mNetdService.tetherRemoveForward(internalInterface, externalInterface);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
public void setInterfaceQuota(String iface, long quotaBytes) {
PermissionUtils.enforceNetworkStackPermission(mContext);
@@ -1126,30 +986,19 @@
}
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDataSaverModeEnabled");
try {
- if (SdkLevel.isAtLeastV()) {
- // setDataSaverEnabled throws if it fails to set data saver.
- mContext.getSystemService(ConnectivityManager.class)
- .setDataSaverEnabled(enable);
- mDataSaverMode = enable;
- if (mUseMeteredFirewallChains) {
- // Copy mDataSaverMode state to FIREWALL_CHAIN_METERED_ALLOW
- // until ConnectivityService allows manipulation of the data saver mode via
- // FIREWALL_CHAIN_METERED_ALLOW.
- synchronized (mRulesLock) {
- mFirewallChainStates.put(FIREWALL_CHAIN_METERED_ALLOW, enable);
- }
+ // setDataSaverEnabled throws if it fails to set data saver.
+ mContext.getSystemService(ConnectivityManager.class).setDataSaverEnabled(enable);
+ mDataSaverMode = enable;
+ if (mUseMeteredFirewallChains) {
+ // Copy mDataSaverMode state to FIREWALL_CHAIN_METERED_ALLOW
+ // until ConnectivityService allows manipulation of the data saver mode via
+ // FIREWALL_CHAIN_METERED_ALLOW.
+ synchronized (mRulesLock) {
+ mFirewallChainStates.put(FIREWALL_CHAIN_METERED_ALLOW, enable);
}
- return true;
- } else {
- final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
- if (changed) {
- mDataSaverMode = enable;
- } else {
- Log.e(TAG, "setDataSaverMode(" + enable + "): failed to set iptables");
- }
- return changed;
}
- } catch (RemoteException | IllegalStateException e) {
+ return true;
+ } catch (IllegalStateException e) {
Log.e(TAG, "setDataSaverMode(" + enable + "): failed with exception", e);
return false;
} finally {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 079f338..365c9b5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -4118,7 +4118,7 @@
fout.increaseIndent();
for (int i = 0; i < mSubscriptionPlans.size(); i++) {
final int subId = mSubscriptionPlans.keyAt(i);
- fout.println("Subscriber ID " + subId + ":");
+ fout.println("Subscription ID " + subId + ":");
fout.increaseIndent();
final SubscriptionPlan[] plans = mSubscriptionPlans.valueAt(i);
if (!ArrayUtils.isEmpty(plans)) {
diff --git a/services/core/java/com/android/server/net/watchlist/OWNERS b/services/core/java/com/android/server/net/watchlist/OWNERS
index d0c4e55..eef1e46 100644
--- a/services/core/java/com/android/server/net/watchlist/OWNERS
+++ b/services/core/java/com/android/server/net/watchlist/OWNERS
@@ -1,2 +1 @@
-alanstokes@google.com
simonjw@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1c22087..6e65a74 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1115,9 +1115,9 @@
}
@Override
- public void onUserUnlocked(@NonNull TargetUser user) {
- if (user.isPreCreated()) return;
- mService.handleOnUserUnlocked(user.getUserIdentifier());
+ public void onUserSwitching(@NonNull TargetUser from, @NonNull TargetUser to) {
+ if (to.isPreCreated()) return;
+ mService.handleOnUserSwitching(from.getUserIdentifier(), to.getUserIdentifier());
}
}
@@ -3680,8 +3680,8 @@
mDevicePolicyEngine.handleUnlockUser(userId);
}
- void handleOnUserUnlocked(int userId) {
- showNewUserDisclaimerIfNecessary(userId);
+ void handleOnUserSwitching(int fromUserId, int toUserId) {
+ showNewUserDisclaimerIfNecessary(toUserId);
}
void handleStopUser(int userId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
index 1000bfa..dbd60c5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
@@ -17,6 +17,7 @@
package com.android.server.devicepolicy;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.VerifierDeviceIdentity;
import android.net.wifi.WifiManager;
import android.os.Build;
@@ -66,13 +67,14 @@
mMeid = meid;
mSerialNumber = Build.getSerial();
WifiManager wifiManager = context.getSystemService(WifiManager.class);
- Preconditions.checkState(wifiManager != null, "Unable to access WiFi service");
- final String[] macAddresses = wifiManager.getFactoryMacAddresses();
- if (macAddresses == null || macAddresses.length == 0) {
- mMacAddress = "";
- } else {
- mMacAddress = macAddresses[0];
+ String macAddress = "";
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ final String[] macAddresses = wifiManager.getFactoryMacAddresses();
+ if (macAddresses != null && macAddresses.length > 0) {
+ macAddress = macAddresses[0];
+ }
}
+ mMacAddress = macAddress;
}
private static String getPaddedTruncatedString(String input, int maxLength) {
diff --git a/services/fakes/Android.bp b/services/fakes/Android.bp
index 148054b..d44bb5a 100644
--- a/services/fakes/Android.bp
+++ b/services/fakes/Android.bp
@@ -16,5 +16,5 @@
"java/**/*.java",
],
path: "java",
- visibility: ["//frameworks/base"],
+ visibility: ["//frameworks/base/ravenwood:__subpackages__"],
}
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 3ed6ad7..dab3978 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -354,6 +354,9 @@
private static void createAndUploadReport(ProfcollectForwardingService pfs) {
BackgroundThread.get().getThreadHandler().post(() -> {
+ if (pfs.mIProfcollect == null) {
+ return;
+ }
String reportName;
try {
reportName = pfs.mIProfcollect.report(pfs.mUsageSetting) + ".zip";
@@ -398,17 +401,19 @@
if (randomNum >= traceFrequency) {
return;
}
- // For a small percentage a traces, we collect the initialization behavior.
- boolean traceInitialization = ThreadLocalRandom.current().nextInt(10) < 1;
- int traceDelay = traceInitialization ? 0 : 1000;
- String traceTag = traceInitialization ? "camera_init" : "camera";
- BackgroundThread.get().getThreadHandler().postDelayed(() -> {
+ final int traceDuration = 5000;
+ final String traceTag = "camera";
+ BackgroundThread.get().getThreadHandler().post(() -> {
+ if (mIProfcollect == null) {
+ return;
+ }
try {
- mIProfcollect.trace_process(traceTag, "android.hardware.camera.provider");
+ mIProfcollect.trace_process(traceTag, "android.hardware.camera.provider",
+ traceDuration);
} catch (RemoteException e) {
Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
}
- }, traceDelay);
+ });
}
}, null);
}
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 7607c64..92af034 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -15,4 +15,4 @@
per-file CarrierConfigManager.java=amruthr@google.com,tgunn@google.com,rgreenwalt@google.com,satk@google.com
#Domain Selection is jointly owned, add additional owners for domain selection specific files
-per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com,jdyou@google.com
+per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,jaesikkong@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com,jdyou@google.com
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index e29d321..5976657 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -51,10 +51,8 @@
java_library {
name: "android.test.mock.ravenwood",
+ defaults: ["ravenwood-internal-only-visibility-java"],
srcs: [":android-test-mock-sources"],
- visibility: [
- "//frameworks/base",
- ],
}
android_ravenwood_test {
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 3722fef..c0e90f9 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -35,6 +35,7 @@
import android.Manifest;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
@@ -77,6 +78,7 @@
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -413,6 +415,311 @@
verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
}
+ @Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopWithRescuePartyAndRollbackObserver() throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ VersionedPackage versionedPackageA = new VersionedPackage(APP_A, VERSION_CODE);
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: SCOPED_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: ALL_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD reached. No more mitigations applied
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopWithRescuePartyAndRollbackObserverEnableDeprecateFlagReset()
+ throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ VersionedPackage versionedPackageA = new VersionedPackage(APP_A, VERSION_CODE);
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageA), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD reached. No more mitigations applied
+ verify(rescuePartyObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageA,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopSystemUIWithRescuePartyAndRollbackObserver() throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ String systemUi = "com.android.systemui";
+ VersionedPackage versionedPackageUi = new VersionedPackage(
+ systemUi, VERSION_CODE);
+ RollbackInfo rollbackInfoUi = getRollbackInfo(systemUi, VERSION_CODE, 1,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_LOW,
+ ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL, rollbackInfoUi));
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: SCOPED_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: ALL_DEVICE_CONFIG_RESET
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: RESET_SETTINGS_UNTRUSTED_DEFAULTS
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 4);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 5);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: RESET_SETTINGS_UNTRUSTED_CHANGES
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 5);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 6);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: RESET_SETTINGS_TRUSTED_DEFAULTS
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 6);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 7);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Factory reset. High impact rollbacks are performed only for boot loops.
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 7);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 8);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_DEPRECATE_FLAGS_AND_SETTINGS_RESETS)
+ public void testCrashLoopSystemUIWithRescuePartyAndRollbackObserverEnableDeprecateFlagReset()
+ throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
+ RollbackPackageHealthObserver rollbackObserver =
+ setUpRollbackPackageHealthObserver(watchdog);
+ String systemUi = "com.android.systemui";
+ VersionedPackage versionedPackageUi = new VersionedPackage(
+ systemUi, VERSION_CODE);
+ RollbackInfo rollbackInfoUi = getRollbackInfo(systemUi, VERSION_CODE, 1,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_LOW,
+ ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL, rollbackInfoUi));
+
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).then(inv -> {
+ ApplicationInfo info = new ApplicationInfo();
+ info.flags |= ApplicationInfo.FLAG_PERSISTENT
+ | ApplicationInfo.FLAG_SYSTEM;
+ return info;
+ });
+
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: WARM_REBOOT
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Low impact rollback
+ verify(rollbackObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+
+ // update available rollbacks to mock rollbacks being applied after the call to
+ // rollbackObserver.execute
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(ROLLBACK_INFO_HIGH, ROLLBACK_INFO_MANUAL));
+
+ raiseFatalFailureAndDispatch(watchdog,
+ Arrays.asList(versionedPackageUi), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+
+ // Mitigation: Factory reset. High impact rollbacks are performed only for boot loops.
+ verify(rescuePartyObserver).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ verify(rescuePartyObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 3);
+ verify(rollbackObserver, never()).execute(versionedPackageUi,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 2);
+ }
+
RollbackPackageHealthObserver setUpRollbackPackageHealthObserver(PackageWatchdog watchdog) {
RollbackPackageHealthObserver rollbackObserver =
spy(new RollbackPackageHealthObserver(mSpyContext, mApexManager));
@@ -424,7 +731,6 @@
watchdog.registerHealthObserver(rollbackObserver);
return rollbackObserver;
}
-
RescuePartyObserver setUpRescuePartyObserver(PackageWatchdog watchdog) {
setCrashRecoveryPropRescueBootCount(0);
RescuePartyObserver rescuePartyObserver = spy(RescuePartyObserver.getInstance(mSpyContext));
@@ -686,4 +992,20 @@
mTestLooper.moveTimeForward(milliSeconds);
mTestLooper.dispatchAll();
}
+
+ private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog,
+ List<VersionedPackage> packages, int failureReason) {
+ long triggerFailureCount = watchdog.getTriggerFailureCount();
+ if (failureReason == PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK
+ || failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
+ triggerFailureCount = 1;
+ }
+ for (int i = 0; i < triggerFailureCount; i++) {
+ watchdog.onPackageFailure(packages, failureReason);
+ }
+ mTestLooper.dispatchAll();
+ if (Flags.recoverabilityDetection()) {
+ moveTimeForwardAndDispatch(watchdog.DEFAULT_MITIGATION_WINDOW_MS);
+ }
+ }
}
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 031dd5b..9b8c3b3 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -836,6 +836,28 @@
return 1;
}
+ // Parse the feature flag values. An argument that starts with '@' points to a file to read flag
+ // values from.
+ std::vector<std::string> all_feature_flags_args;
+ for (const std::string& arg : feature_flags_args_) {
+ if (util::StartsWith(arg, "@")) {
+ const std::string path = arg.substr(1, arg.size() - 1);
+ std::string error;
+ if (!file::AppendArgsFromFile(path, &all_feature_flags_args, &error)) {
+ context.GetDiagnostics()->Error(android::DiagMessage(path) << error);
+ return 1;
+ }
+ } else {
+ all_feature_flags_args.push_back(arg);
+ }
+ }
+
+ for (const std::string& arg : all_feature_flags_args) {
+ if (!ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) {
+ return 1;
+ }
+ }
+
return Compile(&context, file_collection.get(), archive_writer.get(), options_);
}
diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h
index 61c5b60..70c8791 100644
--- a/tools/aapt2/cmd/Compile.h
+++ b/tools/aapt2/cmd/Compile.h
@@ -24,6 +24,7 @@
#include "Command.h"
#include "ResourceTable.h"
#include "androidfw/IDiagnostics.h"
+#include "cmd/Util.h"
#include "format/Archive.h"
#include "process/IResourceTableConsumer.h"
@@ -45,6 +46,7 @@
bool preserve_visibility_of_styleables = false;
bool verbose = false;
std::optional<std::string> product_;
+ FeatureFlagValues feature_flag_values;
};
/** Parses flags and compiles resources to be used in linking. */
@@ -92,6 +94,12 @@
"Leave only resources specific to the given product. All "
"other resources (including defaults) are removed.",
&options_.product_);
+ AddOptionalFlagList("--feature-flags",
+ "Specify the values of feature flags. The pairs in the argument\n"
+ "are separated by ',' the name is separated from the value by '='.\n"
+ "The name can have a suffix of ':ro' to indicate it is read only."
+ "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).",
+ &feature_flags_args_);
}
int Action(const std::vector<std::string>& args) override;
@@ -101,6 +109,7 @@
CompileOptions options_;
std::optional<std::string> visibility_;
std::optional<std::string> trace_folder_;
+ std::vector<std::string> feature_flags_args_;
};
int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 8fe414f..2f17853 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -332,8 +332,9 @@
AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
AddOptionalFlagList("--feature-flags",
"Specify the values of feature flags. The pairs in the argument\n"
- "are separated by ',' and the name is separated from the value by '='.\n"
- "Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).",
+ "are separated by ',' the name is separated from the value by '='.\n"
+ "The name can have a suffix of ':ro' to indicate it is read only."
+ "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).",
&feature_flags_args_);
AddOptionalSwitch("--non-updatable-system",
"Mark the app as a non-updatable system app. This inserts\n"
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index 678d846..7739171 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -128,7 +128,7 @@
if (parts.size() > 2) {
diag->Error(android::DiagMessage()
<< "Invalid feature flag and optional value '" << flag_and_value
- << "'. Must be in the format 'flag_name[=true|false]");
+ << "'. Must be in the format 'flag_name[:ro][=true|false]");
return false;
}
@@ -138,6 +138,28 @@
return false;
}
+ std::vector<std::string> name_parts = util::Split(flag_name, ':');
+ if (name_parts.size() > 2) {
+ diag->Error(android::DiagMessage()
+ << "Invalid feature flag and optional value '" << flag_and_value
+ << "'. Must be in the format 'flag_name[:READ_ONLY|READ_WRITE][=true|false]");
+ return false;
+ }
+ flag_name = name_parts[0];
+ bool read_only = false;
+ if (name_parts.size() == 2) {
+ if (name_parts[1] == "ro" || name_parts[1] == "READ_ONLY") {
+ read_only = true;
+ } else if (name_parts[1] == "READ_WRITE") {
+ read_only = false;
+ } else {
+ diag->Error(android::DiagMessage()
+ << "Invalid feature flag and optional value '" << flag_and_value
+ << "'. Must be in the format 'flag_name[:READ_ONLY|READ_WRITE][=true|false]");
+ return false;
+ }
+ }
+
std::optional<bool> flag_value = {};
if (parts.size() == 2) {
StringPiece str_flag_value = util::TrimWhitespace(parts[1]);
@@ -151,13 +173,13 @@
}
}
- if (auto [it, inserted] =
- out_feature_flag_values->try_emplace(std::string(flag_name), flag_value);
+ auto ffp = FeatureFlagProperties{read_only, flag_value};
+ if (auto [it, inserted] = out_feature_flag_values->try_emplace(std::string(flag_name), ffp);
!inserted) {
// We are allowing the same flag to appear multiple times, last value wins.
diag->Note(android::DiagMessage()
<< "Value for feature flag '" << flag_name << "' was given more than once");
- it->second = flag_value;
+ it->second = ffp;
}
}
return true;
diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h
index 9ece5dd..6b8813b 100644
--- a/tools/aapt2/cmd/Util.h
+++ b/tools/aapt2/cmd/Util.h
@@ -37,7 +37,17 @@
namespace aapt {
-using FeatureFlagValues = std::map<std::string, std::optional<bool>, std::less<>>;
+struct FeatureFlagProperties {
+ bool read_only;
+ std::optional<bool> enabled;
+
+ FeatureFlagProperties(bool ro, std::optional<bool> e) : read_only(ro), enabled(e) {
+ }
+
+ bool operator==(const FeatureFlagProperties&) const = default;
+};
+
+using FeatureFlagValues = std::map<std::string, FeatureFlagProperties, std::less<>>;
// Parses a configuration density (ex. hdpi, xxhdpi, 234dpi, anydpi, etc).
// Returns Nothing and logs a human friendly error message if the string was not legal.
diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp
index 723d87e..7818340 100644
--- a/tools/aapt2/cmd/Util_test.cpp
+++ b/tools/aapt2/cmd/Util_test.cpp
@@ -383,21 +383,25 @@
TEST(UtilTest, ParseFeatureFlagsParameter_DuplicateFlag) {
auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics();
FeatureFlagValues feature_flag_values;
- ASSERT_TRUE(
- ParseFeatureFlagsParameter("foo=true,bar=true,foo=false", diagnostics, &feature_flag_values));
- EXPECT_THAT(feature_flag_values, UnorderedElementsAre(Pair("foo", std::optional<bool>(false)),
- Pair("bar", std::optional<bool>(true))));
+ ASSERT_TRUE(ParseFeatureFlagsParameter("foo=true,bar:READ_WRITE=true,foo:ro=false", diagnostics,
+ &feature_flag_values));
+ EXPECT_THAT(
+ feature_flag_values,
+ UnorderedElementsAre(Pair("foo", FeatureFlagProperties{true, std::optional<bool>(false)}),
+ Pair("bar", FeatureFlagProperties{false, std::optional<bool>(true)})));
}
TEST(UtilTest, ParseFeatureFlagsParameter_Valid) {
auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics();
FeatureFlagValues feature_flag_values;
- ASSERT_TRUE(ParseFeatureFlagsParameter("foo= true, bar =FALSE,baz=, quux", diagnostics,
- &feature_flag_values));
- EXPECT_THAT(feature_flag_values,
- UnorderedElementsAre(Pair("foo", std::optional<bool>(true)),
- Pair("bar", std::optional<bool>(false)),
- Pair("baz", std::nullopt), Pair("quux", std::nullopt)));
+ ASSERT_TRUE(ParseFeatureFlagsParameter("foo:READ_ONLY= true, bar:ro =FALSE,baz:READ_WRITE=, quux",
+ diagnostics, &feature_flag_values));
+ EXPECT_THAT(
+ feature_flag_values,
+ UnorderedElementsAre(Pair("foo", FeatureFlagProperties{true, std::optional<bool>(true)}),
+ Pair("bar", FeatureFlagProperties{true, std::optional<bool>(false)}),
+ Pair("baz", FeatureFlagProperties{false, std::nullopt}),
+ Pair("quux", FeatureFlagProperties{false, std::nullopt})));
}
TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
diff --git a/tools/aapt2/link/FeatureFlagsFilter.cpp b/tools/aapt2/link/FeatureFlagsFilter.cpp
index fdf3f74..9d40db5 100644
--- a/tools/aapt2/link/FeatureFlagsFilter.cpp
+++ b/tools/aapt2/link/FeatureFlagsFilter.cpp
@@ -63,12 +63,11 @@
flag_name = flag_name.substr(1);
}
- if (auto it = feature_flag_values_.find(std::string(flag_name));
- it != feature_flag_values_.end()) {
- if (it->second.has_value()) {
+ if (auto it = feature_flag_values_.find(flag_name); it != feature_flag_values_.end()) {
+ if (it->second.enabled.has_value()) {
if (options_.remove_disabled_elements) {
// Remove if flag==true && attr=="!flag" (negated) OR flag==false && attr=="flag"
- return *it->second == negated;
+ return *it->second.enabled == negated;
}
} else if (options_.flags_must_have_value) {
diagnostics_->Error(android::DiagMessage(node->line_number)
diff --git a/tools/aapt2/link/FeatureFlagsFilter_test.cpp b/tools/aapt2/link/FeatureFlagsFilter_test.cpp
index 53086cc..2db2899 100644
--- a/tools/aapt2/link/FeatureFlagsFilter_test.cpp
+++ b/tools/aapt2/link/FeatureFlagsFilter_test.cpp
@@ -48,7 +48,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" />
</manifest>)EOF",
- {{"flag", false}});
+ {{"flag", FeatureFlagProperties{false, false}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -60,7 +60,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="flag" />
</manifest>)EOF",
- {{"flag", false}});
+ {{"flag", FeatureFlagProperties{false, false}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -73,7 +73,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="!flag" />
</manifest>)EOF",
- {{"flag", true}});
+ {{"flag", FeatureFlagProperties{false, true}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -86,7 +86,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="flag" />
</manifest>)EOF",
- {{"flag", true}});
+ {{"flag", FeatureFlagProperties{false, true}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -102,7 +102,7 @@
<permission android:name="FOO" android:featureFlag="flag"
android:protectionLevel="dangerous" />
</manifest>)EOF",
- {{"flag", true}});
+ {{"flag", FeatureFlagProperties{false, true}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -123,7 +123,7 @@
</activity>
</application>
</manifest>)EOF",
- {{"flag", true}});
+ {{"flag", FeatureFlagProperties{false, true}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -145,7 +145,7 @@
</activity>
</application>
</manifest>)EOF",
- {{"flag", true}});
+ {{"flag", FeatureFlagProperties{false, true}}});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -162,7 +162,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag=" " />
</manifest>)EOF",
- {{"flag", false}});
+ {{"flag", FeatureFlagProperties{false, false}}});
ASSERT_THAT(doc, IsNull());
}
@@ -171,7 +171,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="flag" />
</manifest>)EOF",
- {{"flag", std::nullopt}});
+ {{"flag", FeatureFlagProperties{false, std::nullopt}}});
ASSERT_THAT(doc, IsNull());
}
@@ -180,7 +180,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="unrecognized" />
</manifest>)EOF",
- {{"flag", true}});
+ {{"flag", FeatureFlagProperties{false, true}}});
ASSERT_THAT(doc, IsNull());
}
@@ -190,7 +190,7 @@
<permission android:name="FOO" android:featureFlag="bar" />
<permission android:name="FOO" android:featureFlag="unrecognized" />
</manifest>)EOF",
- {{"flag", std::nullopt}});
+ {{"flag", FeatureFlagProperties{false, std::nullopt}}});
ASSERT_THAT(doc, IsNull());
}
@@ -199,7 +199,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="flag" />
</manifest>)EOF",
- {{"flag", false}}, {.remove_disabled_elements = false});
+ {{"flag", FeatureFlagProperties{false, false}}},
+ {.remove_disabled_elements = false});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -212,7 +213,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="flag" />
</manifest>)EOF",
- {{"flag", std::nullopt}}, {.flags_must_have_value = false});
+ {{"flag", FeatureFlagProperties{false, std::nullopt}}},
+ {.flags_must_have_value = false});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());
@@ -225,7 +227,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android">
<permission android:name="FOO" android:featureFlag="unrecognized" />
</manifest>)EOF",
- {{"flag", true}}, {.fail_on_unrecognized_flags = false});
+ {{"flag", FeatureFlagProperties{false, true}}},
+ {.fail_on_unrecognized_flags = false});
ASSERT_THAT(doc, NotNull());
auto root = doc->root.get();
ASSERT_THAT(root, NotNull());