diff options
133 files changed, 2113 insertions, 774 deletions
diff --git a/Android.bp b/Android.bp index 5211fe23e1bb..5c64dba0f41f 100644 --- a/Android.bp +++ b/Android.bp @@ -413,7 +413,6 @@ java_defaults { "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/BAL_OWNERS b/BAL_OWNERS index d56a1d4634df..ec779e76fa3b 100644 --- a/BAL_OWNERS +++ b/BAL_OWNERS @@ -2,4 +2,6 @@ brufino@google.com achim@google.com topjohnwu@google.com lus@google.com +haok@google.com +wnan@google.com diff --git a/CleanSpec.mk b/CleanSpec.mk index 02e8eecbb721..e6801034cd97 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -262,6 +262,7 @@ $(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/.intermediates/frameworks/base/li $(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 # ****************************************************************** @@ -28,7 +28,7 @@ per-file */TEST_MAPPING = * # 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 f43c37bf637d..912f19d4ca3c 100644 --- a/Ravenwood.bp +++ b/Ravenwood.bp @@ -30,7 +30,7 @@ java_genrule { 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 @@ java_genrule { "--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 @@ java_genrule { 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 @@ java_genrule { "--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_genrule { java_library { name: "services.core.ravenwood-jarjar", + defaults: ["ravenwood-internal-only-visibility-java"], installable: false, static_libs: [ "services.core.ravenwood", @@ -144,88 +145,29 @@ java_library { 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 c69ae39846bd..36266de04d23 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 androidx.test.filters.LargeTest; 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 @@ public final class CipherEncryptPerfTest { } } - 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 dd9f4eb7e8d3..2643bae4060f 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.IOException; 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 @@ public final class ClientSocketPerfTest { } } - 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 000000000000..8a0d52dff3b1 --- /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 000000000000..cd0ac96b41de --- /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 000000000000..1fee2183b11e --- /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 ba2a65a17e84..4f285ff4eb94 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 static org.junit.Assert.assertEquals; 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 @@ public final class ServerSocketPerfTest { } } - 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 @@ public final class ServerSocketPerfTest { 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 @@ public final class ServerSocketPerfTest { // 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 78fe73262e4c..3542b0a76803 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 @@ public enum Transformation { 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 4bcc8c499f0d..f302033dee0f 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.PackageInstaller; 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 class PackageManagerPerfTest { public void setup() { PackageManager.disableApplicationInfoCache(); PackageManager.disablePackageInfoCache(); + PermissionManager.disablePermissionCache(); + PermissionManager.disablePackageNamePermissionCache(); } @Test diff --git a/api/Android.bp b/api/Android.bp index bf4e6a11d25a..4b26eb48f5de 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -29,12 +29,14 @@ bootstrap_go_package { 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 = "$(location metalava)" 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 @@ combined_apis { "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 @@ combined_apis { "service-permission", "service-rkp", "service-sdksandbox", - ], + ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), { + "true": [ + "service-crashrecovery", + ], + default: [], + }), } genrule { @@ -365,8 +345,6 @@ stubs_defaults { "--hide CallbackInterface", // Disable HiddenSuperclass, as Metalava handles this fine (it should be hidden by default) "--hide HiddenSuperclass", - "--hide-package android.audio.policy.configuration.V7_0", - "--hide-package com.android.server", "--manifest $(location :frameworks-base-core-AndroidManifest.xml)", ], filter_packages: packages_to_document, diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index 12820f9ff277..8dfddf0e13c8 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -1345,4 +1345,5 @@ java_library { ":hwbinder-stubs-docs", ], visibility: ["//visibility:public"], + is_stubs_module: true, } diff --git a/api/api.go b/api/api.go index d4db49e90a01..b6b1a7e44510 100644 --- a/api/api.go +++ b/api/api.go @@ -54,16 +54,15 @@ var non_updatable_modules = []string{virtualization, location} // 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 init() { 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 createFullExportableApiLibraries(ctx android.LoadHookContext) { } 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 @@ func combinedApisModuleFactory() android.Module { 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 @@ func remove(s []string, v string) []string { } 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 000000000000..47d167093b39 --- /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/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt index bf67187f4bad..0a3ae4f790b0 100644 --- a/api/coverage/tools/ExtractFlaggedApis.kt +++ b/api/coverage/tools/ExtractFlaggedApis.kt @@ -16,9 +16,9 @@ package android.platform.coverage +import com.android.tools.metalava.model.CallableItem import com.android.tools.metalava.model.ClassItem import com.android.tools.metalava.model.Item -import com.android.tools.metalava.model.MethodItem import com.android.tools.metalava.model.text.ApiFile import java.io.File import java.io.FileWriter @@ -40,24 +40,24 @@ fun main(args: Array<String>) { fun extractFlaggedApisFromClass( classItem: ClassItem, - methods: List<MethodItem>, + callables: List<CallableItem>, packageName: String, builder: FlagApiMap.Builder ) { - if (methods.isEmpty()) return + if (callables.isEmpty()) return val classFlag = getClassFlag(classItem) - for (method in methods) { - val methodFlag = getFlagAnnotation(method) ?: classFlag + for (callable in callables) { + val callableFlag = getFlagAnnotation(callable) ?: classFlag val api = JavaMethod.newBuilder() .setPackageName(packageName) .setClassName(classItem.fullName()) - .setMethodName(method.name()) - for (param in method.parameters()) { + .setMethodName(callable.name()) + for (param in callable.parameters()) { api.addParameters(param.type().toTypeString()) } - if (methodFlag != null) { - addFlaggedApi(builder, api, methodFlag) + if (callableFlag != null) { + addFlaggedApi(builder, api, callableFlag) } } } diff --git a/api/go.work b/api/go.work index edd002e7efba..c09bee578b61 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/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 7eb9d0f3ea91..fdf9abc49604 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -236,7 +236,7 @@ void BootAnimation::onFirstRef() { ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); preloadAnimation(); - ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms", + ALOGD("%sAnimationPreloadTiming stop time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); } } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 9c1a8e854e92..7bf06b4afc3d 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -271,12 +271,12 @@ package android.net { 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/api/system-current.txt b/core/api/system-current.txt index 5aa89b98353f..805cfb7b115d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3738,6 +3738,7 @@ package android.content { method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.content.Intent registerReceiverForAllUsers(@Nullable android.content.BroadcastReceiver, @NonNull android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler, int); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle); method public void sendBroadcastMultiplePermissions(@NonNull android.content.Intent, @NonNull String[], @Nullable android.app.BroadcastOptions); + method @FlaggedApi("android.os.ordered_broadcast_multiple_permissions") public void sendOrderedBroadcastMultiplePermissions(@NonNull android.content.Intent, @NonNull String[], @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @Nullable android.os.Bundle, @NonNull android.os.UserHandle); field public static final String AMBIENT_CONTEXT_SERVICE = "ambient_context"; diff --git a/core/java/android/animation/OWNERS b/core/java/android/animation/OWNERS index f3b330a02116..5223c870824c 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/Activity.java b/core/java/android/app/Activity.java index ee82b3f6ad02..76e761d62f20 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3678,7 +3678,9 @@ public class Activity extends ContextThemeWrapper * @see View#findViewById(int) * @see Activity#requireViewById(int) */ - /* TODO(b/347672184): Re-add @Nullable */ + // Strictly speaking this should be marked as @Nullable but the nullability of the return value + // is deliberately left unspecified as idiomatically correct code can make assumptions either + // way based on local context, e.g. layout specification. public <T extends View> T findViewById(@IdRes int id) { return getWindow().findViewById(id); } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index af56cb4d55b2..d1bd88cfd1d8 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1524,6 +1524,17 @@ class ContextImpl extends Context { public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { + String[] receiverPermissions = receiverPermission == null ? null + : new String[] {receiverPermission}; + sendOrderedBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions, appOp, + options, resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + + @Override + public void sendOrderedBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, + String[] receiverPermissions, int appOp, Bundle options, + BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, + String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { @@ -1543,8 +1554,6 @@ class ContextImpl extends Context { } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); - String[] receiverPermissions = receiverPermission == null ? null - : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntentWithFeature( @@ -1571,6 +1580,20 @@ class ContextImpl extends Context { } @Override + public void sendOrderedBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions, + String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler, + int initialCode, String initialData, @Nullable Bundle initialExtras, + @Nullable Bundle options) { + int intAppOp = AppOpsManager.OP_NONE; + if (!TextUtils.isEmpty(receiverAppOp)) { + intAppOp = AppOpsManager.strOpToOp(receiverAppOp); + } + sendOrderedBroadcastAsUserMultiplePermissions(intent, getUser(), receiverPermissions, + intAppOp, options, resultReceiver, scheduler, initialCode, initialData, + initialExtras); + } + + @Override public void sendOrderedBroadcast(Intent intent, int initialCode, String receiverPermission, String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler, String initialData, @Nullable Bundle initialExtras, Bundle options) { diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 160d00c8a269..d73d536c4675 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -565,7 +565,9 @@ public class Dialog implements DialogInterface, Window.Callback, * @see View#findViewById(int) * @see Dialog#requireViewById(int) */ - /* TODO(b/347672184): Re-add @Nullable */ + // Strictly speaking this should be marked as @Nullable but the nullability of the return value + // is deliberately left unspecified as idiomatically correct code can make assumptions either + // way based on local context, e.g. layout specification. public <T extends View> T findViewById(@IdRes int id) { return mWindow.findViewById(id); } diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 0fad979e27cf..1200b4b45712 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -118,6 +118,8 @@ per-file *Task* = file:/services/core/java/com/android/server/wm/OWNERS 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/app/admin/OWNERS b/core/java/android/app/admin/OWNERS index 308f1d622c25..4f3f5d9c3535 100644 --- a/core/java/android/app/admin/OWNERS +++ b/core/java/android/app/admin/OWNERS @@ -1,7 +1,6 @@ # Bug component: 142675 # Assign bugs to device-policy-manager-triage@google.com -file:WorkDeviceExperience_OWNERS file:EnterprisePlatformSecurity_OWNERS yamasani@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS index e4ffd7f41aa0..b53bdc202a89 100644 --- a/core/java/android/app/assist/OWNERS +++ b/core/java/android/app/assist/OWNERS @@ -1,2 +1 @@ -hackz@google.com -volnov@google.com
\ No newline at end of file +srazdan@google.com diff --git a/core/java/android/audio/policy/configuration/V7_0/package-info.java b/core/java/android/audio/policy/configuration/V7_0/package-info.java new file mode 100644 index 000000000000..8f7425fc2b5b --- /dev/null +++ b/core/java/android/audio/policy/configuration/V7_0/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Hide the android.audio.policy.configuration.V7_0 API as that is managed + * separately. + * + * @hide + */ +package android.audio.policy.configuration.V7_0; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a6eed50a594a..b121da37fd40 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2916,6 +2916,23 @@ public abstract class Context { @Nullable String initialData, @Nullable Bundle initialExtras); /** + * Similar to above but takes array of names of permissions that a receiver must hold in order + * to receive your broadcast. If empty, no permissions are required. + * + * @see #sendOrderedBroadcastAsUser(Intent, UserHandle, String, + * BroadcastReceiver, Handler, int, String, Bundle) + * @hide + */ + @SuppressWarnings("HiddenAbstractMethod") + @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) + public void sendOrderedBroadcastAsUserMultiplePermissions(Intent intent, + UserHandle user, String[] receiverPermissions, int appOp, Bundle options, + BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, + String initialData, Bundle initialExtras) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * Version of * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, * Bundle)} that allows you to specify the App Op to enforce restrictions on which receivers @@ -2997,6 +3014,21 @@ public abstract class Context { } /** + * Like {@link #sendOrderedBroadcast(Intent, String, String, BroadcastReceiver, Handler, int, + * String, Bundle)}, but also allows specification of a list of multiple permissions. + * @hide + */ + @FlaggedApi(Flags.FLAG_ORDERED_BROADCAST_MULTIPLE_PERMISSIONS) + @SystemApi + public void sendOrderedBroadcastMultiplePermissions( + @NonNull Intent intent, @NonNull String[] receiverPermissions, + @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver, + @Nullable Handler scheduler, int initialCode, @Nullable String initialData, + @Nullable Bundle initialExtras, @Nullable Bundle options) { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } + + /** * <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the * Intent you are sending stays around after the broadcast is complete, * so that others can quickly retrieve that data through the return diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index a475c2925881..79fa6ea4d157 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -652,6 +652,16 @@ public class ContextWrapper extends Context { resultReceiver, scheduler, initialCode, initialData, initialExtras); } + /** @hide */ + @Override + public void sendOrderedBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, + @Nullable String[] receiverPermission, int appOp, @Nullable Bundle options, + @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler, + int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) { + mBase.sendOrderedBroadcastAsUserMultiplePermissions(intent, user, receiverPermission, appOp, + options, resultReceiver, scheduler, initialCode, initialData, initialExtras); + } + @Override public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent, @Nullable String receiverPermission, @Nullable String receiverAppOp, @@ -661,6 +671,17 @@ public class ContextWrapper extends Context { scheduler, initialCode, initialData, initialExtras); } + /** @hide */ + @Override + public void sendOrderedBroadcastMultiplePermissions( + @NonNull Intent intent, @NonNull String[] receiverPermissions, + @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver, + @Nullable Handler scheduler, int initialCode, @Nullable String initialData, + @Nullable Bundle initialExtras, @Nullable Bundle options) { + mBase.sendOrderedBroadcastMultiplePermissions(intent, receiverPermissions, receiverAppOp, + resultReceiver, scheduler, initialCode, initialData, initialExtras, options); + } + @Override public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent, int initialCode, @Nullable String receiverPermission, @Nullable String receiverAppOp, diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS index 51ad1519941b..43d3f5466ccf 100644 --- a/core/java/android/hardware/OWNERS +++ b/core/java/android/hardware/OWNERS @@ -5,7 +5,7 @@ michaelwr@google.com sumir@google.com # Camera -per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,zhijunhe@google.com,jchowdhary@google.com +per-file *Camera*=file:platform/frameworks/av:/camera/OWNERS # Sensor Privacy per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 334b2316b268..3e6bbf6cdd0c 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; 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.Intent; 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 @@ public class NetworkPolicyManager { * @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 @@ public class NetworkPolicyManager { * * @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 @@ public class NetworkPolicyManager { /** * 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 048c50eb0a19..48eb9680e647 100644 --- a/core/java/android/net/flags.aconfig +++ b/core/java/android/net/flags.aconfig @@ -25,3 +25,13 @@ flag { 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 c9f207cf26e8..50242bad191b 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -29,7 +29,7 @@ import java.io.FileDescriptor; * 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 @@ import java.io.FileDescriptor; * 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 @@ import java.io.FileDescriptor; * 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 @@ import java.io.FileDescriptor; * 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 @@ import java.io.FileDescriptor; * 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 @@ import java.io.FileDescriptor; * 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 @@ public interface IBinder { * 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 @@ public interface IBinder { * 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 @@ public interface IBinder { * 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 @@ public interface IBinder { /** * 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 @@ public interface IBinder { /** * 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 @@ public interface IBinder { * 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 @@ public interface IBinder { /** * 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 @@ public interface IBinder { /** * 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 @@ public interface IBinder { * 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 a49ee7d00751..0c34c6fea1d0 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -110,92 +110,6 @@ interface INetworkManagementService 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 0be2d3e30c33..e95c6a44c281 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -277,7 +277,7 @@ public final class ServiceManager { 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 @@ public final class ServiceManager { 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 7b91dd5822e7..6c9a5c7f9fff 100644 --- a/core/java/android/os/ServiceManagerNative.java +++ b/core/java/android/os/ServiceManagerNative.java @@ -58,12 +58,12 @@ class ServiceManagerProxy implements IServiceManager { } @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/os/flags.aconfig b/core/java/android/os/flags.aconfig index ca694579e9d0..200c1d8edafa 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -68,6 +68,14 @@ flag { } flag { + name: "ordered_broadcast_multiple_permissions" + is_exported: true + namespace: "bluetooth" + description: "Guards the Context.sendOrderedBroadcastMultiplePermissions API" + bug: "345802719" +} + +flag { name: "battery_saver_supported_check_api" namespace: "backstage_power" description: "Guards a new API in PowerManager to check if battery saver is supported or not." diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 38afb807dcf2..5e8d720cc943 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -83,3 +83,10 @@ flag { description: "Add a dump capability for attestation_verification service" bug: "335498868" } + +flag { + name: "should_trust_manager_listen_for_primary_auth" + namespace: "biometrics" + description: "Causes TrustManagerService to listen for credential attempts and ignore reports from upstream" + bug: "323086607" +} diff --git a/core/java/android/service/contextualsearch/OWNERS b/core/java/android/service/contextualsearch/OWNERS index 463adf48dd3e..b7238721bc60 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/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 327ebd07df1f..c9c2dcc2dd6f 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -536,7 +536,9 @@ public class DreamService extends Service implements Window.Callback { * @see View#findViewById(int) * @see DreamService#requireViewById(int) */ - /* TODO(b/347672184): Re-add @Nullable */ + // Strictly speaking this should be marked as @Nullable but the nullability of the return value + // is deliberately left unspecified as idiomatically correct code can make assumptions either + // way based on local context, e.g. layout specification. public <T extends View> T findViewById(@IdRes int id) { return getWindow().findViewById(id); } diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS index 0f2f8ad3d99e..32f482264103 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/util/StateSet.java b/core/java/android/util/StateSet.java index 16d6082649a7..17adb32fb846 100644 --- a/core/java/android/util/StateSet.java +++ b/core/java/android/util/StateSet.java @@ -288,6 +288,9 @@ public class StateSet { case R.attr.state_activated: sb.append("A "); break; + case R.attr.state_hovered: + sb.append("H "); + break; } } diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index 9099f9855eab..7eb6f2e2b331 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -284,7 +284,7 @@ public final class PointerIcon implements Parcelable { if (bitmap == null) { throw new IllegalArgumentException("bitmap must not be null"); } - validateHotSpot(bitmap, hotSpotX, hotSpotY); + validateHotSpot(bitmap, hotSpotX, hotSpotY, false /* isScaled */); PointerIcon icon = new PointerIcon(TYPE_CUSTOM); icon.mBitmap = bitmap; @@ -517,7 +517,9 @@ public final class PointerIcon implements Parcelable { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; final Bitmap bitmap = getBitmapFromDrawable(bitmapDrawable); - validateHotSpot(bitmap, hotSpotX, hotSpotY); + // The bitmap and hotspot are loaded from the context, which means it is implicitly scaled + // to the current display density, so treat this as a scaled icon when verifying hotspot. + validateHotSpot(bitmap, hotSpotX, hotSpotY, true /* isScaled */); // Set the properties now that we have successfully loaded the icon. mBitmap = bitmap; mHotSpotX = hotSpotX; @@ -531,11 +533,16 @@ public final class PointerIcon implements Parcelable { + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY + "}"; } - private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) { - if (hotSpotX < 0 || hotSpotX >= bitmap.getWidth()) { + private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY, + boolean isScaled) { + // Be more lenient when checking the hotspot for scaled icons to account for the restriction + // that bitmaps must have an integer size. + if (hotSpotX < 0 || (isScaled ? (int) hotSpotX > bitmap.getWidth() + : hotSpotX >= bitmap.getWidth())) { throw new IllegalArgumentException("x hotspot lies outside of the bitmap area"); } - if (hotSpotY < 0 || hotSpotY >= bitmap.getHeight()) { + if (hotSpotY < 0 || (isScaled ? (int) hotSpotY > bitmap.getHeight() + : hotSpotY >= bitmap.getHeight())) { throw new IllegalArgumentException("y hotspot lies outside of the bitmap area"); } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ba6d5df6494b..9aa723aa88e1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -27294,7 +27294,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return a view with given ID if found, or {@code null} otherwise * @see View#requireViewById(int) */ - /* TODO(b/347672184): Re-add @Nullable */ + // Strictly speaking this should be marked as @Nullable but the nullability of the return value + // is deliberately left unspecified as idiomatically correct code can make assumptions either + // way based on local context, e.g. layout specification. public final <T extends View> T findViewById(@IdRes int id) { if (id == NO_ID) { return null; diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index bfdcd5977cd7..50cf5a5fa975 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1712,7 +1712,9 @@ public abstract class Window { * @see View#findViewById(int) * @see Window#requireViewById(int) */ - /* TODO(b/347672184): Re-add @Nullable */ + // Strictly speaking this should be marked as @Nullable but the nullability of the return value + // is deliberately left unspecified as idiomatically correct code can make assumptions either + // way based on local context, e.g. layout specification. public <T extends View> T findViewById(@IdRes int id) { return getDecorView().findViewById(id); } diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS index e4b09524ede7..9ac273f515e7 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/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index f4ad487f48ac..19c6f51ff9a7 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -22,6 +22,8 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; +import static android.security.Flags.reportPrimaryAuthAttempts; +import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth; import android.annotation.IntDef; import android.annotation.NonNull; @@ -414,7 +416,9 @@ public class LockPatternUtils { return; } getDevicePolicyManager().reportFailedPasswordAttempt(userId); - getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); + if (!reportPrimaryAuthAttempts() || !shouldTrustManagerListenForPrimaryAuth()) { + getTrustManager().reportUnlockAttempt(/* authenticated= */ false, userId); + } } @UnsupportedAppUsage @@ -423,7 +427,9 @@ public class LockPatternUtils { return; } getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId); - getTrustManager().reportUnlockAttempt(true /* authenticated */, userId); + if (!reportPrimaryAuthAttempts() || !shouldTrustManagerListenForPrimaryAuth()) { + getTrustManager().reportUnlockAttempt(/* authenticated= */ true, userId); + } } public void reportPasswordLockout(int timeoutMs, int userId) { diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 52237989f059..9fecbd344908 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2703,12 +2703,11 @@ static jint android_media_AudioSystem_getMaxChannelCount(JNIEnv *env, jobject th } static jint android_media_AudioSystem_getMaxSampleRate(JNIEnv *env, jobject thiz) { - // see frameworks/av/services/audiopolicy/common/include/policy.h - return 192000; // SAMPLE_RATE_HZ_MAX (for API) + return SAMPLE_RATE_HZ_MAX; } static jint android_media_AudioSystem_getMinSampleRate(JNIEnv *env, jobject thiz) { - return 4000; // SAMPLE_RATE_HZ_MIN (for API) + return SAMPLE_RATE_HZ_MIN; } static std::vector<uid_t> convertJIntArrayToUidVector(JNIEnv *env, jintArray jArray) { diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp index d426f1240a7f..6c72544a7958 100644 --- a/core/jni/com_android_internal_content_FileSystemUtils.cpp +++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp @@ -87,9 +87,10 @@ bool punchHoles(const char *filePath, const uint64_t offset, 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 @@ bool punchHoles(const char *filePath, const uint64_t offset, 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 @@ bool punchHolesInZip(const char *filePath, uint64_t offset, uint16_t extraFieldL 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 @@ bool punchHolesInZip(const char *filePath, uint64_t offset, uint16_t extraFieldL 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 000000000000..1eefb3a3dc65 --- /dev/null +++ b/core/tests/coretests/src/android/animation/OWNERS @@ -0,0 +1 @@ +include /core/java/android/animation/OWNERS diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml index 78c88815b46c..297c490f4819 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="8" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="18"/> <application android:name="com.android.multidexlegacyandexception.TestApplication" diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/AndroidManifest.xml index 1a60c1e45f97..a2082680071a 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="8" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="18"/> <application android:name=".TestApplication" diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml index 35369c7da6a1..bb2a20157db9 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - <uses-sdk android:minSdkVersion="8" /> + <uses-sdk android:minSdkVersion="21" /> <instrumentation android:name="com.android.test.runner.MultiDexTestRunner" android:targetPackage="com.android.multidexlegacytestapp" /> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml index 1cadfcdf3b81..b96566cea3fa 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - <uses-sdk android:minSdkVersion="8" /> + <uses-sdk android:minSdkVersion="21" /> <instrumentation android:name="com.android.multidexlegacytestapp.test2.MultiDexAndroidJUnitRunner" android:targetPackage="com.android.multidexlegacytestapp" /> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/AndroidManifest.xml index e2fba4ef7741..c644c360f3ca 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - <uses-sdk android:minSdkVersion="9" /> + <uses-sdk android:minSdkVersion="21" /> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.android.framework.multidexlegacytestservices" /> diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml index 01285e77e3ff..f511c5fca8ce 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - <uses-sdk android:minSdkVersion="9" /> + <uses-sdk android:minSdkVersion="21" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml index 8c911c47dbdf..47302439ef24 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="9" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="18"/> <application android:name="androidx.multidex.MultiDexApplication" diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml index 1817e952ef7e..0bcf9feb7d1f 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionCode="2" android:versionName="2.0"> - <uses-sdk android:minSdkVersion="9" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="18"/> <application android:name="androidx.multidex.MultiDexApplication" diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml index c8a41bc43bea..5b7680db9d9b 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionCode="3" android:versionName="3.0"> - <uses-sdk android:minSdkVersion="9" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="18"/> <application android:name="androidx.multidex.MultiDexApplication" diff --git a/core/tests/resourceflaggingtests/OWNERS b/core/tests/resourceflaggingtests/OWNERS new file mode 100644 index 000000000000..10950a193b25 --- /dev/null +++ b/core/tests/resourceflaggingtests/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/RESOURCES_OWNERS diff --git a/data/etc/OWNERS b/data/etc/OWNERS index 701d145fe805..85dae631cac3 100644 --- a/data/etc/OWNERS +++ b/data/etc/OWNERS @@ -1,6 +1,5 @@ include /PACKAGE_MANAGER_OWNERS -alanstokes@google.com cbrubaker@google.com hackbod@android.com hackbod@google.com diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 65615e62c3df..7b96699f7f71 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -325,10 +325,12 @@ <!-- These are the standard packages that are allowed to always have internet access while in power save mode, even if they aren't in the foreground. --> <allow-in-power-save package="com.android.providers.downloads" /> + <allow-in-power-save package="com.android.rkpdapp" /> <!-- These are the standard packages that are allowed to always have internet access while in data mode, even if they aren't in the foreground. --> <allow-in-data-usage-save package="com.android.providers.downloads" /> + <allow-in-data-usage-save package="com.android.rkpdapp" /> <!-- This is a core platform component that needs to freely run in the background --> <allow-in-power-save package="com.android.cellbroadcastreceiver.module" /> diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java index 7c7cb18afc4d..9887c272e7f8 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.source.util.TreeScanner; 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.List; 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 @@ public final class RequiresPermissionChecker extends BugChecker 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 @@ public final class RequiresPermissionChecker extends BugChecker } } - 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 @@ public final class RequiresPermissionChecker extends BugChecker 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; - - @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); + 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(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 e53372d97f3d..05fde7c4fe57 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 @@ public class RequiresPermissionCheckerTest { " 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 efc4fb122435..9d622ffaf120 100644 --- a/errorprone/tests/res/android/content/Context.java +++ b/errorprone/tests/res/android/content/Context.java @@ -36,4 +36,15 @@ public class Context { 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 288396e60577..7ccea784754a 100644 --- a/errorprone/tests/res/android/content/Intent.java +++ b/errorprone/tests/res/android/content/Intent.java @@ -24,4 +24,8 @@ public class Intent { public Intent setAction(String action) { throw new UnsupportedOperationException(); } + + public Intent putExtra(String extra, int value) { + throw new UnsupportedOperationException(); + } } diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 4b367e0e5b4b..f9fd3694835e 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -66,6 +66,7 @@ import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import javax.security.auth.x500.X500Principal; @@ -376,6 +377,8 @@ public final class KeyChain { */ public static final int KEY_ATTESTATION_FAILURE = 4; + private static final int BIND_KEY_CHAIN_SERVICE_TIMEOUT_MS = 30 * 1000; + /** * Used by DPC or delegated app in * {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias} or @@ -1120,7 +1123,10 @@ public final class KeyChain { context.unbindService(keyChainServiceConnection); throw new AssertionError("could not bind to KeyChainService"); } - countDownLatch.await(); + if (!countDownLatch.await(BIND_KEY_CHAIN_SERVICE_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { + context.unbindService(keyChainServiceConnection); + throw new AssertionError("binding to KeyChainService timeout"); + } IKeyChainService service = keyChainService.get(); if (service != null) { return new KeyChainConnection(context, keyChainServiceConnection, service); 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 7ad68aac62c5..b01b2b7ad520 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/libs/androidfw/LocaleDataTables.cpp b/libs/androidfw/LocaleDataTables.cpp index b68143d82090..94351182871a 100644 --- a/libs/androidfw/LocaleDataTables.cpp +++ b/libs/androidfw/LocaleDataTables.cpp @@ -2451,10 +2451,10 @@ const struct { const char script[4]; const std::unordered_map<uint32_t, uint32_t>* map; } SCRIPT_PARENTS[] = { + {{'L', 'a', 't', 'n'}, &LATN_PARENTS}, {{'A', 'r', 'a', 'b'}, &ARAB_PARENTS}, {{'D', 'e', 'v', 'a'}, &DEVA_PARENTS}, {{'H', 'a', 'n', 't'}, &HANT_PARENTS}, - {{'L', 'a', 't', 'n'}, &LATN_PARENTS}, {{'~', '~', '~', 'B'}, &___B_PARENTS}, }; diff --git a/location/Android.bp b/location/Android.bp index 7f3442c47d1f..10ca97d74660 100644 --- a/location/Android.bp +++ b/location/Android.bp @@ -30,9 +30,6 @@ java_sdk_library { "app-compat-annotations", "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage ], - hidden_api_packages: [ - "com.android.internal.location", - ], aidl: { include_dirs: [ "frameworks/base/location/java", diff --git a/location/java/com/android/internal/location/package-info.java b/location/java/com/android/internal/location/package-info.java new file mode 100644 index 000000000000..25573c15ce59 --- /dev/null +++ b/location/java/com/android/internal/location/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Exclude from API surfaces + * + * @hide + */ +package com.android.internal.location; diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 293c561f166c..47adde49b86e 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -1636,7 +1636,8 @@ public class AudioSystem /** @hide */ public static final int FORCE_ENCODED_SURROUND_NEVER = 13; /** @hide */ public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14; /** @hide */ public static final int FORCE_ENCODED_SURROUND_MANUAL = 15; - /** @hide */ public static final int NUM_FORCE_CONFIG = 16; + /** @hide */ public static final int FORCE_BT_BLE = 16; + /** @hide */ public static final int NUM_FORCE_CONFIG = 17; /** @hide */ public static final int FORCE_DEFAULT = FORCE_NONE; /** @hide */ @@ -1658,6 +1659,7 @@ public class AudioSystem case FORCE_ENCODED_SURROUND_NEVER: return "FORCE_ENCODED_SURROUND_NEVER"; case FORCE_ENCODED_SURROUND_ALWAYS: return "FORCE_ENCODED_SURROUND_ALWAYS"; case FORCE_ENCODED_SURROUND_MANUAL: return "FORCE_ENCODED_SURROUND_MANUAL"; + case FORCE_BT_BLE: return "FORCE_BT_BLE"; default: return "unknown config (" + config + ")" ; } } diff --git a/media/tests/SoundPoolTest/AndroidManifest.xml b/media/tests/SoundPoolTest/AndroidManifest.xml index c18efa29462c..b24639ca2d63 100644 --- a/media/tests/SoundPoolTest/AndroidManifest.xml +++ b/media/tests/SoundPoolTest/AndroidManifest.xml @@ -12,6 +12,6 @@ </intent-filter> </activity> </application> - <uses-sdk android:minSdkVersion="8" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="8"/> </manifest> diff --git a/nfc/Android.bp b/nfc/Android.bp index 421f06d5cf2b..2a01b3fec088 100644 --- a/nfc/Android.bp +++ b/nfc/Android.bp @@ -59,9 +59,6 @@ java_sdk_library { "android.nfc", "com.android.nfc", ], - hidden_api_packages: [ - "com.android.nfc", - ], impl_library_visibility: [ "//frameworks/base:__subpackages__", "//cts/tests/tests/nfc", diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java index 8dd51b2b8d11..8de0c35ffa12 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java @@ -22,8 +22,6 @@ import static junit.framework.Assert.assertNull; import android.content.ContentResolver; import android.os.Bundle; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; @@ -73,24 +71,9 @@ public class DeviceConfigServiceTest { } /** - * Test that setting overrides are properly disabled when the flag is off. - */ - @Test - @RequiresFlagsDisabled("com.android.providers.settings.support_overrides") - public void testOverrideDisabled() throws IOException { - final String newValue = "value2"; - - executeShellCommand("device_config put " + sNamespace + " " + sKey + " " + sValue); - executeShellCommand("device_config override " + sNamespace + " " + sKey + " " + newValue); - String result = readShellCommandOutput("device_config get " + sNamespace + " " + sKey); - assertEquals(sValue + "\n", result); - } - - /** * Test that overrides are readable and can be cleared. */ @Test - @RequiresFlagsEnabled("com.android.providers.settings.support_overrides") public void testOverride() throws IOException { final String newValue = "value2"; 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 beb8ddef949d..24cbd1036770 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 @@ fun LazyGridItemScope.DraggableItem( alpha = itemAlpha } } else { - Modifier.animateItemPlacement() + Modifier.animateItem() } Box(modifier) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java index b4530ace68d6..ed7062b5a335 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java @@ -26,6 +26,7 @@ import android.content.res.Configuration; import android.util.Range; import android.view.WindowManager; +import com.android.internal.accessibility.common.MagnificationConstants; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.util.settings.SecureSettings; @@ -40,7 +41,8 @@ import com.android.systemui.util.settings.SecureSettings; public class MagnificationSettingsController implements ComponentCallbacks { // It should be consistent with the value defined in WindowMagnificationGestureHandler. - private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f); + private static final Range<Float> A11Y_ACTION_SCALE_RANGE = + new Range<>(1.0f, MagnificationConstants.SCALE_MAX_VALUE); private final Context mContext; diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp index 178102e2876d..33d3624d4522 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -16,6 +16,38 @@ filegroup { 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 @@ java_device_for_host { 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 index 331dbb19ca37..331dbb19ca37 100644 --- a/ravenwood/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt diff --git a/ravenwood/framework-minus-apex-ravenwood-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt index 371c3acab144..371c3acab144 100644 --- a/ravenwood/framework-minus-apex-ravenwood-policies.txt +++ b/ravenwood/texts/ravenwood-framework-policies.txt diff --git a/ravenwood/ravenwood-services-jarjar-rules.txt b/ravenwood/texts/ravenwood-services-jarjar-rules.txt index 8fdd3408f74d..8fdd3408f74d 100644 --- a/ravenwood/ravenwood-services-jarjar-rules.txt +++ b/ravenwood/texts/ravenwood-services-jarjar-rules.txt diff --git a/ravenwood/services.core-ravenwood-policies.txt b/ravenwood/texts/ravenwood-services-policies.txt index d8d563e05435..d8d563e05435 100644 --- a/ravenwood/services.core-ravenwood-policies.txt +++ b/ravenwood/texts/ravenwood-services-policies.txt diff --git a/ravenwood/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt index f64f26d7962a..f64f26d7962a 100644 --- a/ravenwood/ravenwood-standard-options.txt +++ b/ravenwood/texts/ravenwood-standard-options.txt diff --git a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java index e6055148867d..2009cd3d4527 100644 --- a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java +++ b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java @@ -659,6 +659,8 @@ class FlashNotificationsController { mIsTorchTouched = on; } catch (CameraAccessException e) { Log.e(LOG_TAG, "Failed to setTorchMode: " + e); + } catch (IllegalArgumentException e) { + Log.e(LOG_TAG, "Failed to setTorchMode: " + e); } } else { Log.e(LOG_TAG, "Can not use camera flash notification, please check CameraManager!"); diff --git a/services/core/java/com/android/server/CertBlacklister.java b/services/core/java/com/android/server/CertBlocklister.java index e726c6abfac3..9e23f884f4ba 100644 --- a/services/core/java/com/android/server/CertBlacklister.java +++ b/services/core/java/com/android/server/CertBlocklister.java @@ -16,37 +16,39 @@ package com.android.server; -import android.content.Context; import android.content.ContentResolver; +import android.content.Context; import android.database.ContentObserver; import android.os.Binder; import android.os.FileUtils; import android.provider.Settings; import android.util.Slog; +import libcore.io.IoUtils; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import libcore.io.IoUtils; - /** - * <p>CertBlacklister provides a simple mechanism for updating the platform denylists for SSL + * <p>CertBlocklister provides a simple mechanism for updating the platform denylists for SSL * certificate public keys and serial numbers. */ -public class CertBlacklister extends Binder { +public class CertBlocklister extends Binder { - private static final String TAG = "CertBlacklister"; + private static final String TAG = "CertBlocklister"; private static final String DENYLIST_ROOT = System.getenv("ANDROID_DATA") + "/misc/keychain/"; + /* For compatibility reasons, the name of these paths cannot be changed */ public static final String PUBKEY_PATH = DENYLIST_ROOT + "pubkey_blacklist.txt"; public static final String SERIAL_PATH = DENYLIST_ROOT + "serial_blacklist.txt"; - public static final String PUBKEY_BLACKLIST_KEY = "pubkey_blacklist"; - public static final String SERIAL_BLACKLIST_KEY = "serial_blacklist"; + /* For compatibility reasons, the name of these keys cannot be changed */ + public static final String PUBKEY_BLOCKLIST_KEY = "pubkey_blacklist"; + public static final String SERIAL_BLOCKLIST_KEY = "serial_blacklist"; - private static class BlacklistObserver extends ContentObserver { + private static class BlocklistObserver extends ContentObserver { private final String mKey; private final String mName; @@ -54,7 +56,7 @@ public class CertBlacklister extends Binder { private final File mTmpDir; private final ContentResolver mContentResolver; - public BlacklistObserver(String key, String name, String path, ContentResolver cr) { + BlocklistObserver(String key, String name, String path, ContentResolver cr) { super(null); mKey = key; mName = name; @@ -66,59 +68,61 @@ public class CertBlacklister extends Binder { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); - writeDenylist(); + new Thread("BlocklistUpdater") { + public void run() { + writeDenylist(); + } + }.start(); } public String getValue() { - return Settings.Secure.getString(mContentResolver, mKey); + return Settings.Secure.getStringForUser( + mContentResolver, mKey, mContentResolver.getUserId()); } private void writeDenylist() { - new Thread("BlacklistUpdater") { - public void run() { - synchronized(mTmpDir) { - String blacklist = getValue(); - if (blacklist != null) { - Slog.i(TAG, "Certificate blacklist changed, updating..."); - FileOutputStream out = null; - try { - // create a temporary file - File tmp = File.createTempFile("journal", "", mTmpDir); - // mark it -rw-r--r-- - tmp.setReadable(true, false); - // write to it - out = new FileOutputStream(tmp); - out.write(blacklist.getBytes()); - // sync to disk - FileUtils.sync(out); - // atomic rename - tmp.renameTo(new File(mPath)); - Slog.i(TAG, "Certificate blacklist updated"); - } catch (IOException e) { - Slog.e(TAG, "Failed to write blacklist", e); - } finally { - IoUtils.closeQuietly(out); - } - } - } + synchronized (mTmpDir) { + String blocklist = getValue(); + if (blocklist == null) { + return; } - }.start(); + if (mPath.equals(SERIAL_PATH)) { + Slog.w(TAG, "The certificate blocklist based on serials is deprecated. " + + "Please use the pubkey blocklist instead."); + } + Slog.i(TAG, "Certificate blocklist changed, updating..."); + FileOutputStream out = null; + try { + // Create a temporary file and rename it atomically. + File tmp = File.createTempFile("journal", "", mTmpDir); + tmp.setReadable(true /* readable */, false /* ownerOnly */); + out = new FileOutputStream(tmp); + out.write(blocklist.getBytes()); + FileUtils.sync(out); + tmp.renameTo(new File(mPath)); + Slog.i(TAG, "Certificate blocklist updated"); + } catch (IOException e) { + Slog.e(TAG, "Failed to write blocklist", e); + } finally { + IoUtils.closeQuietly(out); + } + } } } - public CertBlacklister(Context context) { + public CertBlocklister(Context context) { registerObservers(context.getContentResolver()); } - private BlacklistObserver buildPubkeyObserver(ContentResolver cr) { - return new BlacklistObserver(PUBKEY_BLACKLIST_KEY, + private BlocklistObserver buildPubkeyObserver(ContentResolver cr) { + return new BlocklistObserver(PUBKEY_BLOCKLIST_KEY, "pubkey", PUBKEY_PATH, cr); } - private BlacklistObserver buildSerialObserver(ContentResolver cr) { - return new BlacklistObserver(SERIAL_BLACKLIST_KEY, + private BlocklistObserver buildSerialObserver(ContentResolver cr) { + return new BlocklistObserver(SERIAL_BLOCKLIST_KEY, "serial", SERIAL_PATH, cr); @@ -127,16 +131,16 @@ public class CertBlacklister extends Binder { private void registerObservers(ContentResolver cr) { // set up the public key denylist observer cr.registerContentObserver( - Settings.Secure.getUriFor(PUBKEY_BLACKLIST_KEY), - true, - buildPubkeyObserver(cr) + Settings.Secure.getUriFor(PUBKEY_BLOCKLIST_KEY), + true, + buildPubkeyObserver(cr) ); // set up the serial number denylist observer cr.registerContentObserver( - Settings.Secure.getUriFor(SERIAL_BLACKLIST_KEY), - true, - buildSerialObserver(cr) + Settings.Secure.getUriFor(SERIAL_BLOCKLIST_KEY), + true, + buildSerialObserver(cr) ); } } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index c18bacb51671..3e61b1da2ecc 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -1010,6 +1010,7 @@ public class Watchdog implements Dumpable { // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the // kernel log doSysRq('w'); + doSysRq('m'); doSysRq('l'); } diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index f1eea728bedd..33ad49edfe87 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -787,6 +787,14 @@ public class AudioDeviceBroker { return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); } + /*package*/ boolean isBluetoothBleHeadsetActive() { + return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLE_HEADSET); + } + + /*package*/ boolean isBluetoothBleSpeakerActive() { + return isDeviceActiveForCommunication(AudioDeviceInfo.TYPE_BLE_SPEAKER); + } + /*package*/ boolean isDeviceConnected(@NonNull AudioDeviceAttributes device) { synchronized (mDeviceStateLock) { return mDeviceInventory.isDeviceConnected(device); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 3f49b90ad514..6787fa6a68c6 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -5665,16 +5665,25 @@ public class AudioService extends IAudioService.Stub || ringerMode == AudioManager.RINGER_MODE_SILENT; final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE && mDeviceBroker.isBluetoothScoActive(); - // Ask audio policy engine to force use Bluetooth SCO channel if needed + final boolean shouldRingBle = ringerMode == AudioManager.RINGER_MODE_VIBRATE + && (mDeviceBroker.isBluetoothBleHeadsetActive() + || mDeviceBroker.isBluetoothBleSpeakerActive()); + // Ask audio policy engine to force use Bluetooth SCO/BLE channel if needed final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid() + "/" + Binder.getCallingPid(); + int forceUse = AudioSystem.FORCE_NONE; + if (shouldRingSco) { + forceUse = AudioSystem.FORCE_BT_SCO; + } else if (shouldRingBle) { + forceUse = AudioSystem.FORCE_BT_BLE; + } sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING, - shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0); + forceUse, eventSource, 0); for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType); final boolean muteAllowedBySco = - !(shouldRingSco && streamType == AudioSystem.STREAM_RING); + !((shouldRingSco || shouldRingBle) && streamType == AudioSystem.STREAM_RING); final boolean shouldZenMute = isStreamAffectedByCurrentZen(streamType); final boolean shouldMute = shouldZenMute || (ringerModeMute && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco); diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 0f3f8073edcc..73ca6fbf8e5f 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -436,8 +436,13 @@ public class BtHelper { if (mBluetoothHeadset == null || mBluetoothHeadsetDevice == null) { return false; } - return mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) - == BluetoothHeadset.STATE_AUDIO_CONNECTED; + try { + return mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + == BluetoothHeadset.STATE_AUDIO_CONNECTED; + } catch (Exception e) { + Log.e(TAG, "Exception while getting audio state of " + mBluetoothHeadsetDevice, e); + } + return false; } // @GuardedBy("mDeviceBroker.mSetModeLock") @@ -1051,12 +1056,16 @@ public class BtHelper { } private void checkScoAudioState() { - if (mBluetoothHeadset != null - && mBluetoothHeadsetDevice != null - && mScoAudioState == SCO_STATE_INACTIVE - && mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) - != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + try { + if (mBluetoothHeadset != null + && mBluetoothHeadsetDevice != null + && mScoAudioState == SCO_STATE_INACTIVE + && mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } + } catch (Exception e) { + Log.e(TAG, "Exception while getting audio state of " + mBluetoothHeadsetDevice, e); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index f992a2399c61..88d43b20f5f2 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -655,7 +655,11 @@ public class HdmiCecNetwork { .setPortId(physicalAddressToPortId(physicalAddress)) .setDeviceType(type) .build(); - updateCecDevice(updatedDeviceInfo); + if (deviceInfo.getPhysicalAddress() != physicalAddress) { + addCecDevice(updatedDeviceInfo); + } else { + updateCecDevice(updatedDeviceInfo); + } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 1564b2f86218..0f7904e4ae0b 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -2949,6 +2949,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub hideStatusBarIconLocked(); mInFullscreenMode = false; mWindowManagerInternal.setDismissImeOnBackKeyPressed(false); + scheduleResetStylusHandwriting(); } @BinderThread diff --git a/services/core/java/com/android/server/location/altitude/AltitudeService.java b/services/core/java/com/android/server/location/altitude/AltitudeService.java index 289d4a25f208..96540c225e23 100644 --- a/services/core/java/com/android/server/location/altitude/AltitudeService.java +++ b/services/core/java/com/android/server/location/altitude/AltitudeService.java @@ -25,6 +25,7 @@ import android.frameworks.location.altitude.IAltitudeService; import android.location.Location; import android.location.altitude.AltitudeConverter; import android.os.RemoteException; +import android.util.Log; import com.android.server.SystemService; @@ -38,6 +39,8 @@ import java.io.IOException; */ public class AltitudeService extends IAltitudeService.Stub { + private static final String TAG = "AltitudeService"; + private final AltitudeConverter mAltitudeConverter = new AltitudeConverter(); private final Context mContext; @@ -59,6 +62,7 @@ public class AltitudeService extends IAltitudeService.Stub { try { mAltitudeConverter.addMslAltitudeToLocation(mContext, location); } catch (IOException e) { + Log.e(TAG, "", e); response.success = false; return response; } @@ -74,6 +78,7 @@ public class AltitudeService extends IAltitudeService.Stub { try { return mAltitudeConverter.getGeoidHeight(mContext, request); } catch (IOException e) { + Log.e(TAG, "", e); GetGeoidHeightResponse response = new GetGeoidHeightResponse(); response.success = false; return response; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index 17f2fcc5b9d8..bb35b378866b 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 @@ class LockSettingsShellCommand extends ShellCommand { 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 5ea3e70f7957..74f0d9cf3e39 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.annotations.GuardedBy; 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 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @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 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } 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); - } - } - return true; - } else { - final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); - if (changed) { - mDataSaverMode = enable; - } else { - Log.e(TAG, "setDataSaverMode(" + enable + "): failed to set iptables"); + // 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 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 079f3381162b..365c9b51a395 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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 d0c4e553ad8c..eef1e46b2ba6 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/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index c8bc56ce7dcd..9b0616a6b609 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -28,6 +28,7 @@ per-file CrossProfile* = file:MULTIUSER_AND_ENTERPRISE_OWNERS per-file RestrictionsSet.java = file:MULTIUSER_AND_ENTERPRISE_OWNERS per-file UserRestriction* = file:MULTIUSER_AND_ENTERPRISE_OWNERS per-file User* = file:/MULTIUSER_OWNERS +per-file BackgroundUser* = file:/MULTIUSER_OWNERS # security per-file KeySetHandle.java = cbrubaker@google.com, nnk@google.com diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index b3c31a9cfb64..a0ccc9d99d05 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -16,6 +16,7 @@ package com.android.server.trust; +import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth; import static android.service.trust.GrantTrustResult.STATUS_UNLOCKED_BY_GRANT; import static android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE; @@ -82,6 +83,9 @@ import com.android.internal.content.PackageMonitor; import com.android.internal.infra.AndroidFuture; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockSettingsInternal; +import com.android.internal.widget.LockSettingsStateListener; +import com.android.server.LocalServices; import com.android.server.SystemService; import org.xmlpull.v1.XmlPullParser; @@ -154,6 +158,7 @@ public class TrustManagerService extends SystemService { /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; + private final LockSettingsInternal mLockSettings; private final LockPatternUtils mLockPatternUtils; private final KeyStoreAuthorization mKeyStoreAuthorization; private final UserManager mUserManager; @@ -245,6 +250,20 @@ public class TrustManagerService extends SystemService { private final StrongAuthTracker mStrongAuthTracker; + // Used to subscribe to device credential auth attempts. + private final LockSettingsStateListener mLockSettingsStateListener = + new LockSettingsStateListener() { + @Override + public void onAuthenticationSucceeded(int userId) { + mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, 1, userId).sendToTarget(); + } + + @Override + public void onAuthenticationFailed(int userId) { + mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, 0, userId).sendToTarget(); + } + }; + private boolean mTrustAgentsCanRun = false; private int mCurrentUser = UserHandle.USER_SYSTEM; @@ -286,6 +305,7 @@ public class TrustManagerService extends SystemService { mHandler = createHandler(injector.getLooper()); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + mLockSettings = LocalServices.getService(LockSettingsInternal.class); mLockPatternUtils = injector.getLockPatternUtils(); mKeyStoreAuthorization = injector.getKeyStoreAuthorization(); mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper()); @@ -307,6 +327,9 @@ public class TrustManagerService extends SystemService { checkNewAgents(); mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); mReceiver.register(mContext); + if (shouldTrustManagerListenForPrimaryAuth()) { + mLockSettings.registerLockSettingsStateListener(mLockSettingsStateListener); + } mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker); mFingerprintManager = mContext.getSystemService(FingerprintManager.class); mFaceManager = mContext.getSystemService(FaceManager.class); diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index c778398342dc..00cdeb9047b5 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -1956,10 +1956,6 @@ static void handleInputChannelDisposed(JNIEnv* env, jobject /* inputChannelObj * const std::shared_ptr<InputChannel>& inputChannel, void* data) { NativeInputManager* im = static_cast<NativeInputManager*>(data); - - ALOGW("Input channel object '%s' was disposed without first being removed with " - "the input manager!", - inputChannel->getName().c_str()); im->removeInputChannel(inputChannel->getConnectionToken()); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 1c22087965b8..6e65a7453cf5 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 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 1000bfa5f6c9..dbd60c5af274 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 @@ class EnterpriseSpecificIdCalculator { 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 148054b31e89..d44bb5ae302c 100644 --- a/services/fakes/Android.bp +++ b/services/fakes/Android.bp @@ -16,5 +16,5 @@ filegroup { "java/**/*.java", ], path: "java", - visibility: ["//frameworks/base"], + visibility: ["//frameworks/base/ravenwood:__subpackages__"], } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index e19f08cb04a1..37f49e300766 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -2461,11 +2461,11 @@ public final class SystemServer implements Dumpable { t.traceEnd(); } - t.traceBegin("CertBlacklister"); + t.traceBegin("CertBlocklister"); try { - CertBlacklister blacklister = new CertBlacklister(context); + CertBlocklister blocklister = new CertBlocklister(context); } catch (Throwable e) { - reportWtf("starting CertBlacklister", e); + reportWtf("starting CertBlocklister", e); } t.traceEnd(); diff --git a/services/net/Android.bp b/services/net/Android.bp index 3d40f6445834..927146db0a24 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -21,6 +21,7 @@ java_library_static { ":services.net-sources", ], static_libs: [ + "modules-utils-build_system", "netd-client", "networkstack-client", "net-utils-services-common", diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index c76bcf804ee4..e6dac88f8a9e 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -398,17 +398,16 @@ public final class ProfcollectForwardingService extends SystemService { 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(() -> { try { - mIProfcollect.trace_system(traceTag); + 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/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp index 6d3b8ac45913..7eb3441a487a 100644 --- a/services/tests/mockingservicestests/Android.bp +++ b/services/tests/mockingservicestests/Android.bp @@ -53,6 +53,7 @@ android_test { "mockingservicestests-utils-mockito", "mockito-target-extended-minus-junit4", "platform-compat-test-rules", + "platform-parametric-runner-lib", "platform-test-annotations", "PlatformProperties", "service-blobstore", diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java index 7aec42b7eceb..1a398c5f1ec3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java @@ -16,6 +16,8 @@ package com.android.server.trust; +import static android.security.Flags.FLAG_SHOULD_TRUST_MANAGER_LISTEN_FOR_PRIMARY_AUTH; +import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth; import static android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; @@ -43,6 +45,7 @@ import static java.util.Collections.singleton; import android.Manifest; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.admin.DevicePolicyManager; @@ -72,6 +75,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.platform.test.flag.junit.FlagsParameterization; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.security.KeyStoreAuthorization; import android.service.trust.GrantTrustResult; @@ -90,6 +95,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils.StrongAuthTracker; import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.StrongAuthFlags; import com.android.internal.widget.LockSettingsInternal; +import com.android.internal.widget.LockSettingsStateListener; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -100,6 +106,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; @@ -111,7 +118,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import platform.test.runner.parameterized.ParameterizedAndroidJunit4; +import platform.test.runner.parameterized.Parameters; + +@RunWith(ParameterizedAndroidJunit4.class) public class TrustManagerServiceTest { + @Parameters(name = "{0}") + public static List<FlagsParameterization> getParams() { + return FlagsParameterization.allCombinationsOf( + FLAG_SHOULD_TRUST_MANAGER_LISTEN_FOR_PRIMARY_AUTH); + } @Rule public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) @@ -121,6 +137,9 @@ public class TrustManagerServiceTest { .build(); @Rule + public final SetFlagsRule mSetFlagsRule; + + @Rule public final MockContext mMockContext = new MockContext( ApplicationProvider.getApplicationContext()); @@ -142,6 +161,7 @@ public class TrustManagerServiceTest { private final Map<ComponentName, ITrustAgentService.Stub> mMockTrustAgents = new HashMap<>(); private @Mock ActivityManager mActivityManager; + private @Mock ActivityManagerInternal mActivityManagerInternal; private @Mock AlarmManager mAlarmManager; private @Mock BiometricManager mBiometricManager; private @Mock DevicePolicyManager mDevicePolicyManager; @@ -158,6 +178,11 @@ public class TrustManagerServiceTest { private HandlerThread mHandlerThread; private TrustManagerService mService; private ITrustManager mTrustManager; + private ActivityManagerInternal mPreviousActivityManagerInternal; + + public TrustManagerServiceTest(FlagsParameterization flags) { + mSetFlagsRule = new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT, flags); + } @Before public void setUp() throws Exception { @@ -210,6 +235,11 @@ public class TrustManagerServiceTest { mMockContext.setMockPackageManager(mPackageManager); mMockContext.addMockSystemService(UserManager.class, mUserManager); doReturn(mWindowManager).when(() -> WindowManagerGlobal.getWindowManagerService()); + mPreviousActivityManagerInternal = LocalServices.getService( + ActivityManagerInternal.class); + LocalServices.removeServiceForTest(ActivityManagerInternal.class); + LocalServices.addService(ActivityManagerInternal.class, + mActivityManagerInternal); LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class)); grantPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE); @@ -257,7 +287,14 @@ public class TrustManagerServiceTest { @After public void tearDown() { LocalServices.removeServiceForTest(SystemServiceManager.class); - mHandlerThread.quit(); + LocalServices.removeServiceForTest(ActivityManagerInternal.class); + if (mPreviousActivityManagerInternal != null) { + LocalServices.addService(ActivityManagerInternal.class, + mPreviousActivityManagerInternal); + } + if (mHandlerThread != null) { + mHandlerThread.quit(); + } } @Test @@ -579,11 +616,27 @@ public class TrustManagerServiceTest { } private void attemptSuccessfulUnlock(int userId) throws RemoteException { - mTrustManager.reportUnlockAttempt(/* successful= */ true, userId); + if (shouldTrustManagerListenForPrimaryAuth()) { + ArgumentCaptor<LockSettingsStateListener> captor = + ArgumentCaptor.forClass(LockSettingsStateListener.class); + verify(mLockSettingsInternal).registerLockSettingsStateListener(captor.capture()); + LockSettingsStateListener listener = captor.getValue(); + listener.onAuthenticationSucceeded(userId); + } else { + mTrustManager.reportUnlockAttempt(/* successful= */ true, userId); + } } private void attemptFailedUnlock(int userId) throws RemoteException { - mTrustManager.reportUnlockAttempt(/* successful= */ false, userId); + if (shouldTrustManagerListenForPrimaryAuth()) { + ArgumentCaptor<LockSettingsStateListener> captor = + ArgumentCaptor.forClass(LockSettingsStateListener.class); + verify(mLockSettingsInternal).registerLockSettingsStateListener(captor.capture()); + LockSettingsStateListener listener = captor.getValue(); + listener.onAuthenticationFailed(userId); + } else { + mTrustManager.reportUnlockAttempt(/* successful= */ false, userId); + } } private void grantRenewableTrust(ITrustAgentServiceCallback callback) throws RemoteException { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java index 1ad9ce02daa3..b8b191543e90 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -396,7 +396,7 @@ public class HdmiCecNetworkTest { } @Test - public void cecDevices_tracking_updatesPhysicalAddress() { + public void cecDevices_tracking_updatesPhysicalAddress_add() { int logicalAddress = Constants.ADDR_PLAYBACK_1; int initialPhysicalAddress = 0x1000; int updatedPhysicalAddress = 0x2000; @@ -415,11 +415,12 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo(updatedPhysicalAddress); assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(type); - // ADD for physical address first detected - // UPDATE for updating device with new physical address + // Handle case where PA is changed: Update CEC device information by calling + // addCecDevice(). assertThat(mDeviceEventListenerStatuses).containsExactly( HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, - HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); + HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE, + HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } @Test diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java index 49e9232ad535..14c9ea51c618 100644 --- a/telecomm/java/android/telecom/CallAudioState.java +++ b/telecomm/java/android/telecom/CallAudioState.java @@ -159,7 +159,7 @@ public final class CallAudioState implements Parcelable { @Override public String toString() { String bluetoothDeviceList = supportedBluetoothDevices.stream() - .map(BluetoothDevice::getAddress).collect(Collectors.joining(", ")); + .map(BluetoothDevice::toString).collect(Collectors.joining(", ")); return String.format(Locale.US, "[AudioState isMuted: %b, route: %s, supportedRouteMask: %s, " + diff --git a/telephony/OWNERS b/telephony/OWNERS index 7607c64150d8..92af034217a9 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -15,4 +15,4 @@ per-file CarrierConfigManager.java=set noparent 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 e29d321e5105..59766579eee2 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -51,10 +51,8 @@ java_sdk_library { 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/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index cf38bea55f2c..6bf7ff501217 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -479,6 +479,15 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public void sendOrderedBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, + String[] receiverPermissions, int appOp, Bundle options, + BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, + String initialData, Bundle initialExtras) { + throw new UnsupportedOperationException(); + } + @Override public void sendOrderedBroadcast(Intent intent, String receiverPermission, String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler, diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml index 3363af477dcb..27a8b2a0611b 100644 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml +++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/AndroidManifest.xml @@ -18,7 +18,7 @@ android:versionCode="1" android:versionName="1.0" > - <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="17" /> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="17" /> <instrumentation android:name="android.test.InstrumentationTestRunner" diff --git a/tests/HugeBackup/AndroidManifest.xml b/tests/HugeBackup/AndroidManifest.xml index 945e59bd36ed..92445dddef5a 100644 --- a/tests/HugeBackup/AndroidManifest.xml +++ b/tests/HugeBackup/AndroidManifest.xml @@ -25,7 +25,7 @@ android:versionName="1.0"> <!-- The backup/restore mechanism was introduced in API version 8 --> - <uses-sdk android:minSdkVersion="8" + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="8"/> <application android:label="Huge Backup" diff --git a/tests/TrustTests/AndroidManifest.xml b/tests/TrustTests/AndroidManifest.xml index 30cf345db34d..2f6c0dd14adc 100644 --- a/tests/TrustTests/AndroidManifest.xml +++ b/tests/TrustTests/AndroidManifest.xml @@ -78,6 +78,7 @@ <action android:name="android.service.trust.TrustAgentService" /> </intent-filter> </service> + <service android:name=".IsActiveUnlockRunningTrustAgent" android:exported="true" @@ -88,6 +89,16 @@ </intent-filter> </service> + <service + android:name=".UnlockAttemptTrustAgent" + android:exported="true" + android:label="Test Agent" + android:permission="android.permission.BIND_TRUST_AGENT"> + <intent-filter> + <action android:name="android.service.trust.TrustAgentService" /> + </intent-filter> + </service> + </application> <!-- self-instrumenting test package. --> diff --git a/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt b/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt new file mode 100644 index 000000000000..f9e004bcd29e --- /dev/null +++ b/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.trust.test + +import android.app.trust.TrustManager +import android.content.Context +import android.security.Flags.shouldTrustManagerListenForPrimaryAuth +import android.trust.BaseTrustAgentService +import android.trust.TrustTestActivity +import android.trust.test.lib.LockStateTrackingRule +import android.trust.test.lib.ScreenLockRule +import android.trust.test.lib.TestTrustListener +import android.trust.test.lib.TrustAgentRule +import android.util.Log +import androidx.test.core.app.ApplicationProvider.getApplicationContext +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain +import org.junit.runner.RunWith + +/** + * Test for the impacts of reporting unlock attempts. + * + * atest TrustTests:UnlockAttemptTest + */ +@RunWith(AndroidJUnit4::class) +class UnlockAttemptTest { + private val context = getApplicationContext<Context>() + private val trustManager = context.getSystemService(TrustManager::class.java) as TrustManager + private val userId = context.userId + private val activityScenarioRule = ActivityScenarioRule(TrustTestActivity::class.java) + private val screenLockRule = ScreenLockRule(requireStrongAuth = true) + private val lockStateTrackingRule = LockStateTrackingRule() + private val trustAgentRule = + TrustAgentRule<UnlockAttemptTrustAgent>(startUnlocked = false, startEnabled = false) + + private val trustListener = UnlockAttemptTrustListener() + private val agent get() = trustAgentRule.agent + + @get:Rule + val rule: RuleChain = + RuleChain.outerRule(activityScenarioRule) + .around(screenLockRule) + .around(lockStateTrackingRule) + .around(trustAgentRule) + + @Before + fun setUp() { + trustManager.registerTrustListener(trustListener) + } + + @Test + fun successfulUnlockAttempt_allowsTrustAgentToStart() = + runUnlockAttemptTest(enableAndVerifyTrustAgent = false, managingTrust = false) { + trustAgentRule.enableTrustAgent() + + triggerSuccessfulUnlock() + + trustAgentRule.verifyAgentIsRunning(MAX_WAIT_FOR_ENABLED_TRUST_AGENT_TO_START) + } + + @Test + fun successfulUnlockAttempt_notifiesTrustAgent() = + runUnlockAttemptTest(enableAndVerifyTrustAgent = true, managingTrust = true) { + val oldSuccessfulCount = agent.successfulUnlockCallCount + val oldFailedCount = agent.failedUnlockCallCount + + triggerSuccessfulUnlock() + + assertThat(agent.successfulUnlockCallCount).isEqualTo(oldSuccessfulCount + 1) + assertThat(agent.failedUnlockCallCount).isEqualTo(oldFailedCount) + } + + @Test + fun successfulUnlockAttempt_notifiesTrustListenerOfManagedTrust() = + runUnlockAttemptTest(enableAndVerifyTrustAgent = true, managingTrust = true) { + val oldTrustManagedChangedCount = trustListener.onTrustManagedChangedCount[userId] ?: 0 + + triggerSuccessfulUnlock() + + assertThat(trustListener.onTrustManagedChangedCount[userId] ?: 0).isEqualTo( + oldTrustManagedChangedCount + 1 + ) + } + + @Test + fun failedUnlockAttempt_doesNotAllowTrustAgentToStart() = + runUnlockAttemptTest(enableAndVerifyTrustAgent = false, managingTrust = false) { + trustAgentRule.enableTrustAgent() + + triggerFailedUnlock() + + trustAgentRule.ensureAgentIsNotRunning(MAX_WAIT_FOR_ENABLED_TRUST_AGENT_TO_START) + } + + @Test + fun failedUnlockAttempt_notifiesTrustAgent() = + runUnlockAttemptTest(enableAndVerifyTrustAgent = true, managingTrust = true) { + val oldSuccessfulCount = agent.successfulUnlockCallCount + val oldFailedCount = agent.failedUnlockCallCount + + triggerFailedUnlock() + + assertThat(agent.successfulUnlockCallCount).isEqualTo(oldSuccessfulCount) + assertThat(agent.failedUnlockCallCount).isEqualTo(oldFailedCount + 1) + } + + @Test + fun failedUnlockAttempt_doesNotNotifyTrustListenerOfManagedTrust() = + runUnlockAttemptTest(enableAndVerifyTrustAgent = true, managingTrust = true) { + val oldTrustManagedChangedCount = trustListener.onTrustManagedChangedCount[userId] ?: 0 + + triggerFailedUnlock() + + assertThat(trustListener.onTrustManagedChangedCount[userId] ?: 0).isEqualTo( + oldTrustManagedChangedCount + ) + } + + private fun runUnlockAttemptTest( + enableAndVerifyTrustAgent: Boolean, + managingTrust: Boolean, + testBlock: () -> Unit, + ) { + if (enableAndVerifyTrustAgent) { + Log.i(TAG, "Triggering successful unlock") + triggerSuccessfulUnlock() + Log.i(TAG, "Enabling and waiting for trust agent") + trustAgentRule.enableAndVerifyTrustAgentIsRunning( + MAX_WAIT_FOR_ENABLED_TRUST_AGENT_TO_START + ) + Log.i(TAG, "Managing trust: $managingTrust") + agent.setManagingTrust(managingTrust) + await() + } + testBlock() + } + + private fun triggerSuccessfulUnlock() { + screenLockRule.successfulScreenLockAttempt() + if (!shouldTrustManagerListenForPrimaryAuth()) { + trustAgentRule.reportSuccessfulUnlock() + } + await() + } + + private fun triggerFailedUnlock() { + screenLockRule.failedScreenLockAttempt() + if (!shouldTrustManagerListenForPrimaryAuth()) { + trustAgentRule.reportFailedUnlock() + } + await() + } + + companion object { + private const val TAG = "UnlockAttemptTest" + private fun await(millis: Long = 500) = Thread.sleep(millis) + private const val MAX_WAIT_FOR_ENABLED_TRUST_AGENT_TO_START = 10000L + } +} + +class UnlockAttemptTrustAgent : BaseTrustAgentService() { + var successfulUnlockCallCount: Long = 0 + private set + var failedUnlockCallCount: Long = 0 + private set + + override fun onUnlockAttempt(successful: Boolean) { + super.onUnlockAttempt(successful) + if (successful) { + successfulUnlockCallCount++ + } else { + failedUnlockCallCount++ + } + } +} + +private class UnlockAttemptTrustListener : TestTrustListener() { + var enabledTrustAgentsChangedCount = mutableMapOf<Int, Int>() + var onTrustManagedChangedCount = mutableMapOf<Int, Int>() + + override fun onEnabledTrustAgentsChanged(userId: Int) { + enabledTrustAgentsChangedCount.compute(userId) { _: Int, curr: Int? -> + if (curr == null) 0 else curr + 1 + } + } + + data class TrustChangedParams( + val enabled: Boolean, + val newlyUnlocked: Boolean, + val userId: Int, + val flags: Int, + val trustGrantedMessages: MutableList<String>? + ) + + val onTrustChangedCalls = mutableListOf<TrustChangedParams>() + + override fun onTrustChanged( + enabled: Boolean, + newlyUnlocked: Boolean, + userId: Int, + flags: Int, + trustGrantedMessages: MutableList<String> + ) { + onTrustChangedCalls += TrustChangedParams( + enabled, newlyUnlocked, userId, flags, trustGrantedMessages + ) + } + + override fun onTrustManagedChanged(enabled: Boolean, userId: Int) { + onTrustManagedChangedCount.compute(userId) { _: Int, curr: Int? -> + if (curr == null) 0 else curr + 1 + } + } +} diff --git a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt index f1edca3ff86e..1ccdcc623c5b 100644 --- a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt @@ -24,6 +24,8 @@ import androidx.test.core.app.ApplicationProvider.getApplicationContext import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import androidx.test.uiautomator.UiDevice import com.android.internal.widget.LockPatternUtils +import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED +import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN import com.android.internal.widget.LockscreenCredential import com.google.common.truth.Truth.assertWithMessage import org.junit.rules.TestRule @@ -32,13 +34,18 @@ import org.junit.runners.model.Statement /** * Sets a screen lock on the device for the duration of the test. + * + * @param requireStrongAuth Whether a strong auth is required at the beginning. + * If true, trust agents will not be available until the user verifies their credentials. */ -class ScreenLockRule : TestRule { +class ScreenLockRule(val requireStrongAuth: Boolean = false) : TestRule { private val context: Context = getApplicationContext() + private val userId = context.userId private val uiDevice = UiDevice.getInstance(getInstrumentation()) private val windowManager = checkNotNull(WindowManagerGlobal.getWindowManagerService()) private val lockPatternUtils = LockPatternUtils(context) private var instantLockSavedValue = false + private var strongAuthSavedValue: Int = 0 override fun apply(base: Statement, description: Description) = object : Statement() { override fun evaluate() { @@ -46,10 +53,12 @@ class ScreenLockRule : TestRule { dismissKeyguard() setScreenLock() setLockOnPowerButton() + configureStrongAuthState() try { base.evaluate() } finally { + restoreStrongAuthState() removeScreenLock() revertLockOnPowerButton() dismissKeyguard() @@ -57,6 +66,22 @@ class ScreenLockRule : TestRule { } } + private fun configureStrongAuthState() { + strongAuthSavedValue = lockPatternUtils.getStrongAuthForUser(userId) + if (requireStrongAuth) { + Log.d(TAG, "Triggering strong auth due to simulated lockdown") + lockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, userId) + wait("strong auth required after lockdown") { + lockPatternUtils.getStrongAuthForUser(userId) == + STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN + } + } + } + + private fun restoreStrongAuthState() { + lockPatternUtils.requireStrongAuth(strongAuthSavedValue, userId) + } + private fun verifyNoScreenLockAlreadySet() { assertWithMessage("Screen Lock must not already be set on device") .that(lockPatternUtils.isSecure(context.userId)) @@ -82,6 +107,22 @@ class ScreenLockRule : TestRule { } } + fun successfulScreenLockAttempt() { + lockPatternUtils.verifyCredential(LockscreenCredential.createPin(PIN), context.userId, 0) + lockPatternUtils.userPresent(context.userId) + wait("strong auth not required") { + lockPatternUtils.getStrongAuthForUser(context.userId) == STRONG_AUTH_NOT_REQUIRED + } + } + + fun failedScreenLockAttempt() { + lockPatternUtils.verifyCredential( + LockscreenCredential.createPin(WRONG_PIN), + context.userId, + 0 + ) + } + private fun setScreenLock() { lockPatternUtils.setLockCredential( LockscreenCredential.createPin(PIN), @@ -121,5 +162,6 @@ class ScreenLockRule : TestRule { companion object { private const val TAG = "ScreenLockRule" private const val PIN = "0000" + private const val WRONG_PIN = "0001" } } diff --git a/tests/TrustTests/src/android/trust/test/lib/TrustAgentRule.kt b/tests/TrustTests/src/android/trust/test/lib/TrustAgentRule.kt index 18bc029b6845..404c6d968b3a 100644 --- a/tests/TrustTests/src/android/trust/test/lib/TrustAgentRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/TrustAgentRule.kt @@ -20,14 +20,15 @@ import android.app.trust.TrustManager import android.content.ComponentName import android.content.Context import android.trust.BaseTrustAgentService +import android.trust.test.lib.TrustAgentRule.Companion.invoke import android.util.Log import androidx.test.core.app.ApplicationProvider.getApplicationContext import com.android.internal.widget.LockPatternUtils import com.google.common.truth.Truth.assertWithMessage +import kotlin.reflect.KClass import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement -import kotlin.reflect.KClass /** * Enables a trust agent and causes the system service to bind to it. @@ -37,7 +38,9 @@ import kotlin.reflect.KClass * @constructor Creates the rule. Do not use; instead, use [invoke]. */ class TrustAgentRule<T : BaseTrustAgentService>( - private val serviceClass: KClass<T> + private val serviceClass: KClass<T>, + private val startUnlocked: Boolean, + private val startEnabled: Boolean, ) : TestRule { private val context: Context = getApplicationContext() private val trustManager = context.getSystemService(TrustManager::class.java) as TrustManager @@ -48,11 +51,18 @@ class TrustAgentRule<T : BaseTrustAgentService>( override fun apply(base: Statement, description: Description) = object : Statement() { override fun evaluate() { verifyTrustServiceRunning() - unlockDeviceWithCredential() - enableTrustAgent() + if (startUnlocked) { + reportSuccessfulUnlock() + } else { + Log.i(TAG, "Trust manager not starting in unlocked state") + } try { - verifyAgentIsRunning() + if (startEnabled) { + enableAndVerifyTrustAgentIsRunning() + } else { + Log.i(TAG, "Trust agent ${serviceClass.simpleName} not enabled") + } base.evaluate() } finally { disableTrustAgent() @@ -64,12 +74,22 @@ class TrustAgentRule<T : BaseTrustAgentService>( assertWithMessage("Trust service is not running").that(trustManager).isNotNull() } - private fun unlockDeviceWithCredential() { - Log.d(TAG, "Unlocking device with credential") + fun reportSuccessfulUnlock() { + Log.i(TAG, "Reporting successful unlock") trustManager.reportUnlockAttempt(true, context.userId) } - private fun enableTrustAgent() { + fun reportFailedUnlock() { + Log.i(TAG, "Reporting failed unlock") + trustManager.reportUnlockAttempt(false, context.userId) + } + + fun enableAndVerifyTrustAgentIsRunning(maxWait: Long = 30000L) { + enableTrustAgent() + verifyAgentIsRunning(maxWait) + } + + fun enableTrustAgent() { val componentName = ComponentName(context, serviceClass.java) val userId = context.userId Log.i(TAG, "Enabling trust agent ${componentName.flattenToString()} for user $userId") @@ -79,12 +99,18 @@ class TrustAgentRule<T : BaseTrustAgentService>( lockPatternUtils.setEnabledTrustAgents(agents, userId) } - private fun verifyAgentIsRunning() { - wait("${serviceClass.simpleName} to be running") { + fun verifyAgentIsRunning(maxWait: Long = 30000L) { + wait("${serviceClass.simpleName} to be running", maxWait) { BaseTrustAgentService.instance(serviceClass) != null } } + fun ensureAgentIsNotRunning(window: Long = 30000L) { + ensure("${serviceClass.simpleName} is not running", window) { + BaseTrustAgentService.instance(serviceClass) == null + } + } + private fun disableTrustAgent() { val componentName = ComponentName(context, serviceClass.java) val userId = context.userId @@ -97,13 +123,23 @@ class TrustAgentRule<T : BaseTrustAgentService>( companion object { /** - * Creates a new rule for the specified agent class. Example usage: + * Creates a new rule for the specified agent class. Starts with the device unlocked and + * the trust agent enabled. Example usage: * ``` * @get:Rule val rule = TrustAgentRule<MyTestAgent>() * ``` + * + * Also supports setting different device lock and trust agent enablement states: + * ``` + * @get:Rule val rule = TrustAgentRule<MyTestAgent>(startUnlocked = false, startEnabled = false) + * ``` */ - inline operator fun <reified T : BaseTrustAgentService> invoke() = - TrustAgentRule(T::class) + inline operator fun <reified T : BaseTrustAgentService> invoke( + startUnlocked: Boolean = true, + startEnabled: Boolean = true, + ) = + TrustAgentRule(T::class, startUnlocked, startEnabled) + private const val TAG = "TrustAgentRule" } diff --git a/tests/TrustTests/src/android/trust/test/lib/utils.kt b/tests/TrustTests/src/android/trust/test/lib/Utils.kt index e047202f6740..3b32b47a6160 100644 --- a/tests/TrustTests/src/android/trust/test/lib/utils.kt +++ b/tests/TrustTests/src/android/trust/test/lib/Utils.kt @@ -39,7 +39,7 @@ internal fun wait( ) { var waited = 0L var count = 0 - while (!conditionFunction.invoke(count)) { + while (!conditionFunction(count)) { assertWithMessage("Condition exceeded maximum wait time of $maxWait ms: $description") .that(waited <= maxWait) .isTrue() @@ -49,3 +49,34 @@ internal fun wait( Thread.sleep(rate) } } + +/** + * Ensures that [conditionFunction] is true with a failed assertion if it is not within [window] + * ms. + * + * The condition function can perform additional logic (for example, logging or attempting to make + * the condition become true). + * + * @param conditionFunction function which takes the attempt count & returns whether the condition + * is met + */ +internal fun ensure( + description: String? = null, + window: Long = 30000L, + rate: Long = 50L, + conditionFunction: (count: Int) -> Boolean +) { + var waited = 0L + var count = 0 + while (waited <= window) { + assertWithMessage("Condition failed within $window ms: $description").that( + conditionFunction( + count + ) + ).isTrue() + waited += rate + count++ + Log.i(TAG, "Ensuring $description ($waited/$window) #$count") + Thread.sleep(rate) + } +} diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 031dd5bb139c..9b8c3b3d549c 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -836,6 +836,28 @@ int CompileCommand::Action(const std::vector<std::string>& args) { 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 61c5b60adb76..70c8791524c8 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 @@ struct CompileOptions { 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 @@ class CompileCommand : public Command { "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 @@ class CompileCommand : public Command { 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 8fe414f4f660..2f17853718ec 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -332,8 +332,9 @@ class LinkCommand : public Command { 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 678d84628015..7739171b347f 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -128,7 +128,7 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, 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 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, 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 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, } } - 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 9ece5dd4d720..6b8813b34082 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 723d87ed0af3..78183409ad8f 100644 --- a/tools/aapt2/cmd/Util_test.cpp +++ b/tools/aapt2/cmd/Util_test.cpp @@ -383,21 +383,25 @@ TEST(UtilTest, ParseFeatureFlagsParameter_InvalidValue) { 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 fdf3f74d4e18..9d40db521e13 100644 --- a/tools/aapt2/link/FeatureFlagsFilter.cpp +++ b/tools/aapt2/link/FeatureFlagsFilter.cpp @@ -63,12 +63,11 @@ class FlagsVisitor : public xml::Visitor { 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 53086cc30f18..2db2899e716c 100644 --- a/tools/aapt2/link/FeatureFlagsFilter_test.cpp +++ b/tools/aapt2/link/FeatureFlagsFilter_test.cpp @@ -48,7 +48,7 @@ TEST(FeatureFlagsFilterTest, NoFeatureFlagAttributes) { <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 @@ TEST(FeatureFlagsFilterTest, RemoveElementWithDisabledFlag) { <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 @@ TEST(FeatureFlagsFilterTest, RemoveElementWithNegatedEnabledFlag) { <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 @@ TEST(FeatureFlagsFilterTest, KeepElementWithEnabledFlag) { <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 @@ TEST(FeatureFlagsFilterTest, SideBySideEnabledAndDisabled) { <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 @@ TEST(FeatureFlagsFilterTest, RemoveDeeplyNestedElement) { </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 @@ TEST(FeatureFlagsFilterTest, KeepDeeplyNestedElement) { </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 @@ TEST(FeatureFlagsFilterTest, FailOnEmptyFeatureFlagAttribute) { <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 @@ TEST(FeatureFlagsFilterTest, FailOnFlagWithNoGivenValue) { <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 @@ TEST(FeatureFlagsFilterTest, FailOnUnrecognizedFlag) { <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 @@ TEST(FeatureFlagsFilterTest, FailOnMultipleValidationErrors) { <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 @@ TEST(FeatureFlagsFilterTest, OptionRemoveDisabledElementsIsFalse) { <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 @@ TEST(FeatureFlagsFilterTest, OptionFlagsMustHaveValueIsFalse) { <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 @@ TEST(FeatureFlagsFilterTest, OptionFailOnUnrecognizedFlagsIsFalse) { <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()); diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp index 02e4beaed949..8ae55b8868c3 100644 --- a/tools/aapt2/util/Files.cpp +++ b/tools/aapt2/util/Files.cpp @@ -189,7 +189,7 @@ void AppendPath(std::string* base, StringPiece part) { base->append(part.data(), part.size()); } -std::string BuildPath(std::vector<const StringPiece>&& args) { +std::string BuildPath(const std::vector<StringPiece>& args) { if (args.empty()) { return ""; } diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h index 42eeaf2d2e2a..c1a42446ec3b 100644 --- a/tools/aapt2/util/Files.h +++ b/tools/aapt2/util/Files.h @@ -60,7 +60,7 @@ FileType GetFileType(const std::string& path); void AppendPath(std::string* base, android::StringPiece part); // Concatenates the list of paths and separates each part with the directory separator. -std::string BuildPath(std::vector<const android::StringPiece>&& args); +std::string BuildPath(const std::vector<android::StringPiece>& args); // Makes all the directories in `path`. The last element in the path is interpreted as a directory. bool mkdirs(const std::string& path); diff --git a/tools/lint/fix/README.md b/tools/lint/fix/README.md index a5ac2be1c18a..18bda9287a50 100644 --- a/tools/lint/fix/README.md +++ b/tools/lint/fix/README.md @@ -6,7 +6,7 @@ Inspiration: go/refactor-the-platform-with-lint\ It's a python script that runs the framework linter, and then (optionally) copies modified files back into the source tree.\ -Why python, you ask? Because python is cool ¯\_(ツ)_/¯. +Why python, you ask? Because python is cool ¯\\\_(ツ)\_/¯. Incidentally, this exposes a much simpler way to run individual lint checks against individual modules, so it's useful beyond applying fixes. @@ -15,7 +15,7 @@ against individual modules, so it's useful beyond applying fixes. Lint is not allowed to modify source files directly via lint's `--apply-suggestions` flag. As a compromise, soong zips up the (potentially) modified sources and leaves them in an intermediate -directory. This script runs the lint, unpacks those files, and copies them back into the tree. +directory. This script runs the lint, unpacks those files, and copies them back into the tree. ## How do I run it? **WARNING: You probably want to commit/stash any changes to your working tree before doing this...** |