diff options
508 files changed, 7007 insertions, 2059 deletions
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb index e89809138548..e8e7ec901785 100644 --- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb +++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShimPriv_apk.asciipb @@ -1,6 +1,6 @@ drops { android_build_drop { - build_id: "9653376" + build_id: "11947186" target: "CtsShim" source_file: "aosp_riscv64/CtsShimPriv.apk" } @@ -8,7 +8,7 @@ drops { version: "" version_group: "" git_project: "platform/frameworks/base" - git_branch: "master" + git_branch: "main" transform: TRANSFORM_NONE transform_options { } diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb index 04092366c257..6113b6a6dc8f 100644 --- a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb +++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__riscv64_CtsShim_apk.asciipb @@ -1,6 +1,6 @@ drops { android_build_drop { - build_id: "9653376" + build_id: "11947186" target: "CtsShim" source_file: "aosp_riscv64/CtsShim.apk" } @@ -8,7 +8,7 @@ drops { version: "" version_group: "" git_project: "platform/frameworks/base" - git_branch: "master" + git_branch: "main" transform: TRANSFORM_NONE transform_options { } diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp index e092499cb41f..65bc8ccd12f8 100644 --- a/apct-tests/perftests/core/Android.bp +++ b/apct-tests/perftests/core/Android.bp @@ -44,6 +44,7 @@ android_test { "apct-perftests-resources-manager-apps", "apct-perftests-utils", "collector-device-lib", + "conscrypt-test-support", "compatibility-device-util-axt", "junit", "junit-params", diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/BufferType.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/BufferType.java new file mode 100644 index 000000000000..bdc2a829a95b --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/BufferType.java @@ -0,0 +1,48 @@ +/* + * 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 java.nio.ByteBuffer; +import javax.net.ssl.SSLEngine; + +/** + * Enumeration that provides allocation of direct or heap buffers. + */ +@SuppressWarnings("unused") +public enum BufferType { + HEAP { + @Override + ByteBuffer newBuffer(int size) { + return ByteBuffer.allocate(size); + } + }, + DIRECT { + @Override + ByteBuffer newBuffer(int size) { + return ByteBuffer.allocateDirect(size); + } + }; + + abstract ByteBuffer newBuffer(int size); + + ByteBuffer newApplicationBuffer(SSLEngine engine) { + return newBuffer(engine.getSession().getApplicationBufferSize()); + } + + ByteBuffer newPacketBuffer(SSLEngine engine) { + return newBuffer(engine.getSession().getPacketBufferSize()); + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java new file mode 100644 index 000000000000..c69ae39846bd --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2016 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 android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import androidx.test.filters.LargeTest; + +import org.conscrypt.TestUtils; + +import java.nio.ByteBuffer; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Benchmark for comparing cipher encrypt performance. + */ +@RunWith(JUnitParamsRunner.class) +@LargeTest +public final class CipherEncryptPerfTest { + + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + public enum BufferType { + ARRAY, + HEAP_HEAP, + HEAP_DIRECT, + DIRECT_DIRECT, + DIRECT_HEAP + } + + private enum MyCipherFactory implements CipherFactory { + JDK { + @Override + public Cipher newCipher(String transformation) + throws NoSuchPaddingException, NoSuchAlgorithmException { + return Cipher.getInstance(transformation); + } + }, + CONSCRYPT { + @Override + public Cipher newCipher(String transformation) + throws NoSuchPaddingException, NoSuchAlgorithmException { + return Cipher.getInstance(transformation, TestUtils.getConscryptProvider()); + } + }; + } + + private class Config { + BufferType b_bufferType; + CipherFactory c_provider; + Transformation a_tx; + Config(BufferType bufferType, CipherFactory cipherFactory, Transformation transformation) { + b_bufferType = bufferType; + c_provider = cipherFactory; + a_tx = transformation; + } + public BufferType bufferType() { + return b_bufferType; + } + + public CipherFactory cipherFactory() { + return c_provider; + } + + public Transformation transformation() { + return a_tx; + } + } + + 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)}, + }; + } + + private EncryptStrategy encryptStrategy; + + @Test + @Parameters(method = "getParams") + public void encrypt(Config config) throws Exception { + switch (config.bufferType()) { + case ARRAY: + encryptStrategy = new ArrayStrategy(config); + break; + default: + encryptStrategy = new ByteBufferStrategy(config); + break; + } + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + encryptStrategy.encrypt(); + } + } + + private static abstract class EncryptStrategy { + private final Key key; + final Cipher cipher; + final int outputSize; + + EncryptStrategy(Config config) throws Exception { + Transformation tx = config.transformation(); + key = tx.newEncryptKey(); + cipher = config.cipherFactory().newCipher(tx.toFormattedString()); + initCipher(); + + int messageSize = messageSize(tx.toFormattedString()); + outputSize = cipher.getOutputSize(messageSize); + } + + final void initCipher() throws Exception { + cipher.init(Cipher.ENCRYPT_MODE, key); + } + + final int messageSize(String transformation) throws Exception { + Cipher conscryptCipher = Cipher.getInstance( + transformation, TestUtils.getConscryptProvider()); + conscryptCipher.init(Cipher.ENCRYPT_MODE, key); + return conscryptCipher.getBlockSize() > 0 ? + conscryptCipher.getBlockSize() : 128; + } + + final byte[] newMessage() { + return TestUtils.newTextMessage(cipher.getBlockSize()); + } + + abstract int encrypt() throws Exception; + } + + private static final class ArrayStrategy extends EncryptStrategy { + private final byte[] plainBytes; + private final byte[] cipherBytes; + + ArrayStrategy(Config config) throws Exception { + super(config); + + plainBytes = newMessage(); + cipherBytes = new byte[outputSize]; + } + + @Override + int encrypt() throws Exception { + initCipher(); + return cipher.doFinal(plainBytes, 0, plainBytes.length, cipherBytes, 0); + } + } + + private static final class ByteBufferStrategy extends EncryptStrategy { + private final ByteBuffer input; + private final ByteBuffer output; + + ByteBufferStrategy(Config config) throws Exception { + super(config); + + switch (config.bufferType()) { + case HEAP_HEAP: + input = ByteBuffer.wrap(newMessage()); + output = ByteBuffer.allocate(outputSize); + break; + case HEAP_DIRECT: + input = ByteBuffer.wrap(newMessage()); + output = ByteBuffer.allocateDirect(outputSize); + break; + case DIRECT_DIRECT: + input = toDirect(newMessage()); + output = ByteBuffer.allocateDirect(outputSize); + break; + case DIRECT_HEAP: + input = toDirect(newMessage()); + output = ByteBuffer.allocate(outputSize); + break; + default: { + throw new IllegalStateException( + "Unexpected buffertype: " + config.bufferType()); + } + } + } + + @Override + int encrypt() throws Exception { + initCipher(); + input.position(0); + output.clear(); + return cipher.doFinal(input, output); + } + + private static ByteBuffer toDirect(byte[] data) { + ByteBuffer buffer = ByteBuffer.allocateDirect(data.length); + buffer.put(data); + buffer.flip(); + return buffer; + } + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherFactory.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherFactory.java new file mode 100644 index 000000000000..f8a3d5f2ed04 --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherFactory.java @@ -0,0 +1,27 @@ +/* + * 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 java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +/** + * Factory for {@link Cipher} instances. + */ +public interface CipherFactory { + Cipher newCipher(String transformation) throws NoSuchPaddingException, NoSuchAlgorithmException; +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientEndpoint.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientEndpoint.java new file mode 100644 index 000000000000..1a7258a802df --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientEndpoint.java @@ -0,0 +1,110 @@ +/* + * 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 java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.SocketException; +import java.nio.channels.ClosedChannelException; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import org.conscrypt.ChannelType; + +/** + * Client-side endpoint. Provides basic services for sending/receiving messages from the client + * socket. + */ +final class ClientEndpoint { + private final SSLSocket socket; + private InputStream input; + private OutputStream output; + + ClientEndpoint(SSLSocketFactory socketFactory, ChannelType channelType, int port, + String[] protocols, String[] ciphers) throws IOException { + socket = channelType.newClientSocket(socketFactory, InetAddress.getLoopbackAddress(), port); + socket.setEnabledProtocols(protocols); + socket.setEnabledCipherSuites(ciphers); + } + + void start() { + try { + socket.startHandshake(); + input = socket.getInputStream(); + output = socket.getOutputStream(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + void stop() { + try { + socket.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + int readMessage(byte[] buffer) { + try { + int totalBytesRead = 0; + while (totalBytesRead < buffer.length) { + int remaining = buffer.length - totalBytesRead; + int bytesRead = input.read(buffer, totalBytesRead, remaining); + if (bytesRead == -1) { + break; + } + totalBytesRead += bytesRead; + } + return totalBytesRead; + } catch (SSLException e) { + if (e.getCause() instanceof EOFException) { + return -1; + } + throw new RuntimeException(e); + } catch (ClosedChannelException e) { + // Thrown for channel-based sockets. Just treat like EOF. + return -1; + } catch (SocketException e) { + // The socket was broken. Just treat like EOF. + return -1; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + void sendMessage(byte[] data) { + try { + output.write(data); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + void flush() { + try { + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java new file mode 100644 index 000000000000..dd9f4eb7e8d3 --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2016 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.ChannelType; +import org.conscrypt.TestUtils; +import static org.conscrypt.TestUtils.getCommonProtocolSuites; +import static org.conscrypt.TestUtils.newTextMessage; +import static org.junit.Assert.assertEquals; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import androidx.test.filters.LargeTest; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.SocketException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import android.conscrypt.ServerEndpoint.MessageProcessor; + +/** + * Benchmark for comparing performance of server socket implementations. + */ +@RunWith(JUnitParamsRunner.class) +@LargeTest +public final class ClientSocketPerfTest { + + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + /** + * Provider for the test configuration + */ + private class Config { + EndpointFactory a_clientFactory; + EndpointFactory b_serverFactory; + int c_messageSize; + String d_cipher; + ChannelType e_channelType; + PerfTestProtocol f_protocol; + Config(EndpointFactory clientFactory, + EndpointFactory serverFactory, + int messageSize, + String cipher, + ChannelType channelType, + PerfTestProtocol protocol) { + a_clientFactory = clientFactory; + b_serverFactory = serverFactory; + c_messageSize = messageSize; + d_cipher = cipher; + e_channelType = channelType; + f_protocol = protocol; + } + public EndpointFactory clientFactory() { + return a_clientFactory; + } + + public EndpointFactory serverFactory() { + return b_serverFactory; + } + + public int messageSize() { + return c_messageSize; + } + + public String cipher() { + return d_cipher; + } + + public ChannelType channelType() { + return e_channelType; + } + + public PerfTestProtocol protocol() { + return f_protocol; + } + } + + private Object[] getParams() { + return new Object[][] { + new Object[] {new Config( + EndpointFactory.CONSCRYPT, + EndpointFactory.CONSCRYPT, + 64, + "AES128-GCM", + ChannelType.CHANNEL, + PerfTestProtocol.TLSv13)}, + }; + } + + + private ClientEndpoint client; + private ServerEndpoint server; + private byte[] message; + private ExecutorService executor; + private Future<?> sendingFuture; + private volatile boolean stopping; + + private static final AtomicLong bytesCounter = new AtomicLong(); + private AtomicBoolean recording = new AtomicBoolean(); + + private void setup(Config config) throws Exception { + message = newTextMessage(512); + + // Always use the same server for consistency across the benchmarks. + server = config.serverFactory().newServer( + ChannelType.CHANNEL, config.messageSize(), config.protocol().getProtocols(), + ciphers(config)); + + server.setMessageProcessor(new ServerEndpoint.MessageProcessor() { + @Override + public void processMessage(byte[] inMessage, int numBytes, OutputStream os) { + if (recording.get()) { + // Server received a message, increment the count. + bytesCounter.addAndGet(numBytes); + } + } + }); + Future<?> connectedFuture = server.start(); + + client = config.clientFactory().newClient( + config.channelType(), server.port(), config.protocol().getProtocols(), ciphers(config)); + client.start(); + + // Wait for the initial connection to complete. + connectedFuture.get(5, TimeUnit.SECONDS); + + executor = Executors.newSingleThreadExecutor(); + sendingFuture = executor.submit(new Runnable() { + @Override + public void run() { + try { + Thread thread = Thread.currentThread(); + while (!stopping && !thread.isInterrupted()) { + client.sendMessage(message); + } + } finally { + client.flush(); + } + } + }); + } + + void close() throws Exception { + stopping = true; + + // Wait for the sending thread to stop. + sendingFuture.get(5, TimeUnit.SECONDS); + + client.stop(); + server.stop(); + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); + } + + /** + * Simple benchmark for the amount of time to send a given number of messages + */ + @Test + @Parameters(method = "getParams") + public void time(Config config) throws Exception { + reset(); + setup(config); + recording.set(true); + + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + while (bytesCounter.get() < config.messageSize()) { + } + bytesCounter.set(0); + } + recording.set(false); + close(); + } + + void reset() { + stopping = false; + bytesCounter.set(0); + } + + private String[] ciphers(Config config) { + return new String[] {config.cipher()}; + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java new file mode 100644 index 000000000000..0655f45726ba --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/EndpointFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 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.ChannelType; +import org.conscrypt.TestUtils; +import java.io.IOException; +import java.security.Provider; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocketFactory; + +/** + * Utility for creating test client and server instances. + */ +public enum EndpointFactory { + CONSCRYPT(newConscryptFactories(false)), + CONSCRYPT_ENGINE(newConscryptFactories(true)); + + private final Factories factories; + + EndpointFactory(Factories factories) { + this.factories = factories; + } + + public ClientEndpoint newClient(ChannelType channelType, int port, String[] protocols, + String[] ciphers) throws IOException { + return new ClientEndpoint( + factories.clientFactory, channelType, port, protocols, ciphers); + } + + public ServerEndpoint newServer(ChannelType channelType, int messageSize, + String[] protocols, String[] ciphers) throws IOException { + return new ServerEndpoint(factories.serverFactory, factories.serverSocketFactory, + channelType, messageSize, protocols, ciphers); + } + + private static final class Factories { + final SSLSocketFactory clientFactory; + final SSLSocketFactory serverFactory; + final SSLServerSocketFactory serverSocketFactory; + + private Factories(SSLSocketFactory clientFactory, SSLSocketFactory serverFactory, + SSLServerSocketFactory serverSocketFactory) { + this.clientFactory = clientFactory; + this.serverFactory = serverFactory; + this.serverSocketFactory = serverSocketFactory; + } + } + + private static Factories newConscryptFactories(boolean useEngineSocket) { + Provider provider = TestUtils.getConscryptProvider(); + SSLContext clientContext = TestUtils.newClientSslContext(provider); + SSLContext serverContext = TestUtils.newServerSslContext(provider); + final SSLSocketFactory clientFactory = clientContext.getSocketFactory(); + final SSLSocketFactory serverFactory = serverContext.getSocketFactory(); + final SSLServerSocketFactory serverSocketFactory = serverContext.getServerSocketFactory(); + TestUtils.setUseEngineSocket(clientFactory, useEngineSocket); + TestUtils.setUseEngineSocket(serverFactory, useEngineSocket); + TestUtils.setUseEngineSocket(serverSocketFactory, useEngineSocket); + return new Factories(clientFactory, serverFactory, serverSocketFactory); + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/OWNERS b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/OWNERS new file mode 100644 index 000000000000..7efabfd3758c --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 24949 +include platform/libcore:/OWNERS
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/PerfTestProtocol.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/PerfTestProtocol.java new file mode 100644 index 000000000000..4defe71fcddd --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/PerfTestProtocol.java @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.conscrypt; + +public enum PerfTestProtocol { + + TLSv13("TLSv1.3"), + TLSv12("TLSv1.2"); + + private final String[] protocols; + + PerfTestProtocol(String... protocols) { + this.protocols = protocols; + } + + public String[] getProtocols() { + return protocols.clone(); + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java new file mode 100644 index 000000000000..3631c3f29287 --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerEndpoint.java @@ -0,0 +1,199 @@ +/* + * 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 java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.SocketException; +import java.nio.channels.ClosedChannelException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import org.conscrypt.ChannelType; + +/** + * A simple socket-based test server. + */ +final class ServerEndpoint { + /** + * A processor for receipt of a single message. + */ + public interface MessageProcessor { + void processMessage(byte[] message, int numBytes, OutputStream os); + } + + /** + * A {@link MessageProcessor} that simply echos back the received message to the client. + */ + public static final class EchoProcessor implements MessageProcessor { + @Override + public void processMessage(byte[] message, int numBytes, OutputStream os) { + try { + os.write(message, 0, numBytes); + os.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private final ServerSocket serverSocket; + private final ChannelType channelType; + private final SSLSocketFactory socketFactory; + private final int messageSize; + private final String[] protocols; + private final String[] cipherSuites; + private final byte[] buffer; + private SSLSocket socket; + private ExecutorService executor; + private InputStream inputStream; + private OutputStream outputStream; + private volatile boolean stopping; + private volatile MessageProcessor messageProcessor = new EchoProcessor(); + private volatile Future<?> processFuture; + + ServerEndpoint(SSLSocketFactory socketFactory, SSLServerSocketFactory serverSocketFactory, + ChannelType channelType, int messageSize, String[] protocols, + String[] cipherSuites) throws IOException { + this.serverSocket = channelType.newServerSocket(serverSocketFactory); + this.socketFactory = socketFactory; + this.channelType = channelType; + this.messageSize = messageSize; + this.protocols = protocols; + this.cipherSuites = cipherSuites; + buffer = new byte[messageSize]; + } + + void setMessageProcessor(MessageProcessor messageProcessor) { + this.messageProcessor = messageProcessor; + } + + Future<?> start() throws IOException { + executor = Executors.newSingleThreadExecutor(); + return executor.submit(new AcceptTask()); + } + + void stop() { + try { + stopping = true; + + if (socket != null) { + socket.close(); + socket = null; + } + + if (processFuture != null) { + processFuture.get(5, TimeUnit.SECONDS); + } + + serverSocket.close(); + + if (executor != null) { + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); + executor = null; + } + } catch (IOException | InterruptedException | ExecutionException | TimeoutException e) { + throw new RuntimeException(e); + } + } + + public int port() { + return serverSocket.getLocalPort(); + } + + private final class AcceptTask implements Runnable { + @Override + public void run() { + try { + if (stopping) { + return; + } + socket = channelType.accept(serverSocket, socketFactory); + socket.setEnabledProtocols(protocols); + socket.setEnabledCipherSuites(cipherSuites); + + socket.startHandshake(); + + inputStream = socket.getInputStream(); + outputStream = socket.getOutputStream(); + + if (stopping) { + return; + } + processFuture = executor.submit(new ProcessTask()); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } + + private final class ProcessTask implements Runnable { + @Override + public void run() { + try { + Thread thread = Thread.currentThread(); + while (!stopping && !thread.isInterrupted()) { + int bytesRead = readMessage(); + if (!stopping && !thread.isInterrupted()) { + messageProcessor.processMessage(buffer, bytesRead, outputStream); + } + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + private int readMessage() throws IOException { + int totalBytesRead = 0; + while (!stopping && totalBytesRead < messageSize) { + try { + int remaining = messageSize - totalBytesRead; + int bytesRead = inputStream.read(buffer, totalBytesRead, remaining); + if (bytesRead == -1) { + break; + } + totalBytesRead += bytesRead; + } catch (SSLException e) { + if (e.getCause() instanceof EOFException) { + break; + } + throw e; + } catch (ClosedChannelException e) { + // Thrown for channel-based sockets. Just treat like EOF. + break; + } catch (SocketException e) { + // The socket was broken. Just treat like EOF. + break; + } + } + return totalBytesRead; + } + } +}
\ 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 new file mode 100644 index 000000000000..ba2a65a17e84 --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java @@ -0,0 +1,208 @@ +/* + * 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.ChannelType; +import static org.conscrypt.TestUtils.getCommonProtocolSuites; +import static org.conscrypt.TestUtils.newTextMessage; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.SocketException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +import android.conscrypt.ServerEndpoint.MessageProcessor; + +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 for comparing performance of server socket implementations. + */ +@RunWith(JUnitParamsRunner.class) +@LargeTest +public final class ServerSocketPerfTest { + + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + /** + * Provider for the benchmark configuration + */ + private class Config { + EndpointFactory a_clientFactory; + EndpointFactory b_serverFactory; + int c_messageSize; + String d_cipher; + ChannelType e_channelType; + Config(EndpointFactory clientFactory, + EndpointFactory serverFactory, + int messageSize, + String cipher, + ChannelType channelType) { + a_clientFactory = clientFactory; + b_serverFactory = serverFactory; + c_messageSize = messageSize; + d_cipher = cipher; + e_channelType = channelType; + } + public EndpointFactory clientFactory() { + return a_clientFactory; + } + + public EndpointFactory serverFactory() { + return b_serverFactory; + } + + public int messageSize() { + return c_messageSize; + } + + public String cipher() { + return d_cipher; + } + + public ChannelType channelType() { + return e_channelType; + } + } + + private Object[] getParams() { + return new Object[][] { + new Object[] {new Config( + EndpointFactory.CONSCRYPT, + EndpointFactory.CONSCRYPT, + 64, + "AES128-GCM", + ChannelType.CHANNEL)}, + }; + } + + private ClientEndpoint client; + private ServerEndpoint server; + private ExecutorService executor; + private Future<?> receivingFuture; + private volatile boolean stopping; + private static final AtomicLong bytesCounter = new AtomicLong(); + private AtomicBoolean recording = new AtomicBoolean(); + + private void setup(final Config config) throws Exception { + recording.set(false); + + byte[] message = newTextMessage(config.messageSize()); + + final ChannelType channelType = config.channelType(); + + server = config.serverFactory().newServer( + channelType, config.messageSize(), getCommonProtocolSuites(), ciphers(config)); + server.setMessageProcessor(new MessageProcessor() { + @Override + public void processMessage(byte[] inMessage, int numBytes, OutputStream os) { + try { + try { + while (!stopping) { + os.write(inMessage, 0, numBytes); + } + } finally { + os.flush(); + } + } catch (SocketException e) { + // Just ignore. + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + + Future<?> connectedFuture = server.start(); + + // Always use the same client for consistency across the benchmarks. + client = config.clientFactory().newClient( + ChannelType.CHANNEL, server.port(), getCommonProtocolSuites(), ciphers(config)); + client.start(); + + // Wait for the initial connection to complete. + connectedFuture.get(5, TimeUnit.SECONDS); + + // Start the server-side streaming by sending a message to the server. + client.sendMessage(message); + client.flush(); + + executor = Executors.newSingleThreadExecutor(); + receivingFuture = executor.submit(new Runnable() { + @Override + public void run() { + Thread thread = Thread.currentThread(); + byte[] buffer = new byte[config.messageSize()]; + while (!stopping && !thread.isInterrupted()) { + int numBytes = client.readMessage(buffer); + if (numBytes < 0) { + return; + } + assertEquals(config.messageSize(), numBytes); + + // Increment the message counter if we're recording. + if (recording.get()) { + bytesCounter.addAndGet(numBytes); + } + } + } + }); + } + + void close() throws Exception { + stopping = true; + // Stop and wait for sending to complete. + server.stop(); + client.stop(); + executor.shutdown(); + receivingFuture.get(5, TimeUnit.SECONDS); + executor.awaitTermination(5, TimeUnit.SECONDS); + } + + @Test + @Parameters(method = "getParams") + public void throughput(Config config) throws Exception { + setup(config); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + recording.set(true); + while (bytesCounter.get() < config.messageSize()) { + } + bytesCounter.set(0); + recording.set(false); + } + close(); + } + + private String[] ciphers(Config config) { + return new String[] {config.cipher()}; + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java new file mode 100644 index 000000000000..78fe73262e4c --- /dev/null +++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/Transformation.java @@ -0,0 +1,88 @@ +/* + * 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 java.security.Key; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import javax.crypto.KeyGenerator; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +/** + * Supported cipher transformations. + */ +@SuppressWarnings({"ImmutableEnumChecker", "unused"}) +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) { + this.algorithm = algorithm; + this.mode = mode; + this.padding = padding; + this.keyGen = keyGen; + } + + final String algorithm; + final String mode; + final String padding; + final KeyGen keyGen; + + String toFormattedString() { + return algorithm + "/" + mode + "/" + padding; + } + + Key newEncryptKey() { + return keyGen.newEncryptKey(); + } + + private interface KeyGen { Key newEncryptKey(); } + + private static final class RsaKeyGen implements KeyGen { + @Override + public Key newEncryptKey() { + try { + // Use Bouncy castle + KeyPairGenerator generator = + KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider()); + generator.initialize(2048); + KeyPair pair = generator.generateKeyPair(); + return pair.getPublic(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + } + + private static final class AesKeyGen implements KeyGen { + @Override + public Key newEncryptKey() { + try { + // Just use the JDK's provider. + KeyGenerator keyGen = KeyGenerator.getInstance("AES"); + keyGen.init(256); + return keyGen.generateKey(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + } +}
\ No newline at end of file diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java index d80d3c8d9301..b955032ff8e4 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java @@ -18,11 +18,8 @@ package android.wm; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static com.android.window.flags.Flags.windowSessionRelayoutInfo; - import android.app.Activity; import android.content.Context; -import android.os.Bundle; import android.os.RemoteException; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; @@ -131,7 +128,6 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase final MergedConfiguration mOutMergedConfiguration = new MergedConfiguration(); final InsetsState mOutInsetsState = new InsetsState(); final InsetsSourceControl.Array mOutControls = new InsetsSourceControl.Array(); - final Bundle mOutBundle = windowSessionRelayoutInfo() ? null : new Bundle(); final WindowRelayoutResult mOutRelayoutResult; final IWindow mWindow; final View mView; @@ -152,26 +148,16 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase mHeight = mView.getMeasuredHeight(); mOutSurfaceControl = mView.getViewRootImpl().getSurfaceControl(); mViewVisibility = visibilitySupplier; - mOutRelayoutResult = windowSessionRelayoutInfo() - ? new WindowRelayoutResult(mOutFrames, mOutMergedConfiguration, - mOutSurfaceControl, mOutInsetsState, mOutControls) - : null; + mOutRelayoutResult = new WindowRelayoutResult(mOutFrames, mOutMergedConfiguration, + mOutSurfaceControl, mOutInsetsState, mOutControls); } void runBenchmark(BenchmarkState state) throws RemoteException { final IWindowSession session = WindowManagerGlobal.getWindowSession(); while (state.keepRunning()) { mRelayoutSeq++; - if (windowSessionRelayoutInfo()) { - session.relayout(mWindow, mParams, mWidth, mHeight, - mViewVisibility.getAsInt(), mFlags, mRelayoutSeq, 0 /* lastSyncSeqId */, - mOutRelayoutResult); - } else { - session.relayoutLegacy(mWindow, mParams, mWidth, mHeight, - mViewVisibility.getAsInt(), mFlags, mRelayoutSeq, 0 /* lastSyncSeqId */, - mOutFrames, mOutMergedConfiguration, mOutSurfaceControl, - mOutInsetsState, mOutControls, mOutBundle); - } + session.relayout(mWindow, mParams, mWidth, mHeight, mViewVisibility.getAsInt(), + mFlags, mRelayoutSeq, 0 /* lastSyncSeqId */, mOutRelayoutResult); } } } diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index b982d1253e21..dfa72069c28a 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -4925,7 +4925,6 @@ public class AlarmManagerService extends SystemService { sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); sdFilter.addAction(Intent.ACTION_USER_STOPPED); if (mStartUserBeforeScheduledAlarms) { - sdFilter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED); sdFilter.addAction(Intent.ACTION_USER_REMOVED); } sdFilter.addAction(Intent.ACTION_UID_REMOVED); @@ -4958,14 +4957,6 @@ public class AlarmManagerService extends SystemService { mTemporaryQuotaReserve.removeForUser(userHandle); } return; - case Intent.ACTION_LOCKED_BOOT_COMPLETED: - final int handle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (handle >= 0) { - if (mStartUserBeforeScheduledAlarms) { - mUserWakeupStore.onUserStarted(handle); - } - } - return; case Intent.ACTION_USER_REMOVED: final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (user >= 0) { diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java index 7fc630c964e5..dc5e3414a819 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/UserWakeupStore.java @@ -98,12 +98,7 @@ public class UserWakeupStore { */ @GuardedBy("mUserWakeupLock") private final SparseLongArray mUserStarts = new SparseLongArray(); - /** - * A list of users that are in a phase after they have been started but before alarms were - * initialized. - */ - @GuardedBy("mUserWakeupLock") - private final SparseLongArray mStartingUsers = new SparseLongArray(); + private Executor mBackgroundExecutor; private static final File USER_WAKEUP_DIR = new File(Environment.getDataSystemDirectory(), ROOT_DIR_NAME); @@ -124,9 +119,6 @@ public class UserWakeupStore { */ public void addUserWakeup(int userId, long alarmTime) { synchronized (mUserWakeupLock) { - // This should not be needed, but if an app in the user is scheduling an alarm clock, we - // consider the user start complete. There is a dedicated removal when user is started. - mStartingUsers.delete(userId); mUserStarts.put(userId, alarmTime - BUFFER_TIME_MS + getUserWakeupOffset()); } updateUserListFile(); @@ -192,23 +184,10 @@ public class UserWakeupStore { } /** - * Move user from wakeup list to starting user list. + * Remove scheduled user wakeup from the list when it is started. */ public void onUserStarting(int userId) { - synchronized (mUserWakeupLock) { - final long wakeup = getWakeupTimeForUser(userId); - if (wakeup >= 0) { - mStartingUsers.put(userId, wakeup); - mUserStarts.delete(userId); - } - } - } - - /** - * Remove userId from starting user list once start is complete. - */ - public void onUserStarted(int userId) { - if (deleteWakeupFromStartingUsers(userId)) { + if (deleteWakeupFromUserStarts(userId)) { updateUserListFile(); } } @@ -217,7 +196,7 @@ public class UserWakeupStore { * Remove userId from the store when the user is removed. */ public void onUserRemoved(int userId) { - if (deleteWakeupFromUserStarts(userId) || deleteWakeupFromStartingUsers(userId)) { + if (deleteWakeupFromUserStarts(userId)) { updateUserListFile(); } } @@ -227,29 +206,14 @@ public class UserWakeupStore { * @return true if an entry is found and the list of wakeups changes. */ private boolean deleteWakeupFromUserStarts(int userId) { - int index; synchronized (mUserWakeupLock) { - index = mUserStarts.indexOfKey(userId); + final int index = mUserStarts.indexOfKey(userId); if (index >= 0) { mUserStarts.removeAt(index); + return true; } + return false; } - return index >= 0; - } - - /** - * Remove wakeup for a given userId from mStartingUsers. - * @return true if an entry is found and the list of wakeups changes. - */ - private boolean deleteWakeupFromStartingUsers(int userId) { - int index; - synchronized (mUserWakeupLock) { - index = mStartingUsers.indexOfKey(userId); - if (index >= 0) { - mStartingUsers.removeAt(index); - } - } - return index >= 0; } /** @@ -299,9 +263,6 @@ public class UserWakeupStore { for (int i = 0; i < mUserStarts.size(); i++) { listOfUsers.add(new Pair<>(mUserStarts.keyAt(i), mUserStarts.valueAt(i))); } - for (int i = 0; i < mStartingUsers.size(); i++) { - listOfUsers.add(new Pair<>(mStartingUsers.keyAt(i), mStartingUsers.valueAt(i))); - } } Collections.sort(listOfUsers, Comparator.comparingLong(pair -> pair.second)); for (int i = 0; i < listOfUsers.size(); i++) { @@ -329,7 +290,6 @@ public class UserWakeupStore { } synchronized (mUserWakeupLock) { mUserStarts.clear(); - mStartingUsers.clear(); } try (FileInputStream fis = userWakeupFile.openRead()) { final TypedXmlPullParser parser = Xml.resolvePullParser(fis); @@ -396,14 +356,6 @@ public class UserWakeupStore { TimeUtils.formatDuration(mUserStarts.valueAt(i), nowELAPSED, pw); pw.println(); } - pw.println(mStartingUsers.size() + " starting users: "); - for (int i = 0; i < mStartingUsers.size(); i++) { - pw.print("UserId: "); - pw.print(mStartingUsers.keyAt(i)); - pw.print(", userStartTime: "); - TimeUtils.formatDuration(mStartingUsers.valueAt(i), nowELAPSED, pw); - pw.println(); - } pw.decreaseIndent(); } } diff --git a/api/Android.bp b/api/Android.bp index 3fa9c600741e..26899eaf872d 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -157,6 +157,7 @@ genrule { genrule { name: "frameworks-base-api-system-current-compat", srcs: [ + ":android.api.public.latest", ":android.api.system.latest", ":android-incompatibilities.api.system.latest", ":frameworks-base-api-current.txt", @@ -165,33 +166,35 @@ genrule { out: ["updated-baseline.txt"], tools: ["metalava"], cmd: metalava_cmd + + "--check-compatibility:api:released $(location :android.api.public.latest) " + "--check-compatibility:api:released $(location :android.api.system.latest) " + - "--check-compatibility:base $(location :frameworks-base-api-current.txt) " + "--baseline:compatibility:released $(location :android-incompatibilities.api.system.latest) " + "--update-baseline:compatibility:released $(genDir)/updated-baseline.txt " + + "$(location :frameworks-base-api-current.txt) " + "$(location :frameworks-base-api-system-current.txt)", } genrule { name: "frameworks-base-api-module-lib-current-compat", srcs: [ + ":android.api.public.latest", + ":android.api.system.latest", ":android.api.module-lib.latest", ":android-incompatibilities.api.module-lib.latest", ":frameworks-base-api-current.txt", + ":frameworks-base-api-system-current.txt", ":frameworks-base-api-module-lib-current.txt", ], out: ["updated-baseline.txt"], tools: ["metalava"], cmd: metalava_cmd + + "--check-compatibility:api:released $(location :android.api.public.latest) " + + "--check-compatibility:api:released $(location :android.api.system.latest) " + "--check-compatibility:api:released $(location :android.api.module-lib.latest) " + - // Note: having "public" be the base of module-lib is not perfect -- it should - // ideally be a merged public+system (which metalava is not currently able to generate). - // This "base" will help when migrating from MODULE_LIBS -> public, but not when - // migrating from MODULE_LIBS -> system (where it needs to instead be listed as - // an incompatibility). - "--check-compatibility:base $(location :frameworks-base-api-current.txt) " + "--baseline:compatibility:released $(location :android-incompatibilities.api.module-lib.latest) " + "--update-baseline:compatibility:released $(genDir)/updated-baseline.txt " + + "$(location :frameworks-base-api-current.txt) " + + "$(location :frameworks-base-api-system-current.txt) " + "$(location :frameworks-base-api-module-lib-current.txt)", } diff --git a/core/api/current.txt b/core/api/current.txt index 5eeb299de9da..6e42fe3a1013 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -3453,6 +3453,8 @@ package android.accessibilityservice { field public static final int GLOBAL_ACTION_HOME = 2; // 0x2 field public static final int GLOBAL_ACTION_KEYCODE_HEADSETHOOK = 10; // 0xa field public static final int GLOBAL_ACTION_LOCK_SCREEN = 8; // 0x8 + field @FlaggedApi("android.view.accessibility.global_action_media_play_pause") public static final int GLOBAL_ACTION_MEDIA_PLAY_PAUSE = 22; // 0x16 + field @FlaggedApi("android.view.accessibility.global_action_menu") public static final int GLOBAL_ACTION_MENU = 21; // 0x15 field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4 field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6 field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5 @@ -6699,7 +6701,7 @@ package android.app { method @NonNull public android.app.Notification.Builder setExtras(android.os.Bundle); method @NonNull public android.app.Notification.Builder setFlag(int, boolean); method @NonNull public android.app.Notification.Builder setForegroundServiceBehavior(int); - method @NonNull public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); + method @NonNull @RequiresPermission(android.Manifest.permission.USE_FULL_SCREEN_INTENT) public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); method @NonNull public android.app.Notification.Builder setGroup(String); method @NonNull public android.app.Notification.Builder setGroupAlertBehavior(int); method @NonNull public android.app.Notification.Builder setGroupSummary(boolean); @@ -9824,6 +9826,7 @@ package android.companion { method public void onAssociationPending(@NonNull android.content.IntentSender); method @Deprecated public void onDeviceFound(@NonNull android.content.IntentSender); method public abstract void onFailure(@Nullable CharSequence); + method @FlaggedApi("android.companion.association_failure_code") public void onFailure(int); } public abstract class CompanionDeviceService extends android.app.Service { diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index fd9600c1f87f..19ffc17f6a94 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -67,6 +67,7 @@ import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityWindowInfo; +import android.view.accessibility.Flags; import android.view.inputmethod.EditorInfo; import com.android.internal.annotations.VisibleForTesting; @@ -625,6 +626,18 @@ public abstract class AccessibilityService extends Service { */ public static final int GLOBAL_ACTION_DPAD_CENTER = 20; + /** + * Action to trigger menu key event. + */ + @FlaggedApi(Flags.FLAG_GLOBAL_ACTION_MENU) + public static final int GLOBAL_ACTION_MENU = 21; + + /** + * Action to trigger media play/pause key event. + */ + @FlaggedApi(Flags.FLAG_GLOBAL_ACTION_MEDIA_PLAY_PAUSE) + public static final int GLOBAL_ACTION_MEDIA_PLAY_PAUSE = 22; + private static final String LOG_TAG = "AccessibilityService"; /** diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 3b9a5d3b2cf2..baed4fd02e5b 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2303,19 +2303,26 @@ class ContextImpl extends Context { && PermissionManager.DEVICE_AWARE_PERMISSIONS.contains(permission)) { VirtualDeviceManager virtualDeviceManager = getSystemService(VirtualDeviceManager.class); - VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId); - if (virtualDevice != null) { - if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO) - && !virtualDevice.hasCustomAudioInputSupport()) - || (Objects.equals(permission, Manifest.permission.CAMERA) - && !virtualDevice.hasCustomCameraSupport())) { - deviceId = Context.DEVICE_ID_DEFAULT; - } - } else { + if (virtualDeviceManager == null) { Slog.e( TAG, - "virtualDevice is not found when device id is not default. deviceId = " + "VDM is not enabled when device id is not default. deviceId = " + deviceId); + } else { + VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId); + if (virtualDevice != null) { + if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO) + && !virtualDevice.hasCustomAudioInputSupport()) + || (Objects.equals(permission, Manifest.permission.CAMERA) + && !virtualDevice.hasCustomCameraSupport())) { + deviceId = Context.DEVICE_ID_DEFAULT; + } + } else { + Slog.e( + TAG, + "virtualDevice is not found when device id is not default. deviceId = " + + deviceId); + } } } @@ -3169,6 +3176,11 @@ class ContextImpl extends Context { public void updateDeviceId(int updatedDeviceId) { if (updatedDeviceId != Context.DEVICE_ID_DEFAULT) { VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class); + if (vdm == null) { + throw new IllegalArgumentException( + "VDM is not enabled when updating to non-default device id: " + + updatedDeviceId); + } if (!vdm.isValidVirtualDeviceId(updatedDeviceId)) { throw new IllegalArgumentException( "Not a valid ID of the default device or any virtual device: " diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index ffb920b907ab..15b13dc97554 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -757,15 +757,6 @@ interface IActivityManager { void addStartInfoTimestamp(int key, long timestampNs, int userId); /** - * Reports view related timestamps to be added to the calling apps most - * recent {@link ApplicationStartInfo}. - * - * @param renderThreadDrawStartTimeNs Clock monotonic time in nanoseconds of RenderThread draw start - * @param framePresentedTimeNs Clock monotonic time in nanoseconds of frame presented - */ - oneway void reportStartInfoViewTimestamps(long renderThreadDrawStartTimeNs, long framePresentedTimeNs); - - /** * Return a list of {@link ApplicationExitInfo} records. * * <p class="note"> Note: System stores these historical information in a ring buffer, older diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index a1c4267072c0..aea15e13e5d6 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5058,6 +5058,7 @@ public class Notification implements Parcelable * @see Notification#fullScreenIntent */ @NonNull + @RequiresPermission(android.Manifest.permission.USE_FULL_SCREEN_INTENT) public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { mN.fullScreenIntent = intent; setFlag(FLAG_HIGH_PRIORITY, highPriority); @@ -6050,6 +6051,7 @@ public class Notification implements Parcelable bindProfileBadge(contentView, p); bindAlertedIcon(contentView, p); bindExpandButton(contentView, p); + bindCloseButton(contentView, p); mN.mUsesStandardHeader = true; } @@ -6071,6 +6073,15 @@ public class Notification implements Parcelable contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor); } + private void bindCloseButton(RemoteViews contentView, StandardTemplateParams p) { + // set default colors + int bgColor = getBackgroundColor(p); + int backgroundColor = Colors.flattenAlpha(getColors(p).getProtectionColor(), bgColor); + int foregroundColor = Colors.flattenAlpha(getPrimaryTextColor(p), backgroundColor); + contentView.setInt(R.id.close_button, "setForegroundColor", foregroundColor); + contentView.setInt(R.id.close_button, "setBackgroundColor", backgroundColor); + } + private void bindHeaderChronometerAndTime(RemoteViews contentView, StandardTemplateParams p, boolean hasTextToLeft) { if (!p.mHideTime && showsTimeOrChronometer()) { diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index b4ad1c8fff12..34cfa584b683 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -21,6 +21,8 @@ import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_P import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER; import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH; +import static java.util.Collections.unmodifiableMap; + import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; @@ -56,6 +58,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.UserHandle; import android.service.notification.NotificationListenerService; +import android.util.ArrayMap; import android.util.ExceptionUtils; import android.util.Log; import android.util.SparseArray; @@ -75,6 +78,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.BiConsumer; @@ -119,29 +123,31 @@ public final class CompanionDeviceManager { * is created successfully. */ public static final int RESULT_OK = -1; - + //TODO(b/331459560) Need to update the java doc after API cut for W. /** * The result code to propagate back to the user activity, indicates if the association dialog * is implicitly cancelled. * E.g. phone is locked, switch to another app or press outside the dialog. */ public static final int RESULT_CANCELED = 0; - + //TODO(b/331459560) Need to update the java doc after API cut for W. /** * The result code to propagate back to the user activity, indicates the association dialog * is explicitly declined by the users. */ public static final int RESULT_USER_REJECTED = 1; - + //TODO(b/331459560) Need to update the java doc after API cut for W. /** * The result code to propagate back to the user activity, indicates the association * dialog is dismissed if there's no device found after 20 seconds. */ public static final int RESULT_DISCOVERY_TIMEOUT = 2; - + //TODO(b/331459560) Need to update the java doc after API cut for W. /** * The result code to propagate back to the user activity, indicates the internal error * in CompanionDeviceManager. + * E.g. Missing necessary permissions or duplicate {@link AssociationRequest}s when create the + * {@link AssociationInfo}. */ public static final int RESULT_INTERNAL_ERROR = 3; @@ -368,12 +374,22 @@ public final class CompanionDeviceManager { */ public void onAssociationCreated(@NonNull AssociationInfo associationInfo) {} + //TODO(b/331459560): Add deprecated and remove abstract after API cut for W. /** * Invoked if the association could not be created. * * @param error error message. */ public abstract void onFailure(@Nullable CharSequence error); + + /** + * Invoked if the association could not be created. + * + * @param resultCode indicate the particular reason why the association + * could not be created. + */ + @FlaggedApi(Flags.FLAG_ASSOCIATION_FAILURE_CODE) + public void onFailure(@ResultCode int resultCode) {} } private final ICompanionDeviceManager mService; @@ -1803,8 +1819,12 @@ public final class CompanionDeviceManager { } @Override - public void onFailure(CharSequence error) throws RemoteException { - execute(mCallback::onFailure, error); + public void onFailure(@ResultCode int resultCode) { + if (Flags.associationFailureCode()) { + execute(mCallback::onFailure, resultCode); + } + + execute(mCallback::onFailure, RESULT_CODE_TO_REASON.get(resultCode)); } private <T> void execute(Consumer<T> callback, T arg) { @@ -1988,4 +2008,15 @@ public final class CompanionDeviceManager { } } } + + private static final Map<Integer, String> RESULT_CODE_TO_REASON; + static { + final Map<Integer, String> map = new ArrayMap<>(); + map.put(RESULT_CANCELED, REASON_CANCELED); + map.put(RESULT_USER_REJECTED, REASON_USER_REJECTED); + map.put(RESULT_DISCOVERY_TIMEOUT, REASON_DISCOVERY_TIMEOUT); + map.put(RESULT_INTERNAL_ERROR, REASON_INTERNAL_ERROR); + + RESULT_CODE_TO_REASON = unmodifiableMap(map); + } } diff --git a/core/java/android/companion/IAssociationRequestCallback.aidl b/core/java/android/companion/IAssociationRequestCallback.aidl index 8cc2a7194e08..b1be30a1288c 100644 --- a/core/java/android/companion/IAssociationRequestCallback.aidl +++ b/core/java/android/companion/IAssociationRequestCallback.aidl @@ -25,5 +25,5 @@ interface IAssociationRequestCallback { oneway void onAssociationCreated(in AssociationInfo associationInfo); - oneway void onFailure(in CharSequence error); + oneway void onFailure(in int resultCode); }
\ No newline at end of file diff --git a/core/java/android/companion/flags.aconfig b/core/java/android/companion/flags.aconfig index fd4ba83b02e3..ee9114f74092 100644 --- a/core/java/android/companion/flags.aconfig +++ b/core/java/android/companion/flags.aconfig @@ -53,4 +53,12 @@ flag { namespace: "companion" description: "Unpair with an associated bluetooth device" bug: "322237619" -}
\ No newline at end of file +} + +flag { + name: "association_failure_code" + is_exported: true + namespace: "companion" + description: "Enable association failure code API" + bug: "331459560" +} diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java index fb9536f846aa..3acb37385de9 100644 --- a/core/java/android/content/ComponentCallbacks.java +++ b/core/java/android/content/ComponentCallbacks.java @@ -58,7 +58,9 @@ public interface ComponentCallbacks { * @deprecated Since API level 14 this is superseded by * {@link ComponentCallbacks2#onTrimMemory}. * Since API level 34 this is never called. - * Apps targeting API level 34 and above may provide an empty implementation. + * If you're overriding ComponentCallbacks2#onTrimMemory and + * your minSdkVersion is greater than API 14, you can provide + * an empty implementation for this method. */ @Deprecated void onLowMemory(); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 4fcf6b66895c..24fd000c3cd4 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4451,7 +4451,8 @@ public abstract class Context { * @see #DISPLAY_HASH_SERVICE * @see android.view.displayhash.DisplayHashManager */ - public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name); + // TODO(b/347269120): Re-add @Nullable + public abstract Object getSystemService(@ServiceName @NonNull String name); /** * Return the handle to a system-level service by class. @@ -4495,7 +4496,8 @@ public abstract class Context { * <b>never</b> throw a {@link RuntimeException} if the name is not supported. */ @SuppressWarnings("unchecked") - public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { + // TODO(b/347269120): Re-add @Nullable + public final <T> T getSystemService(@NonNull Class<T> serviceClass) { // Because subclasses may override getSystemService(String) we cannot // perform a lookup by class alone. We must first map the class to its // service name then invoke the string-based method. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index e0cf0a5f8178..a475c2925881 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -932,7 +932,8 @@ public class ContextWrapper extends Context { } @Override - public @Nullable Object getSystemService(String name) { + // TODO(b/347269120): Re-add @Nullable + public Object getSystemService(String name) { return mBase.getSystemService(name); } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 32d2a6f803d6..c2424e8a6529 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -347,7 +347,9 @@ public class Camera { VirtualDeviceManager virtualDeviceManager = context.getSystemService(VirtualDeviceManager.class); - return virtualDeviceManager.getDevicePolicy(context.getDeviceId(), POLICY_TYPE_CAMERA); + return virtualDeviceManager == null + ? DEVICE_POLICY_DEFAULT + : virtualDeviceManager.getDevicePolicy(context.getDeviceId(), POLICY_TYPE_CAMERA); } /** diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 708f8a173aba..9eb97452444f 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -581,7 +581,9 @@ public final class CameraManager { if (mVirtualDeviceManager == null) { mVirtualDeviceManager = context.getSystemService(VirtualDeviceManager.class); } - return mVirtualDeviceManager.getDevicePolicy(context.getDeviceId(), POLICY_TYPE_CAMERA); + return mVirtualDeviceManager == null + ? DEVICE_POLICY_DEFAULT + : mVirtualDeviceManager.getDevicePolicy(context.getDeviceId(), POLICY_TYPE_CAMERA); } // TODO(b/147726300): Investigate how to support foldables/multi-display devices. diff --git a/core/java/android/hardware/radio/TunerCallbackAdapter.java b/core/java/android/hardware/radio/TunerCallbackAdapter.java index f9a2dbb1bdb4..b1b4de35a9c4 100644 --- a/core/java/android/hardware/radio/TunerCallbackAdapter.java +++ b/core/java/android/hardware/radio/TunerCallbackAdapter.java @@ -63,48 +63,53 @@ final class TunerCallbackAdapter extends ITunerCallback.Stub { } void close() { + ProgramList programList; synchronized (mLock) { - if (mProgramList != null) { - mProgramList.close(); + if (mProgramList == null) { + return; } + programList = mProgramList; } + programList.close(); } void setProgramListObserver(@Nullable ProgramList programList, ProgramList.OnCloseListener closeListener) { Objects.requireNonNull(closeListener, "CloseListener cannot be null"); + ProgramList prevProgramList; synchronized (mLock) { - if (mProgramList != null) { - Log.w(TAG, "Previous program list observer wasn't properly closed, closing it..."); - mProgramList.close(); - } + prevProgramList = mProgramList; mProgramList = programList; - if (programList == null) { - return; + } + if (prevProgramList != null) { + Log.w(TAG, "Previous program list observer wasn't properly closed, closing it..."); + prevProgramList.close(); + } + if (programList == null) { + return; + } + programList.setOnCloseListener(() -> { + synchronized (mLock) { + if (mProgramList != programList) { + return; + } + mProgramList = null; + mLastCompleteList = null; } - programList.setOnCloseListener(() -> { - synchronized (mLock) { - if (mProgramList != programList) { - return; - } - mProgramList = null; - mLastCompleteList = null; + closeListener.onClose(); + }); + programList.addOnCompleteListener(() -> { + synchronized (mLock) { + if (mProgramList != programList) { + return; } - closeListener.onClose(); - }); - programList.addOnCompleteListener(() -> { - synchronized (mLock) { - if (mProgramList != programList) { - return; - } - mLastCompleteList = programList.toList(); - if (mDelayedCompleteCallback) { - Log.d(TAG, "Sending delayed onBackgroundScanComplete callback"); - sendBackgroundScanCompleteLocked(); - } + mLastCompleteList = programList.toList(); + if (mDelayedCompleteCallback) { + Log.d(TAG, "Sending delayed onBackgroundScanComplete callback"); + sendBackgroundScanCompleteLocked(); } - }); - } + } + }); } @Nullable List<RadioManager.ProgramInfo> getLastCompleteList() { @@ -245,12 +250,14 @@ final class TunerCallbackAdapter extends ITunerCallback.Stub { @Override public void onProgramListUpdated(ProgramList.Chunk chunk) { mHandler.post(() -> { + ProgramList programList; synchronized (mLock) { if (mProgramList == null) { return; } - mProgramList.apply(Objects.requireNonNull(chunk, "Chunk cannot be null")); + programList = mProgramList; } + programList.apply(Objects.requireNonNull(chunk, "Chunk cannot be null")); }); } diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig index eda755c05509..b01ffe5932fd 100644 --- a/core/java/android/os/vibrator/flags.aconfig +++ b/core/java/android/os/vibrator/flags.aconfig @@ -31,3 +31,14 @@ flag { description: "Enables the adaptive haptics feature" bug: "305961689" } + +flag { + namespace: "haptics" + name: "cancel_by_appops" + description: "Cancels ongoing vibrations when the appops mode changes to disallow them" + bug: "230745615" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java index 141ffc9a491a..a698b180dbe0 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -374,20 +374,22 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis public @NonNull List<PermissionGroupUsage> getOpUsageDataForAllDevices( boolean includeMicrophoneUsage) { List<PermissionGroupUsage> allUsages = new ArrayList<>(); - List<VirtualDevice> virtualDevices = mVirtualDeviceManager.getVirtualDevices(); - ArraySet<String> persistentDeviceIds = new ArraySet<>(); - for (int num = 0; num < virtualDevices.size(); num++) { - persistentDeviceIds.add(virtualDevices.get(num).getPersistentDeviceId()); - } - persistentDeviceIds.add(VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); + if (mVirtualDeviceManager != null) { + List<VirtualDevice> virtualDevices = mVirtualDeviceManager.getVirtualDevices(); + ArraySet<String> persistentDeviceIds = new ArraySet<>(); - for (int index = 0; index < persistentDeviceIds.size(); index++) { - allUsages.addAll( - getOpUsageDataByDevice(includeMicrophoneUsage, - persistentDeviceIds.valueAt(index))); - } + for (int num = 0; num < virtualDevices.size(); num++) { + persistentDeviceIds.add(virtualDevices.get(num).getPersistentDeviceId()); + } + persistentDeviceIds.add(VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); + for (int index = 0; index < persistentDeviceIds.size(); index++) { + allUsages.addAll( + getOpUsageDataByDevice(includeMicrophoneUsage, + persistentDeviceIds.valueAt(index))); + } + } return allUsages; } diff --git a/core/java/android/service/dreams/DreamOverlayConnectionHandler.java b/core/java/android/service/dreams/DreamOverlayConnectionHandler.java index 85a13c796ee2..bc034008f17c 100644 --- a/core/java/android/service/dreams/DreamOverlayConnectionHandler.java +++ b/core/java/android/service/dreams/DreamOverlayConnectionHandler.java @@ -27,7 +27,6 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ObservableServiceConnection; -import com.android.internal.util.PersistentServiceConnection; import java.util.ArrayList; import java.util.List; @@ -48,22 +47,20 @@ public final class DreamOverlayConnectionHandler { private static final int MSG_OVERLAY_CLIENT_READY = 3; private final Handler mHandler; - private final PersistentServiceConnection<IDreamOverlay> mConnection; + private final ObservableServiceConnection<IDreamOverlay> mConnection; // Retrieved Client private IDreamOverlayClient mClient; // A list of pending requests to execute on the overlay. private final List<Consumer<IDreamOverlayClient>> mConsumers = new ArrayList<>(); private final OverlayConnectionCallback mCallback; + private final Runnable mOnDisconnected; DreamOverlayConnectionHandler( Context context, Looper looper, Intent serviceIntent, - int minConnectionDurationMs, - int maxReconnectAttempts, - int baseReconnectDelayMs) { - this(context, looper, serviceIntent, minConnectionDurationMs, maxReconnectAttempts, - baseReconnectDelayMs, new Injector()); + Runnable onDisconnected) { + this(context, looper, serviceIntent, onDisconnected, new Injector()); } @VisibleForTesting @@ -71,20 +68,15 @@ public final class DreamOverlayConnectionHandler { Context context, Looper looper, Intent serviceIntent, - int minConnectionDurationMs, - int maxReconnectAttempts, - int baseReconnectDelayMs, + Runnable onDisconnected, Injector injector) { mCallback = new OverlayConnectionCallback(); mHandler = new Handler(looper, new OverlayHandlerCallback()); + mOnDisconnected = onDisconnected; mConnection = injector.buildConnection( context, mHandler, - serviceIntent, - minConnectionDurationMs, - maxReconnectAttempts, - baseReconnectDelayMs - ); + serviceIntent); } /** @@ -201,10 +193,14 @@ public final class DreamOverlayConnectionHandler { @Override public void onDisconnected(ObservableServiceConnection<IDreamOverlay> connection, int reason) { + Log.i(TAG, "Dream overlay disconnected, reason: " + reason); mClient = null; // Cancel any pending messages about the overlay being ready, since it is no // longer ready. mHandler.removeMessages(MSG_OVERLAY_CLIENT_READY); + if (mOnDisconnected != null) { + mOnDisconnected.run(); + } } } @@ -217,25 +213,18 @@ public final class DreamOverlayConnectionHandler { * Returns milliseconds since boot, not counting time spent in deep sleep. Can be overridden * in tests with a fake clock. */ - public PersistentServiceConnection<IDreamOverlay> buildConnection( + public ObservableServiceConnection<IDreamOverlay> buildConnection( Context context, Handler handler, - Intent serviceIntent, - int minConnectionDurationMs, - int maxReconnectAttempts, - int baseReconnectDelayMs) { + Intent serviceIntent) { final Executor executor = handler::post; final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; - return new PersistentServiceConnection<>( + return new ObservableServiceConnection<>( context, executor, - handler, IDreamOverlay.Stub::asInterface, serviceIntent, - flags, - minConnectionDurationMs, - maxReconnectAttempts, - baseReconnectDelayMs + flags ); } } diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index a769643ce976..8ecb1fb4e9ad 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -182,6 +182,7 @@ public class DreamService extends Service implements Window.Callback { /** * The name of the dream manager service. + * * @hide */ public static final String DREAM_SERVICE = "dreams"; @@ -222,12 +223,14 @@ public class DreamService extends Service implements Window.Callback { /** * Dream category for Low Light Dream + * * @hide */ public static final int DREAM_CATEGORY_LOW_LIGHT = 1 << 0; /** * Dream category for Home Panel Dream + * * @hide */ public static final int DREAM_CATEGORY_HOME_PANEL = 1 << 1; @@ -295,7 +298,8 @@ public class DreamService extends Service implements Window.Callback { void init(Context context); /** Creates and returns the dream overlay connection */ - DreamOverlayConnectionHandler createOverlayConnection(ComponentName overlayComponent); + DreamOverlayConnectionHandler createOverlayConnection(ComponentName overlayComponent, + Runnable onDisconnected); /** Returns the {@link DreamActivity} component */ ComponentName getDreamActivityComponent(); @@ -333,16 +337,15 @@ public class DreamService extends Service implements Window.Callback { @Override public DreamOverlayConnectionHandler createOverlayConnection( - ComponentName overlayComponent) { + ComponentName overlayComponent, + Runnable onDisconnected) { final Resources resources = mContext.getResources(); return new DreamOverlayConnectionHandler( /* context= */ mContext, Looper.getMainLooper(), new Intent().setComponent(overlayComponent), - resources.getInteger(R.integer.config_minDreamOverlayDurationMs), - resources.getInteger(R.integer.config_dreamOverlayMaxReconnectAttempts), - resources.getInteger(R.integer.config_dreamOverlayReconnectTimeoutMs)); + onDisconnected); } @Override @@ -1176,7 +1179,8 @@ public class DreamService extends Service implements Window.Callback { // Connect to the overlay service if present. if (!mWindowless && overlayComponent != null) { - mOverlayConnection = mInjector.createOverlayConnection(overlayComponent); + mOverlayConnection = mInjector.createOverlayConnection(overlayComponent, + this::finish); if (!mOverlayConnection.bind()) { // Binding failed. diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 8271caf57353..3161ff1e4c00 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -31,7 +31,6 @@ import static com.android.window.flags.Flags.FLAG_OFFLOAD_COLOR_EXTRACTION; import static com.android.window.flags.Flags.noConsecutiveVisibilityEvents; import static com.android.window.flags.Flags.noVisibilityEventOnDisplayStateChange; import static com.android.window.flags.Flags.offloadColorExtraction; -import static com.android.window.flags.Flags.windowSessionRelayoutInfo; import android.animation.AnimationHandler; import android.animation.Animator; @@ -302,13 +301,10 @@ public abstract class WallpaperService extends Service { final InsetsState mInsetsState = new InsetsState(); final InsetsSourceControl.Array mTempControls = new InsetsSourceControl.Array(); final MergedConfiguration mMergedConfiguration = new MergedConfiguration(); - final Bundle mSyncSeqIdBundle = windowSessionRelayoutInfo() ? null : new Bundle(); SurfaceControl mSurfaceControl = new SurfaceControl(); - WindowRelayoutResult mRelayoutResult = windowSessionRelayoutInfo() - ? new WindowRelayoutResult(mWinFrames, mMergedConfiguration, mSurfaceControl, - mInsetsState, mTempControls) - : null; + WindowRelayoutResult mRelayoutResult = new WindowRelayoutResult( + mWinFrames, mMergedConfiguration, mSurfaceControl, mInsetsState, mTempControls); private final Point mSurfaceSize = new Point(); private final Point mLastSurfaceSize = new Point(); @@ -1277,15 +1273,8 @@ public abstract class WallpaperService extends Service { } else { mLayout.surfaceInsets.set(0, 0, 0, 0); } - final int relayoutResult; - if (windowSessionRelayoutInfo()) { - relayoutResult = mSession.relayout(mWindow, mLayout, mWidth, mHeight, - View.VISIBLE, 0, 0, 0, mRelayoutResult); - } else { - relayoutResult = mSession.relayoutLegacy(mWindow, mLayout, mWidth, mHeight, - View.VISIBLE, 0, 0, 0, mWinFrames, mMergedConfiguration, - mSurfaceControl, mInsetsState, mTempControls, mSyncSeqIdBundle); - } + final int relayoutResult = mSession.relayout(mWindow, mLayout, mWidth, mHeight, + View.VISIBLE, 0, 0, 0, mRelayoutResult); final Rect outMaxBounds = mMergedConfiguration.getMergedConfiguration() .windowConfiguration.getMaxBounds(); if (!outMaxBounds.equals(maxBounds)) { diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index e3e4fc04098b..070d33bb9be6 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -49,18 +49,6 @@ import java.util.List; */ interface IWindowSession { - /** - * Bundle key to store the latest sync seq id for the relayout configuration. - * @see #relayout - */ - const String KEY_RELAYOUT_BUNDLE_SEQID = "seqid"; - /** - * Bundle key to store the latest ActivityWindowInfo associated with the relayout configuration. - * Will only be set if the relayout window is an activity window. - * @see #relayout - */ - const String KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO = "activity_window_info"; - int addToDisplay(IWindow window, in WindowManager.LayoutParams attrs, in int viewVisibility, in int layerStackId, int requestedVisibleTypes, out InputChannel outInputChannel, out InsetsState insetsState, @@ -85,16 +73,6 @@ interface IWindowSession { void remove(IBinder clientToken); /** - * @deprecated - */ - int relayoutLegacy(IWindow window, in WindowManager.LayoutParams attrs, - int requestedWidth, int requestedHeight, int viewVisibility, - int flags, int seq, int lastSyncSeqId, out ClientWindowFrames outFrames, - out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl, - out InsetsState insetsState, out InsetsSourceControl.Array activeControls, - out Bundle bundle); - - /** * Change the parameters of a window. You supply the * new parameters, it returns the new frame of the window on screen (the * position should be ignored) and surface of the window. The surface diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9f4d7e2f3338..1494d21e7769 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -25,8 +25,6 @@ import static android.os.Trace.TRACE_TAG_VIEW; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.DragEvent.ACTION_DRAG_LOCATION; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APP_PROGRESS_GENERATION_ALLOWED; -import static android.view.flags.Flags.sensitiveContentPrematureProtectionRemovedFix; import static android.view.InputDevice.SOURCE_CLASS_NONE; import static android.view.InsetsSource.ID_IME; import static android.view.Surface.FRAME_RATE_CATEGORY_DEFAULT; @@ -90,6 +88,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APP_PROGRESS_GENERATION_ALLOWED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY; @@ -114,6 +113,7 @@ import static android.view.accessibility.Flags.forceInvertColor; import static android.view.accessibility.Flags.reduceWindowContentChangedEventThrottle; import static android.view.flags.Flags.addSchandleToVriSurface; import static android.view.flags.Flags.sensitiveContentAppProtection; +import static android.view.flags.Flags.sensitiveContentPrematureProtectionRemovedFix; import static android.view.flags.Flags.toolkitFrameRateFunctionEnablingReadOnly; import static android.view.flags.Flags.toolkitFrameRateTypingReadOnly; import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly; @@ -124,12 +124,11 @@ import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodCl import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; +import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme; import static com.android.window.flags.Flags.activityWindowInfoFlag; import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay; import static com.android.window.flags.Flags.insetsControlChangedItem; import static com.android.window.flags.Flags.setScPropertiesInClient; -import static com.android.window.flags.Flags.windowSessionRelayoutInfo; -import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme; import android.Manifest; import android.accessibilityservice.AccessibilityService; @@ -179,7 +178,6 @@ import android.graphics.Region; import android.graphics.RenderNode; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; -import android.hardware.SyncFence; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.display.DisplayManagerGlobal; @@ -222,7 +220,6 @@ import android.util.proto.ProtoOutputStream; import android.view.InputDevice.InputSourceClass; import android.view.Surface.OutOfResourcesException; import android.view.SurfaceControl.Transaction; -import android.view.SurfaceControl.TransactionStats; import android.view.View.AttachInfo; import android.view.View.FocusDirection; import android.view.View.MeasureSpec; @@ -298,7 +295,6 @@ import java.util.OptionalInt; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; -import java.util.function.Consumer; import java.util.function.Predicate; /** * The top of a view hierarchy, implementing the needed protocol between View @@ -1138,7 +1134,7 @@ public final class ViewRootImpl implements ViewParent, */ /** - * A temporary object used so relayoutWindow can return the latest SyncSeqId + * Object for relayoutWindow to return the latest window info, including the SyncSeqId * system. The SyncSeqId system was designed to work without synchronous relayout * window, and actually synchronous relayout window presents a problem. We could have * a sequence like this: @@ -1152,14 +1148,8 @@ public final class ViewRootImpl implements ViewParent, * we get rid of synchronous relayout, until then, we use this bundle to channel the * integer back over relayout. */ - private final Bundle mRelayoutBundle = windowSessionRelayoutInfo() - ? null - : new Bundle(); - - private final WindowRelayoutResult mRelayoutResult = windowSessionRelayoutInfo() - ? new WindowRelayoutResult(mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, - mTempInsets, mTempControls) - : null; + private final WindowRelayoutResult mRelayoutResult = new WindowRelayoutResult( + mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mTempControls); private static volatile boolean sAnrReported = false; static BLASTBufferQueue.TransactionHangCallback sTransactionHangCallback = @@ -1195,13 +1185,6 @@ public final class ViewRootImpl implements ViewParent, private String mFpsTraceName; private String mLargestViewTraceName; - private final boolean mAppStartInfoTimestampsFlagValue; - @GuardedBy("this") - private boolean mAppStartTimestampsSent = false; - private boolean mAppStartTrackingStarted = false; - private long mRenderThreadDrawStartTimeNs = -1; - private long mFirstFramePresentedTimeNs = -1; - private static boolean sToolkitSetFrameRateReadOnlyFlagValue; private static boolean sToolkitFrameRateFunctionEnablingReadOnlyFlagValue; private static boolean sToolkitMetricsForFrameRateDecisionFlagValue; @@ -1319,8 +1302,6 @@ public final class ViewRootImpl implements ViewParent, } else { mSensitiveContentProtectionService = null; } - - mAppStartInfoTimestampsFlagValue = android.app.Flags.appStartInfoTimestamps(); } public static void addFirstDrawHandler(Runnable callback) { @@ -2596,12 +2577,6 @@ public final class ViewRootImpl implements ViewParent, notifySurfaceDestroyed(); } destroySurface(); - - // Reset so they can be sent again for warm starts. - mAppStartTimestampsSent = false; - mAppStartTrackingStarted = false; - mRenderThreadDrawStartTimeNs = -1; - mFirstFramePresentedTimeNs = -1; } } } @@ -4400,30 +4375,6 @@ public final class ViewRootImpl implements ViewParent, reportDrawFinished(t, seqId); } }); - - // Only trigger once per {@link ViewRootImpl} instance, so don't add listener if - // {link mTransactionCompletedTimeNs} has already been set. - if (mAppStartInfoTimestampsFlagValue && !mAppStartTrackingStarted) { - mAppStartTrackingStarted = true; - Transaction transaction = new Transaction(); - transaction.addTransactionCompletedListener(mExecutor, - new Consumer<TransactionStats>() { - @Override - public void accept(TransactionStats transactionStats) { - SyncFence presentFence = transactionStats.getPresentFence(); - if (presentFence.awaitForever()) { - if (mFirstFramePresentedTimeNs == -1) { - // Only trigger once per {@link ViewRootImpl} instance. - mFirstFramePresentedTimeNs = presentFence.getSignalTime(); - maybeSendAppStartTimes(); - } - } - presentFence.close(); - } - }); - applyTransactionOnDraw(transaction); - } - if (DEBUG_BLAST) { Log.d(mTag, "Setup new sync=" + mWmsRequestSyncGroup.getName()); } @@ -4431,45 +4382,6 @@ public final class ViewRootImpl implements ViewParent, mWmsRequestSyncGroup.add(this, null /* runnable */); } - private void maybeSendAppStartTimes() { - synchronized (this) { - if (mAppStartTimestampsSent) { - // Don't send timestamps more than once. - return; - } - - // If we already have {@link mRenderThreadDrawStartTimeNs} then pass it through, if not - // post to main thread and check if we have it there. - if (mRenderThreadDrawStartTimeNs != -1) { - sendAppStartTimesLocked(); - } else { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (ViewRootImpl.this) { - if (mRenderThreadDrawStartTimeNs == -1) { - return; - } - sendAppStartTimesLocked(); - } - } - }); - } - } - } - - @GuardedBy("this") - private void sendAppStartTimesLocked() { - try { - ActivityManager.getService().reportStartInfoViewTimestamps( - mRenderThreadDrawStartTimeNs, mFirstFramePresentedTimeNs); - mAppStartTimestampsSent = true; - } catch (RemoteException e) { - // Ignore, timestamps may be lost. - if (DBG) Log.d(TAG, "Exception attempting to report start timestamps.", e); - } - } - /** * Helper used to notify the service to block projection when a sensitive * view (the view displays sensitive content) is attached to the window. @@ -5656,13 +5568,7 @@ public final class ViewRootImpl implements ViewParent, registerCallbackForPendingTransactions(); } - long timeNs = SystemClock.uptimeNanos(); mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this); - - // Only trigger once per {@link ViewRootImpl} instance. - if (mAppStartInfoTimestampsFlagValue && mRenderThreadDrawStartTimeNs == -1) { - mRenderThreadDrawStartTimeNs = timeNs; - } } else { // If we get here with a disabled & requested hardware renderer, something went // wrong (an invalidate posted right before we destroyed the hardware surface @@ -9261,42 +9167,19 @@ public final class ViewRootImpl implements ViewParent, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq, mLastSyncSeqId); } else { - if (windowSessionRelayoutInfo()) { - relayoutResult = mWindowSession.relayout(mWindow, params, - requestedWidth, requestedHeight, viewVisibility, - insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, - mRelayoutSeq, mLastSyncSeqId, mRelayoutResult); - } else { - relayoutResult = mWindowSession.relayoutLegacy(mWindow, params, - requestedWidth, requestedHeight, viewVisibility, - insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, - mRelayoutSeq, mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration, - mSurfaceControl, mTempInsets, mTempControls, mRelayoutBundle); - } + relayoutResult = mWindowSession.relayout(mWindow, params, + requestedWidth, requestedHeight, viewVisibility, + insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, + mRelayoutSeq, mLastSyncSeqId, mRelayoutResult); mRelayoutRequested = true; if (activityWindowInfoFlag() && mPendingActivityWindowInfo != null) { - ActivityWindowInfo outInfo = null; - if (windowSessionRelayoutInfo()) { - outInfo = mRelayoutResult != null ? mRelayoutResult.activityWindowInfo : null; - } else { - try { - outInfo = mRelayoutBundle.getParcelable( - IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO, - ActivityWindowInfo.class); - mRelayoutBundle.remove( - IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO); - } catch (IllegalStateException e) { - Log.e(TAG, "Failed to get ActivityWindowInfo from relayout Bundle", e); - } - } + final ActivityWindowInfo outInfo = mRelayoutResult.activityWindowInfo; if (outInfo != null) { mPendingActivityWindowInfo.set(outInfo); } } - final int maybeSyncSeqId = windowSessionRelayoutInfo() - ? mRelayoutResult.syncSeqId - : mRelayoutBundle.getInt(IWindowSession.KEY_RELAYOUT_BUNDLE_SEQID); + final int maybeSyncSeqId = mRelayoutResult.syncSeqId; if (maybeSyncSeqId > 0) { mSyncSeqId = maybeSyncSeqId; } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index d7d764b6ce75..55f22a631c3b 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -23,7 +23,6 @@ import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Region; -import android.os.Bundle; import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; @@ -349,18 +348,6 @@ public class WindowlessWindowManager implements IWindowSession { } @Override - public int relayoutLegacy(IWindow window, WindowManager.LayoutParams inAttrs, - int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq, - int lastSyncSeqId, ClientWindowFrames outFrames, - MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl, - InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls, - Bundle outSyncSeqIdBundle) { - return relayoutInner(window, inAttrs, requestedWidth, requestedHeight, viewFlags, flags, - seq, lastSyncSeqId, outFrames, outMergedConfiguration, outSurfaceControl, - outInsetsState, outActiveControls); - } - - @Override public int relayout(IWindow window, WindowManager.LayoutParams inAttrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq, int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) { diff --git a/core/java/android/view/accessibility/a11ychecker/AccessibilityNodePathBuilder.java b/core/java/android/view/accessibility/a11ychecker/AccessibilityNodePathBuilder.java new file mode 100644 index 000000000000..2996ddef6f64 --- /dev/null +++ b/core/java/android/view/accessibility/a11ychecker/AccessibilityNodePathBuilder.java @@ -0,0 +1,112 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.accessibility.a11ychecker; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.view.accessibility.AccessibilityNodeInfo; + +/** + * Utility class to create developer-friendly {@link AccessibilityNodeInfo} path Strings for use + * in reporting AccessibilityCheck results. + * + * @hide + */ +public final class AccessibilityNodePathBuilder { + + /** + * Returns the path of the node within its accessibility hierarchy starting from the root node + * down to the given node itself, and prefixed by the package name. This path is not guaranteed + * to be unique. This can return null in case the node's hierarchy changes while scanning. + * + * <p>Each element in the path is represented by its View ID resource name, when available, or + * the + * simple class name if not. The path also includes the index of each child node relative to + * its + * parent. See {@link AccessibilityNodeInfo#getViewIdResourceName()}. + * + * <p>For example, + * "com.example.app:RootElementClassName/parent_resource_name[1]/TargetElementClassName[3]" + * indicates the element has type {@code TargetElementClassName}, and is the third child of an + * element with the resource name {@code parent_resource_name}, which is the first child of an + * element of type {@code RootElementClassName}. + * + * <p>This format is consistent with elements paths in Pre-Launch Reports and the Accessibility + * Scanner, starting from the window's root node instead of the first resource name. + * TODO (b/344607035): link to ClusteringUtils when AATF is merged in main. + */ + public static @Nullable String createNodePath(@NonNull AccessibilityNodeInfo nodeInfo) { + StringBuilder resourceIdBuilder = getNodePathBuilder(nodeInfo); + return resourceIdBuilder == null ? null : String.valueOf(nodeInfo.getPackageName()) + ':' + + resourceIdBuilder; + } + + private static @Nullable StringBuilder getNodePathBuilder(AccessibilityNodeInfo nodeInfo) { + AccessibilityNodeInfo parent = nodeInfo.getParent(); + if (parent == null) { + return new StringBuilder(getShortUiElementName(nodeInfo)); + } + StringBuilder parentNodePath = getNodePathBuilder(parent); + if (parentNodePath == null) { + return null; + } + int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (!nodeInfo.equals(parent.getChild(i))) { + continue; + } + CharSequence uiElementName = getShortUiElementName(nodeInfo); + if (uiElementName != null) { + parentNodePath.append('/').append(uiElementName).append('[').append(i + 1).append( + ']'); + } else { + parentNodePath.append(":nth-child(").append(i + 1).append(')'); + } + return parentNodePath; + } + return null; + } + + //Returns the part of the element's View ID resource name after the qualifier + // "package_name:id/" or the last '/', when available. Otherwise, returns the element's + // simple class name. + private static CharSequence getShortUiElementName(AccessibilityNodeInfo nodeInfo) { + String viewIdResourceName = nodeInfo.getViewIdResourceName(); + if (viewIdResourceName != null) { + String idQualifier = ":id/"; + int idQualifierStartIndex = viewIdResourceName.indexOf(idQualifier); + int unqualifiedNameStartIndex = idQualifierStartIndex == -1 ? 0 + : (idQualifierStartIndex + idQualifier.length()); + return viewIdResourceName.substring(unqualifiedNameStartIndex); + } + return getSimpleClassName(nodeInfo); + } + + private static CharSequence getSimpleClassName(AccessibilityNodeInfo nodeInfo) { + CharSequence name = nodeInfo.getClassName(); + for (int i = name.length() - 1; i > 0; i--) { + char ithChar = name.charAt(i); + if (ithChar == '.' || ithChar == '$') { + return name.subSequence(i + 1, name.length()); + } + } + return name; + } + + private AccessibilityNodePathBuilder() { + } +} diff --git a/core/java/android/view/accessibility/a11ychecker/Android.bp b/core/java/android/view/accessibility/a11ychecker/Android.bp new file mode 100644 index 000000000000..e5a577c16421 --- /dev/null +++ b/core/java/android/view/accessibility/a11ychecker/Android.bp @@ -0,0 +1,7 @@ +java_library_static { + name: "A11yChecker", + srcs: [ + "*.java", + ], + visibility: ["//visibility:public"], +} diff --git a/core/java/android/view/accessibility/a11ychecker/OWNERS b/core/java/android/view/accessibility/a11ychecker/OWNERS new file mode 100644 index 000000000000..d1e7986cc209 --- /dev/null +++ b/core/java/android/view/accessibility/a11ychecker/OWNERS @@ -0,0 +1,4 @@ +# Android Accessibility Framework owners +include /services/accessibility/OWNERS + +yaraabdullatif@google.com diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig index 95d001fa4e80..d0bc57b9afbe 100644 --- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig +++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig @@ -100,6 +100,20 @@ flag { flag { namespace: "accessibility" + name: "global_action_menu" + description: "Allow AccessibilityService to perform GLOBAL_ACTION_MENU" + bug: "334954140" +} + +flag { + namespace: "accessibility" + name: "global_action_media_play_pause" + description: "Allow AccessibilityService to perform GLOBAL_ACTION_MEDIA_PLAY_PAUSE" + bug: "334954140" +} + +flag { + namespace: "accessibility" name: "granular_scrolling" is_exported: true description: "Allow the use of granular scrolling. This allows scrollable nodes to scroll by increments other than a full screen" diff --git a/core/java/android/window/flags/OWNERS b/core/java/android/window/flags/OWNERS index fd73d35e00d2..0472b6c43ce6 100644 --- a/core/java/android/window/flags/OWNERS +++ b/core/java/android/window/flags/OWNERS @@ -1,3 +1,4 @@ per-file responsible_apis.aconfig = file:/BAL_OWNERS per-file large_screen_experiences_app_compat.aconfig = file:/LSE_APP_COMPAT_OWNERS per-file accessibility.aconfig = file:/core/java/android/view/accessibility/OWNERS +per-file lse_desktop_experience.aconfig = file:/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index ca125dafc2f7..d0ab674a0e62 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -120,3 +120,10 @@ flag { description: "Whether to enable min/max window size constraints when resizing a window in desktop windowing mode" bug: "327589741" } + +flag { + name: "show_desktop_windowing_dev_option" + namespace: "lse_desktop_experience" + description: "Whether to show developer option for enabling desktop windowing mode" + bug: "348193756" +} diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig index 552bb466d8ee..8cd2a3ed124e 100644 --- a/core/java/android/window/flags/windowing_sdk.aconfig +++ b/core/java/android/window/flags/windowing_sdk.aconfig @@ -103,17 +103,6 @@ flag { flag { namespace: "windowing_sdk" - name: "window_session_relayout_info" - description: "Pass an out RelayoutInfo instead of Bundle to fix the Parcel recycle bug" - bug: "335601427" - is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { - namespace: "windowing_sdk" name: "fix_pip_restore_to_overlay" description: "Restore exit-pip activity back to ActivityEmbedding overlay" bug: "297887697" @@ -181,3 +170,14 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + namespace: "windowing_sdk" + name: "fix_no_container_update_without_resize" + description: "Fix the containers not being updated when the Task is brought to front and has the same configuration" + bug: "344721335" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java index fc3cd45787f7..c8d619481726 100644 --- a/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java +++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java @@ -29,8 +29,6 @@ import android.app.Activity; import android.content.ComponentName; import android.os.Bundle; import android.provider.Settings; -import android.text.TextUtils; -import android.view.View; import android.view.accessibility.AccessibilityManager; import android.widget.GridView; import android.widget.TextView; @@ -73,16 +71,11 @@ public class AccessibilityButtonChooserActivity extends Activity { promptPrologue.setText(isTouchExploreOn ? R.string.accessibility_gesture_3finger_prompt_text : R.string.accessibility_gesture_prompt_text); - } - if (TextUtils.isEmpty(component)) { final TextView prompt = findViewById(R.id.accessibility_button_prompt); - if (isGestureNavigateEnabled) { - prompt.setText(isTouchExploreOn - ? R.string.accessibility_gesture_3finger_instructional_text - : R.string.accessibility_gesture_instructional_text); - } - prompt.setVisibility(View.VISIBLE); + prompt.setText(isTouchExploreOn + ? R.string.accessibility_gesture_3finger_instructional_text + : R.string.accessibility_gesture_instructional_text); } mTargets.addAll(getTargets(this, SOFTWARE)); diff --git a/core/java/com/android/internal/jank/Cuj.java b/core/java/com/android/internal/jank/Cuj.java index a52d33ab7c42..618f622cb9ce 100644 --- a/core/java/com/android/internal/jank/Cuj.java +++ b/core/java/com/android/internal/jank/Cuj.java @@ -155,8 +155,13 @@ public class Cuj { */ public static final int CUJ_FOLD_ANIM = 105; + /** + * Track window re-sizing interaction in desktop mode. + */ + public static final int CUJ_DESKTOP_MODE_RESIZE_WINDOW = 106; + // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. - @VisibleForTesting static final int LAST_CUJ = CUJ_FOLD_ANIM; + @VisibleForTesting static final int LAST_CUJ = CUJ_DESKTOP_MODE_RESIZE_WINDOW; /** @hide */ @IntDef({ @@ -253,7 +258,8 @@ public class Cuj { CUJ_LAUNCHER_PRIVATE_SPACE_LOCK, CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK, CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, - CUJ_FOLD_ANIM + CUJ_FOLD_ANIM, + CUJ_DESKTOP_MODE_RESIZE_WINDOW }) @Retention(RetentionPolicy.SOURCE) public @interface CujType {} @@ -361,6 +367,7 @@ public class Cuj { CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_PRIVATE_SPACE_UNLOCK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_PRIVATE_SPACE_UNLOCK; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_MAXIMIZE_WINDOW; CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_FOLD_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__FOLD_ANIM; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_DESKTOP_MODE_RESIZE_WINDOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__DESKTOP_MODE_RESIZE_WINDOW; } private Cuj() { @@ -567,6 +574,8 @@ public class Cuj { return "DESKTOP_MODE_MAXIMIZE_WINDOW"; case CUJ_FOLD_ANIM: return "FOLD_ANIM"; + case CUJ_DESKTOP_MODE_RESIZE_WINDOW: + return "DESKTOP_MODE_RESIZE_WINDOW"; } return "UNKNOWN"; } diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java index 13efaf06aeda..754f77e72f8a 100644 --- a/core/java/com/android/internal/util/LatencyTracker.java +++ b/core/java/com/android/internal/util/LatencyTracker.java @@ -28,6 +28,7 @@ import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPOR import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN; +import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FPS_UNLOCK_TO_HOME; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOAD_SHARE_SHEET; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK; @@ -227,7 +228,8 @@ public class LatencyTracker { public static final int ACTION_NOTIFICATION_BIG_PICTURE_LOADED = 23; /** - * Time it takes to unlock the device via udfps, until the whole launcher appears. + * Time it takes to unlock the device via fps, + * until either the launcher or the foreground app appears. */ public static final int ACTION_KEYGUARD_FPS_UNLOCK_TO_HOME = 24; @@ -249,6 +251,12 @@ public class LatencyTracker { */ public static final int ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN = 27; + /** + * Time it takes to unlock the device via face, + * until either the launcher or the foreground app appears. + */ + public static final int ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME = 28; + private static final int[] ACTIONS_ALL = { ACTION_EXPAND_PANEL, ACTION_TOGGLE_RECENTS, @@ -278,6 +286,7 @@ public class LatencyTracker { ACTION_BACK_SYSTEM_ANIMATION, ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE, ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN, + ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME, }; /** @hide */ @@ -310,6 +319,7 @@ public class LatencyTracker { ACTION_BACK_SYSTEM_ANIMATION, ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE, ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN, + ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME, }) @Retention(RetentionPolicy.SOURCE) public @interface Action { @@ -345,6 +355,7 @@ public class LatencyTracker { UIACTION_LATENCY_REPORTED__ACTION__ACTION_BACK_SYSTEM_ANIMATION, UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE, UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN, + UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME, }; private final Object mLock = new Object(); @@ -539,6 +550,8 @@ public class LatencyTracker { return "ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE"; case UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN: return "ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN"; + case UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME: + return "ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME"; default: throw new IllegalArgumentException("Invalid action"); } diff --git a/core/java/com/android/internal/widget/NotificationCloseButton.java b/core/java/com/android/internal/widget/NotificationCloseButton.java new file mode 100644 index 000000000000..bce266d71e43 --- /dev/null +++ b/core/java/com/android/internal/widget/NotificationCloseButton.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +import android.annotation.ColorInt; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.util.AttributeSet; +import android.view.RemotableViewMethod; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RemoteViews; + +import com.android.internal.R; + +/** + * A close button in a notification + */ +@RemoteViews.RemoteView +public class NotificationCloseButton extends ImageView { + + @ColorInt private int mBackgroundColor; + @ColorInt private int mForegroundColor; + + public NotificationCloseButton(Context context) { + this(context, null, 0, 0); + } + + public NotificationCloseButton(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0, 0); + } + + public NotificationCloseButton(Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public NotificationCloseButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + setContentDescription(mContext.getText(R.string.close_button_text)); + boolean notificationCloseButtonSupported = Resources.getSystem().getBoolean( + com.android.internal.R.bool.config_notificationCloseButtonSupported); + this.setVisibility(notificationCloseButtonSupported ? View.VISIBLE : View.GONE); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(Button.class.getName()); + } + + + private void updateColors() { + if (mBackgroundColor != 0) { + this.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); + } + if (mForegroundColor != 0) { + this.setImageTintList(ColorStateList.valueOf(mForegroundColor)); + } + } + + /** + * Set the color used for the foreground. + */ + @RemotableViewMethod + public void setForegroundColor(@ColorInt int color) { + mForegroundColor = color; + updateColors(); + } + + /** + * Sets the color used for the background. + */ + @RemotableViewMethod + public void setBackgroundColor(@ColorInt int color) { + mBackgroundColor = color; + updateColors(); + } +} diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto index 1d9b0db3218b..5a4d6dbdc085 100644 --- a/core/proto/android/server/vibrator/vibratormanagerservice.proto +++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto @@ -146,6 +146,7 @@ message VibrationProto { IGNORED_FROM_VIRTUAL_DEVICE = 26; IGNORED_ON_WIRELESS_CHARGER = 27; IGNORED_MISSING_PERMISSION = 28; + CANCELLED_BY_APP_OPS = 29; reserved 17; // prev IGNORED_UNKNOWN_VIBRATION } } diff --git a/core/res/res/drawable/notification_close_button_icon.xml b/core/res/res/drawable/notification_close_button_icon.xml new file mode 100644 index 000000000000..947cd5a10525 --- /dev/null +++ b/core/res/res/drawable/notification_close_button_icon.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="@dimen/notification_close_button_size" + android:height="@dimen/notification_close_button_size" + android:viewportWidth="16.0" + android:viewportHeight="16.0"> +<path + android:fillColor="#FF000000" + android:pathData="M 12.6667 4.2733 L 11.7267 3.3333 L 8 7.06 L 4.2734 3.3333 L 3.3334 +4.2733 L 7.06 8 L 3.3334 11.7267 L 4.2734 12.6667 L 8 8.94 L 11.7267 12.6667 L 12.6667 +11.7267 L 8.94 8 L 12.6667 4.2733 Z"/> +</vector>
\ No newline at end of file diff --git a/core/res/res/layout/accessibility_button_chooser.xml b/core/res/res/layout/accessibility_button_chooser.xml index 2f97bae2a80e..f50af15875d8 100644 --- a/core/res/res/layout/accessibility_button_chooser.xml +++ b/core/res/res/layout/accessibility_button_chooser.xml @@ -47,6 +47,16 @@ android:paddingTop="8dp" android:paddingBottom="8dp"/> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/accessibility_button_prompt" + android:textAppearance="?attr/textAppearanceMedium" + android:text="@string/accessibility_button_instructional_text" + android:gravity="start|center_vertical" + android:paddingTop="8dp" + android:paddingBottom="8dp"/> + <GridView android:layout_width="match_parent" android:layout_height="wrap_content" @@ -57,16 +67,5 @@ android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center"/> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:id="@+id/accessibility_button_prompt" - android:textAppearance="?attr/textAppearanceMedium" - android:text="@string/accessibility_button_instructional_text" - android:gravity="start|center_vertical" - android:paddingTop="8dp" - android:paddingBottom="8dp" - android:visibility="gone"/> </LinearLayout> </com.android.internal.widget.ResolverDrawerLayout> diff --git a/core/res/res/layout/notification_close_button.xml b/core/res/res/layout/notification_close_button.xml new file mode 100644 index 000000000000..5eff84e6981a --- /dev/null +++ b/core/res/res/layout/notification_close_button.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<com.android.internal.widget.NotificationCloseButton + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/close_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|end" + android:contentDescription="@string/close_button_text" + android:visibility="gone" + android:src="@drawable/notification_close_button_icon" + android:padding="2dp" + android:scaleType="fitCenter" + android:importantForAccessibility="no" + > +</com.android.internal.widget.NotificationCloseButton> diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index d80b7657d0b0..e44c7272bc1e 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -83,11 +83,28 @@ android:focusable="false" /> - <include layout="@layout/notification_expand_button" + <LinearLayout + android:id="@+id/notification_buttons_column" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:layout_centerVertical="true" - /> + android:orientation="vertical" + > + + <include layout="@layout/notification_close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_gravity="end" + android:layout_marginEnd="20dp" + /> + + <include layout="@layout/notification_expand_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_centerVertical="true" + /> + + </LinearLayout> </NotificationHeaderView> diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml index 452df50484c8..29f14a4a93fc 100644 --- a/core/res/res/layout/notification_template_material_base.xml +++ b/core/res/res/layout/notification_template_material_base.xml @@ -157,20 +157,38 @@ android:maxDrawableHeight="@dimen/notification_right_icon_size" /> - <FrameLayout - android:id="@+id/expand_button_touch_container" + <LinearLayout + android:id="@+id/notification_buttons_column" android:layout_width="wrap_content" android:layout_height="match_parent" - android:minWidth="@dimen/notification_content_margin_end" + android:layout_alignParentEnd="true" + android:orientation="vertical" > - <include layout="@layout/notification_expand_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical|end" + <include layout="@layout/notification_close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_gravity="end" + android:layout_marginEnd="20dp" /> - </FrameLayout> + <FrameLayout + android:id="@+id/expand_button_touch_container" + android:layout_width="wrap_content" + android:layout_height="0dp" + android:layout_weight="1" + android:minWidth="@dimen/notification_content_margin_end" + > + + <include layout="@layout/notification_expand_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + /> + + </FrameLayout> + + </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml index ce8a90495572..13f2c37d73fe 100644 --- a/core/res/res/layout/notification_template_material_conversation.xml +++ b/core/res/res/layout/notification_template_material_conversation.xml @@ -107,13 +107,20 @@ > <!--expand_button_container is dynamically placed between here and at the end of the layout. It starts here since only FrameLayout layout params have gravity--> - <FrameLayout + <LinearLayout android:id="@+id/expand_button_container" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="end|top" android:clipChildren="false" - android:clipToPadding="false"> + android:clipToPadding="false" + android:orientation="vertical"> + <include layout="@layout/notification_close_button" + android:layout_width="@dimen/notification_close_button_size" + android:layout_height="@dimen/notification_close_button_size" + android:layout_gravity="end" + android:layout_marginEnd="20dp" + /> <!--expand_button_touch_container makes sure that we can nicely center the expand content in the collapsed layout while the parent makes sure that we're never laid out bigger than the messaging content.--> @@ -145,6 +152,6 @@ android:layout_gravity="center" /> </LinearLayout> - </FrameLayout> + </LinearLayout> </FrameLayout> </com.android.internal.widget.ConversationLayout> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 678dcff48439..105b09988835 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -567,14 +567,6 @@ It has been updated to affect other plug types. --> <bool name="config_keepDreamingWhenUnplugging">false</bool> - <!-- The timeout (in ms) to wait before attempting to reconnect to the dream overlay service if - it becomes disconnected --> - <integer name="config_dreamOverlayReconnectTimeoutMs">1000</integer> <!-- 1 second --> - <!-- The maximum number of times to attempt reconnecting to the dream overlay service --> - <integer name="config_dreamOverlayMaxReconnectAttempts">3</integer> - <!-- The duration after which the dream overlay connection should be considered stable --> - <integer name="config_minDreamOverlayDurationMs">10000</integer> <!-- 10 seconds --> - <!-- Auto-rotation behavior --> <!-- If true, enables auto-rotation features using the accelerometer. @@ -7092,6 +7084,9 @@ <!-- Whether the system uses auto-suspend mode. --> <bool name="config_useAutoSuspend">true</bool> + <!-- Whether close/dismiss buttons are supported on notifications. --> + <bool name="config_notificationCloseButtonSupported">false</bool> + <!-- Whether to show GAIA education screen during account login of private space setup. OEM/Partner can explicitly opt to disable the screen. --> <bool name="config_enableGaiaEducationInPrivateSpace">true</bool> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 5fea51599971..6cba84be58c3 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -355,6 +355,9 @@ <!-- the padding of the expand icon in the notification header --> <dimen name="notification_expand_button_icon_padding">2dp</dimen> + <!-- the size of the notification close button --> + <dimen name="notification_close_button_size">16dp</dimen> + <!-- Vertical margin for the headerless notification content, when content has 1 line --> <!-- 16 * 2 (margins) + 24 (1 line) = 56 (notification) --> <dimen name="notification_headerless_margin_oneline">16dp</dimen> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 351cbad534c2..05c46b9d4654 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4844,19 +4844,19 @@ <!-- Text spoken when accessibility shortcut warning dialog is shown. [CHAR LIMIT=none] --> <string name="accessibility_shortcut_spoken_feedback">Release the volume keys. To turn on <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g>, press and hold both volume keys again for 3 seconds.</string> - <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. [CHAR LIMIT=none]--> - <string name="accessibility_button_prompt_text">Choose a feature to use when you tap the accessibility button:</string> + <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button in the navigation bar or in gesture navigation. [CHAR LIMIT=none]--> + <string name="accessibility_button_prompt_text">Choose a feature</string> <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button when gesture navigation is enabled [CHAR LIMIT=none] --> - <string name="accessibility_gesture_prompt_text">Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):</string> + <string name="accessibility_gesture_prompt_text">Choose a feature</string> <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button when gesture navigation and TalkBack is enabled [CHAR LIMIT=none] --> - <string name="accessibility_gesture_3finger_prompt_text">Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):</string> + <string name="accessibility_gesture_3finger_prompt_text">Choose a feature</string> <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. [CHAR LIMIT=none]--> - <string name="accessibility_button_instructional_text">To switch between features, touch & hold the accessibility button.</string> + <string name="accessibility_button_instructional_text">The feature will open next time you tap the accessibility button.</string> <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button when gesture navigation is enabled. [CHAR LIMIT=none] --> - <string name="accessibility_gesture_instructional_text">To switch between features, swipe up with two fingers and hold.</string> + <string name="accessibility_gesture_instructional_text">The feature will open next time you use this shortcut. Swipe up with two fingers from the bottom of your screen and release quickly.</string> <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button when gesture navigation and TalkBack is enabled. [CHAR LIMIT=none] --> - <string name="accessibility_gesture_3finger_instructional_text">To switch between features, swipe up with three fingers and hold.</string> + <string name="accessibility_gesture_3finger_instructional_text">The feature will open next time you use this shortcut. Swipe up with three fingers from the bottom of your screen and release quickly.</string> <!-- Text used to describe system navigation features, shown within a UI allowing a user to assign system magnification features to the Accessibility button in the navigation bar. --> <string name="accessibility_magnification_chooser_text">Magnification</string> @@ -5985,6 +5985,10 @@ <string name="accessibility_system_action_hardware_a11y_shortcut_label">Accessibility Shortcut</string> <!-- Label for dismissing the notification shade [CHAR LIMIT=NONE] --> <string name="accessibility_system_action_dismiss_notification_shade">Dismiss Notification Shade</string> + <!-- Label for menu action [CHAR LIMIT=NONE] --> + <string name="accessibility_system_action_menu_label">Menu</string> + <!-- Label for media play/pause action [CHAR LIMIT=NONE] --> + <string name="accessibility_system_action_media_play_pause_label">Media Play/Pause</string> <!-- Label for Dpad up action [CHAR LIMIT=NONE] --> <string name="accessibility_system_action_dpad_up_label">Dpad Up</string> <!-- Label for Dpad down action [CHAR LIMIT=NONE] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 63934c4dc70b..0f54d89e49c0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -521,6 +521,7 @@ <java-symbol type="bool" name="config_preferKeepClearForFocus" /> <java-symbol type="bool" name="config_hibernationDeletesOatArtifactsEnabled"/> <java-symbol type="integer" name="config_defaultAnalogClockSecondsHandFps"/> + <java-symbol type="bool" name="config_notificationCloseButtonSupported"/> <java-symbol type="bool" name="config_enableGaiaEducationInPrivateSpace"/> <java-symbol type="color" name="tab_indicator_text_v4" /> @@ -2298,9 +2299,6 @@ <java-symbol type="array" name="config_disabledDreamComponents" /> <java-symbol type="bool" name="config_dismissDreamOnActivityStart" /> <java-symbol type="bool" name="config_resetScreenTimeoutOnUnexpectedDreamExit" /> - <java-symbol type="integer" name="config_dreamOverlayReconnectTimeoutMs" /> - <java-symbol type="integer" name="config_dreamOverlayMaxReconnectAttempts" /> - <java-symbol type="integer" name="config_minDreamOverlayDurationMs" /> <java-symbol type="array" name="config_loggable_dream_prefixes" /> <java-symbol type="string" name="config_dozeComponent" /> <java-symbol type="string" name="enable_explore_by_touch_warning_title" /> @@ -3171,6 +3169,7 @@ <java-symbol type="id" name="header_text_secondary_divider" /> <java-symbol type="drawable" name="ic_expand_notification" /> <java-symbol type="drawable" name="ic_collapse_notification" /> + <java-symbol type="drawable" name="notification_close_button_icon" /> <java-symbol type="drawable" name="ic_expand_bundle" /> <java-symbol type="drawable" name="ic_collapse_bundle" /> <java-symbol type="drawable" name="ic_notification_summary_auto" /> @@ -3877,6 +3876,7 @@ <java-symbol type="string" name="expand_button_content_description_collapsed" /> <java-symbol type="string" name="expand_button_content_description_expanded" /> + <java-symbol type="string" name="close_button_text" /> <java-symbol type="string" name="content_description_collapsed" /> <java-symbol type="string" name="content_description_expanded" /> @@ -4462,6 +4462,8 @@ <java-symbol type="string" name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" /> <java-symbol type="string" name="accessibility_system_action_hardware_a11y_shortcut_label" /> <java-symbol type="string" name="accessibility_system_action_dismiss_notification_shade" /> + <java-symbol type="string" name="accessibility_system_action_menu_label" /> + <java-symbol type="string" name="accessibility_system_action_media_play_pause_label" /> <java-symbol type="string" name="accessibility_system_action_dpad_up_label" /> <java-symbol type="string" name="accessibility_system_action_dpad_down_label" /> <java-symbol type="string" name="accessibility_system_action_dpad_left_label" /> @@ -5042,6 +5044,9 @@ <java-symbol type="string" name="ui_translation_accessibility_translation_finished" /> <java-symbol type="layout" name="notification_expand_button"/> + <java-symbol type="id" name="close_button" /> + <java-symbol type="layout" name="notification_close_button"/> + <java-symbol type="id" name="notification_buttons_column" /> <java-symbol type="bool" name="config_supportsMicToggle" /> <java-symbol type="bool" name="config_supportsCamToggle" /> diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index 41696dfa782e..d2771691c50c 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -63,6 +63,7 @@ android_test { "-c fa", ], static_libs: [ + "A11yChecker", "collector-device-lib-platform", "frameworks-base-testutils", "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport diff --git a/core/tests/coretests/src/android/view/accessibility/a11ychecker/AccessibilityNodePathBuilderTest.java b/core/tests/coretests/src/android/view/accessibility/a11ychecker/AccessibilityNodePathBuilderTest.java new file mode 100644 index 000000000000..438277b272cb --- /dev/null +++ b/core/tests/coretests/src/android/view/accessibility/a11ychecker/AccessibilityNodePathBuilderTest.java @@ -0,0 +1,145 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.accessibility.a11ychecker; + +import static android.view.accessibility.a11ychecker.MockAccessibilityNodeInfoBuilder.PACKAGE_NAME; + +import static com.google.common.truth.Truth.assertThat; + +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.widget.RecyclerView; + +import com.google.common.collect.ImmutableList; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class AccessibilityNodePathBuilderTest { + + public static final String RESOURCE_ID_PREFIX = PACKAGE_NAME + ":id/"; + + @Test + public void createNodePath_pathWithResourceNames() { + AccessibilityNodeInfo child = new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName(RESOURCE_ID_PREFIX + "child_node") + .build(); + AccessibilityNodeInfo parent = + new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName(RESOURCE_ID_PREFIX + "parent_node") + .addChildren(ImmutableList.of(child)) + .build(); + AccessibilityNodeInfo root = + new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName(RESOURCE_ID_PREFIX + "root_node") + .addChildren(ImmutableList.of(parent)) + .build(); + + assertThat(AccessibilityNodePathBuilder.createNodePath(child)) + .isEqualTo(PACKAGE_NAME + ":root_node/parent_node[1]/child_node[1]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(parent)) + .isEqualTo(PACKAGE_NAME + ":root_node/parent_node[1]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(root)) + .isEqualTo(PACKAGE_NAME + ":root_node"); + } + + @Test + public void createNodePath_pathWithoutResourceNames() { + AccessibilityNodeInfo child = + new MockAccessibilityNodeInfoBuilder() + .setClassName(TextView.class.getName()) + .build(); + AccessibilityNodeInfo parent = + + new MockAccessibilityNodeInfoBuilder() + .setClassName(RecyclerView.class.getName()) + .addChildren(ImmutableList.of(child)) + .build(); + AccessibilityNodeInfo root = + new MockAccessibilityNodeInfoBuilder() + .setClassName(FrameLayout.class.getName()) + .addChildren(ImmutableList.of(parent)) + .build(); + + assertThat(AccessibilityNodePathBuilder.createNodePath(child)) + .isEqualTo(PACKAGE_NAME + ":FrameLayout/RecyclerView[1]/TextView[1]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(parent)) + .isEqualTo(PACKAGE_NAME + ":FrameLayout/RecyclerView[1]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(root)) + .isEqualTo(PACKAGE_NAME + ":FrameLayout"); + } + + @Test + public void createNodePath_parentWithMultipleChildren() { + AccessibilityNodeInfo child1 = + new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName(RESOURCE_ID_PREFIX + "child1") + .build(); + AccessibilityNodeInfo child2 = + new MockAccessibilityNodeInfoBuilder() + .setClassName(TextView.class.getName()) + .build(); + AccessibilityNodeInfo parent = + new MockAccessibilityNodeInfoBuilder() + .setClassName(FrameLayout.class.getName()) + .addChildren(ImmutableList.of(child1, child2)) + .build(); + + assertThat(AccessibilityNodePathBuilder.createNodePath(child1)) + .isEqualTo(PACKAGE_NAME + ":FrameLayout/child1[1]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(child2)) + .isEqualTo(PACKAGE_NAME + ":FrameLayout/TextView[2]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(parent)) + .isEqualTo(PACKAGE_NAME + ":FrameLayout"); + } + + @Test + public void createNodePath_handlesDifferentIdFormats() { + AccessibilityNodeInfo child1 = + new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName(RESOURCE_ID_PREFIX + "childId") + .build(); + AccessibilityNodeInfo child2 = + new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName(RESOURCE_ID_PREFIX + "child/Id/With/Slash") + .build(); + AccessibilityNodeInfo child3 = + new MockAccessibilityNodeInfoBuilder() + .setViewIdResourceName("childIdWithoutPrefix") + .build(); + AccessibilityNodeInfo parent = + new MockAccessibilityNodeInfoBuilder() + .addChildren(ImmutableList.of(child1, child2, child3)) + .setViewIdResourceName(RESOURCE_ID_PREFIX + "parentId") + .build(); + + assertThat(AccessibilityNodePathBuilder.createNodePath(child1)) + .isEqualTo(PACKAGE_NAME + ":parentId/childId[1]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(child2)) + .isEqualTo(PACKAGE_NAME + ":parentId/child/Id/With/Slash[2]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(child3)) + .isEqualTo(PACKAGE_NAME + ":parentId/childIdWithoutPrefix[3]"); + assertThat(AccessibilityNodePathBuilder.createNodePath(parent)) + .isEqualTo(PACKAGE_NAME + ":parentId"); + } + +} diff --git a/core/tests/coretests/src/android/view/accessibility/a11ychecker/MockAccessibilityNodeInfoBuilder.java b/core/tests/coretests/src/android/view/accessibility/a11ychecker/MockAccessibilityNodeInfoBuilder.java new file mode 100644 index 000000000000..e363f0c81720 --- /dev/null +++ b/core/tests/coretests/src/android/view/accessibility/a11ychecker/MockAccessibilityNodeInfoBuilder.java @@ -0,0 +1,58 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.accessibility.a11ychecker; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.view.accessibility.AccessibilityNodeInfo; + +import java.util.List; + +final class MockAccessibilityNodeInfoBuilder { + static final String PACKAGE_NAME = "com.example.app"; + private final AccessibilityNodeInfo mMockNodeInfo = mock(AccessibilityNodeInfo.class); + + MockAccessibilityNodeInfoBuilder() { + when(mMockNodeInfo.getPackageName()).thenReturn(PACKAGE_NAME); + } + + MockAccessibilityNodeInfoBuilder setClassName(String className) { + when(mMockNodeInfo.getClassName()).thenReturn(className); + return this; + } + + MockAccessibilityNodeInfoBuilder setViewIdResourceName(String + viewIdResourceName) { + when(mMockNodeInfo.getViewIdResourceName()).thenReturn(viewIdResourceName); + return this; + } + + MockAccessibilityNodeInfoBuilder addChildren(List<AccessibilityNodeInfo> + children) { + when(mMockNodeInfo.getChildCount()).thenReturn(children.size()); + for (int i = 0; i < children.size(); i++) { + when(mMockNodeInfo.getChild(i)).thenReturn(children.get(i)); + when(children.get(i).getParent()).thenReturn(mMockNodeInfo); + } + return this; + } + + AccessibilityNodeInfo build() { + return mMockNodeInfo; + } +} diff --git a/core/tests/coretests/src/android/view/accessibility/a11ychecker/OWNERS b/core/tests/coretests/src/android/view/accessibility/a11ychecker/OWNERS new file mode 100644 index 000000000000..872a1804555b --- /dev/null +++ b/core/tests/coretests/src/android/view/accessibility/a11ychecker/OWNERS @@ -0,0 +1,5 @@ +# Android Accessibility Framework owners +include /core/java/android/view/accessibility/a11ychecker/OWNERS +include /services/accessibility/OWNERS + +yaraabdullatif@google.com diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java index 24aea371c094..ecf4eb4502df 100644 --- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java +++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java @@ -17,7 +17,6 @@ package android.security; import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; @@ -112,29 +111,6 @@ public class AndroidKeyStoreMaintenance { } /** - * Informs Keystore 2.0 about changing user's password - * - * @param userId - Android user id of the user - * @param password - a secret derived from the synthetic password provided by the - * LockSettingsService - * @return 0 if successful or a {@code ResponseCode} - * @hide - */ - public static int onUserPasswordChanged(int userId, @Nullable byte[] password) { - StrictMode.noteDiskWrite(); - try { - getService().onUserPasswordChanged(userId, password); - return 0; - } catch (ServiceSpecificException e) { - Log.e(TAG, "onUserPasswordChanged failed", e); - return e.errorCode; - } catch (Exception e) { - Log.e(TAG, "Can not connect to keystore", e); - return SYSTEM_ERROR; - } - } - - /** * Tells Keystore that a user's LSKF is being removed, ie the user's lock screen is changing to * Swipe or None. Keystore uses this notification to delete the user's auth-bound keys. * diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index d5eaedd385f8..7ddda1f98809 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -904,14 +904,23 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @GuardedBy("mLock") void updateContainersInTaskIfVisible(@NonNull WindowContainerTransaction wct, int taskId) { final TaskContainer taskContainer = getTaskContainer(taskId); - if (taskContainer != null && taskContainer.isVisible()) { + if (taskContainer == null) { + return; + } + + if (taskContainer.isVisible()) { updateContainersInTask(wct, taskContainer); + } else if (Flags.fixNoContainerUpdateWithoutResize()) { + // the TaskFragmentContainers need to be updated when the task becomes visible + taskContainer.mTaskFragmentContainersNeedsUpdate = true; } } @GuardedBy("mLock") private void updateContainersInTask(@NonNull WindowContainerTransaction wct, @NonNull TaskContainer taskContainer) { + taskContainer.mTaskFragmentContainersNeedsUpdate = false; + // Update all TaskFragments in the Task. Make a copy of the list since some may be // removed on updating. final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers(); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java index ee00c4cd67eb..20ad53ee19a8 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java @@ -108,6 +108,12 @@ class TaskContainer { private boolean mPlaceholderRuleSuppressed; /** + * {@code true} if the TaskFragments in this Task needs to be updated next time the Task + * becomes visible. See {@link #shouldUpdateContainer(TaskFragmentParentInfo)} + */ + boolean mTaskFragmentContainersNeedsUpdate; + + /** * The {@link TaskContainer} constructor * * @param taskId The ID of the Task, which must match {@link Activity#getTaskId()} with @@ -185,7 +191,8 @@ class TaskContainer { // If the task properties equals regardless of starting position, don't // need to update the container. - return mInfo.getConfiguration().diffPublicOnly(configuration) != 0 + return mTaskFragmentContainersNeedsUpdate + || mInfo.getConfiguration().diffPublicOnly(configuration) != 0 || mInfo.getDisplayId() != info.getDisplayId(); } diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml index 34f03c2f226b..501bedd50f55 100644 --- a/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml +++ b/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml @@ -19,7 +19,7 @@ android:layout_height="wrap_content" android:layout_width="wrap_content" android:orientation="vertical" - android:id="@+id/bubble_bar_expanded_view"> + android:id="@+id/bubble_expanded_view"> <com.android.wm.shell.bubbles.bar.BubbleBarHandleView android:id="@+id/bubble_bar_handle_view" diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java index 6ffeb97f50fa..58007b50350b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java @@ -27,7 +27,9 @@ import android.util.DisplayMetrics; import android.util.Size; import android.view.Gravity; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.io.PrintWriter; @@ -39,6 +41,9 @@ public class PipBoundsAlgorithm { private static final String TAG = PipBoundsAlgorithm.class.getSimpleName(); private static final float INVALID_SNAP_FRACTION = -1f; + // The same value (with the same name) is used in Launcher. + private static final float PIP_ASPECT_RATIO_MISMATCH_THRESHOLD = 0.01f; + @NonNull private final PipBoundsState mPipBoundsState; @NonNull protected final PipDisplayLayoutState mPipDisplayLayoutState; @NonNull protected final SizeSpecSource mSizeSpecSource; @@ -206,9 +211,27 @@ public class PipBoundsAlgorithm { */ public static boolean isSourceRectHintValidForEnterPip(Rect sourceRectHint, Rect destinationBounds) { - return sourceRectHint != null - && sourceRectHint.width() > destinationBounds.width() - && sourceRectHint.height() > destinationBounds.height(); + if (sourceRectHint == null || sourceRectHint.isEmpty()) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "isSourceRectHintValidForEnterPip=false, empty hint"); + return false; + } + if (sourceRectHint.width() <= destinationBounds.width() + || sourceRectHint.height() <= destinationBounds.height()) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "isSourceRectHintValidForEnterPip=false, hint(%s) is smaller" + + " than destination(%s)", sourceRectHint, destinationBounds); + return false; + } + final float reportedRatio = destinationBounds.width() / (float) destinationBounds.height(); + final float inferredRatio = sourceRectHint.width() / (float) sourceRectHint.height(); + if (Math.abs(reportedRatio - inferredRatio) > PIP_ASPECT_RATIO_MISMATCH_THRESHOLD) { + ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, + "isSourceRectHintValidForEnterPip=false, hint(%s) does not match" + + " destination(%s) aspect ratio", sourceRectHint, destinationBounds); + return false; + } + return true; } public float getDefaultAspectRatio() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt index a09720dd6a70..3e9366fd6459 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt @@ -34,6 +34,7 @@ import com.android.internal.protolog.common.ProtoLog import com.android.wm.shell.Flags import com.android.wm.shell.protolog.ShellProtoLogGroup import kotlin.math.abs +import kotlin.math.roundToInt /** A class that includes convenience methods. */ object PipUtils { @@ -149,16 +150,16 @@ object PipUtils { val appBoundsAspRatio = appBounds.width().toFloat() / appBounds.height() val width: Int val height: Int - var left = 0 - var top = 0 + var left = appBounds.left + var top = appBounds.top if (appBoundsAspRatio < aspectRatio) { width = appBounds.width() - height = Math.round(width / aspectRatio) - top = (appBounds.height() - height) / 2 + height = (width / aspectRatio).roundToInt() + top = appBounds.top + (appBounds.height() - height) / 2 } else { height = appBounds.height() - width = Math.round(height * aspectRatio) - left = (appBounds.width() - width) / 2 + width = (height * aspectRatio).roundToInt() + left = appBounds.left + (appBounds.width() - width) / 2 } return Rect(left, top, left + width, top + height) } 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 1385f42bc676..7ad68aac62c5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS @@ -5,3 +5,4 @@ madym@google.com nmusgrave@google.com pbdr@google.com tkachenkoi@google.com +vaniadesmonda@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java index 202f60dad842..3d1994cac534 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java @@ -137,7 +137,7 @@ public class PipSurfaceTransactionHelper { mTmpDestinationRect.inset(insets); // Scale to the bounds no smaller than the destination and offset such that the top/left // of the scaled inset source rect aligns with the top/left of the destination bounds - final float scale, left, top; + final float scale; if (isInPipDirection && sourceRectHint != null && sourceRectHint.width() < sourceBounds.width()) { // scale by sourceRectHint if it's not edge-to-edge, for entering PiP transition only. @@ -148,14 +148,17 @@ public class PipSurfaceTransactionHelper { ? (float) destinationBounds.width() / sourceBounds.width() : (float) destinationBounds.height() / sourceBounds.height(); scale = (1 - fraction) * startScale + fraction * endScale; - left = destinationBounds.left - insets.left * scale; - top = destinationBounds.top - insets.top * scale; } else { scale = Math.max((float) destinationBounds.width() / sourceBounds.width(), (float) destinationBounds.height() / sourceBounds.height()); - // Work around the rounding error by fix the position at very beginning. - left = scale == 1 ? 0 : destinationBounds.left - insets.left * scale; - top = scale == 1 ? 0 : destinationBounds.top - insets.top * scale; + } + float left = destinationBounds.left - insets.left * scale; + float top = destinationBounds.top - insets.top * scale; + if (scale == 1) { + // Work around the 1 pixel off error by rounding the position down at very beginning. + // We noticed such error from flicker tests, not visually. + left = sourceBounds.left; + top = sourceBounds.top; } mTmpTransform.setScale(scale, scale); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 82add2904c26..e2e1ecde8b56 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -63,7 +63,6 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.RemoteException; import android.os.SystemProperties; -import android.util.Rational; import android.view.Choreographer; import android.view.Display; import android.view.Surface; @@ -128,8 +127,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, SystemProperties.getInt( "persist.wm.debug.extra_content_overlay_fade_out_delay_ms", 400); - private static final float PIP_ASPECT_RATIO_MISMATCH_THRESHOLD = 0.005f; - private final Context mContext; private final SyncTransactionQueue mSyncTransactionQueue; private final PipBoundsState mPipBoundsState; @@ -822,37 +819,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPictureInPictureParams.getTitle()); mPipParamsChangedForwarder.notifySubtitleChanged( mPictureInPictureParams.getSubtitle()); - - if (mPictureInPictureParams.hasSourceBoundsHint() - && mPictureInPictureParams.hasSetAspectRatio()) { - Rational sourceRectHintAspectRatio = new Rational( - mPictureInPictureParams.getSourceRectHint().width(), - mPictureInPictureParams.getSourceRectHint().height()); - if (sourceRectHintAspectRatio.compareTo( - mPictureInPictureParams.getAspectRatio()) != 0) { - ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, - "Aspect ratio of source rect hint (%d/%d) does not match the provided " - + "aspect ratio value (%d/%d). Consider matching them for " - + "improved animation. Future releases might override the " - + "value to match.", - mPictureInPictureParams.getSourceRectHint().width(), - mPictureInPictureParams.getSourceRectHint().height(), - mPictureInPictureParams.getAspectRatio().getNumerator(), - mPictureInPictureParams.getAspectRatio().getDenominator()); - } - if (Math.abs(sourceRectHintAspectRatio.floatValue() - - mPictureInPictureParams.getAspectRatioFloat()) - > PIP_ASPECT_RATIO_MISMATCH_THRESHOLD) { - ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, - "Aspect ratio of source rect hint (%f) does not match the provided " - + "aspect ratio value (%f) and is above threshold of %f. " - + "Consider matching them for improved animation. Future " - + "releases might override the value to match.", - sourceRectHintAspectRatio.floatValue(), - mPictureInPictureParams.getAspectRatioFloat(), - PIP_ASPECT_RATIO_MISMATCH_THRESHOLD); - } - } } mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java index 66b3553bea09..8fc54edcbd4b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java @@ -21,8 +21,6 @@ import static android.graphics.Color.WHITE; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; -import static com.android.window.flags.Flags.windowSessionRelayoutInfo; - import android.annotation.BinderThread; import android.annotation.NonNull; import android.annotation.Nullable; @@ -30,7 +28,6 @@ import android.app.ActivityManager; import android.app.ActivityManager.TaskDescription; import android.graphics.Paint; import android.graphics.Rect; -import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; @@ -139,16 +136,10 @@ public class TaskSnapshotWindow { } try { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout"); - if (windowSessionRelayoutInfo()) { - final WindowRelayoutResult outRelayoutResult = new WindowRelayoutResult(tmpFrames, - tmpMergedConfiguration, surfaceControl, tmpInsetsState, tmpControls); - session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, 0, 0, - outRelayoutResult); - } else { - session.relayoutLegacy(window, layoutParams, -1, -1, View.VISIBLE, 0, 0, 0, - tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState, - tmpControls, new Bundle()); - } + final WindowRelayoutResult outRelayoutResult = new WindowRelayoutResult(tmpFrames, + tmpMergedConfiguration, surfaceControl, tmpInsetsState, tmpControls); + session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, 0, 0, + outRelayoutResult); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } catch (RemoteException e) { snapshotSurface.clearWindowSynced(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java index 5fce5d228d71..956d04c548f7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java @@ -18,6 +18,8 @@ package com.android.wm.shell.windowdecor; import static android.view.WindowManager.TRANSIT_CHANGE; +import static com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_RESIZE_WINDOW; + import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; @@ -33,6 +35,7 @@ import androidx.annotation.Nullable; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.InteractionJankMonitorUtils; import com.android.wm.shell.transition.Transitions; import java.util.function.Supplier; @@ -89,6 +92,10 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback, mDesktopWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds()); mRepositionStartPoint.set(x, y); if (isResizing()) { + // Capture CUJ for re-sizing window in DW mode. + InteractionJankMonitorUtils.beginTracing(CUJ_DESKTOP_MODE_RESIZE_WINDOW, + mDesktopWindowDecoration.mContext, mDesktopWindowDecoration.mTaskSurface, + /* tag= */ null); if (!mDesktopWindowDecoration.mTaskInfo.isFocused) { WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reorder(mDesktopWindowDecoration.mTaskInfo.token, true); @@ -146,6 +153,7 @@ public class VeiledResizeTaskPositioner implements DragPositioningCallback, // won't be called. resetVeilIfVisible(); } + InteractionJankMonitorUtils.endTracing(CUJ_DESKTOP_MODE_RESIZE_WINDOW); } else { final WindowContainerTransaction wct = new WindowContainerTransaction(); DragPositioningCallbackUtility.updateTaskBounds(mRepositionTaskBounds, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java index 5880ffb0dce2..72950a8dc139 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java @@ -88,8 +88,11 @@ public class PipAnimationControllerTest extends ShellTestCase { @Test public void getAnimator_withBounds_returnBoundsAnimator() { + final Rect baseValue = new Rect(0, 0, 100, 100); + final Rect startValue = new Rect(0, 0, 100, 100); + final Rect endValue1 = new Rect(100, 100, 200, 200); final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController - .getAnimator(mTaskInfo, mLeash, new Rect(), new Rect(), new Rect(), null, + .getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue1, null, TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0); assertEquals("Expect ANIM_TYPE_BOUNDS animation", diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 0d0af1110ca4..4d185c69c172 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -28,8 +28,8 @@ #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h> #include <include/gpu/ganesh/vk/GrVkBackendSurface.h> #include <include/gpu/ganesh/vk/GrVkDirectContext.h> +#include <include/gpu/vk/VulkanBackendContext.h> #include <ui/FatVector.h> -#include <vk/GrVkExtensions.h> #include <vk/GrVkTypes.h> #include <sstream> @@ -141,7 +141,8 @@ VulkanManager::~VulkanManager() { mPhysicalDeviceFeatures2 = {}; } -void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) { +void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions, + VkPhysicalDeviceFeatures2& features) { VkResult err; constexpr VkApplicationInfo app_info = { @@ -506,7 +507,7 @@ sk_sp<GrDirectContext> VulkanManager::createContext(GrContextOptions& options, return vkGetInstanceProcAddr(instance, proc_name); }; - GrVkBackendContext backendContext; + skgpu::VulkanBackendContext backendContext; backendContext.fInstance = mInstance; backendContext.fPhysicalDevice = mPhysicalDevice; backendContext.fDevice = mDevice; diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index b92ebb3cdf71..08f9d4253d7e 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -24,8 +24,7 @@ #include <SkSurface.h> #include <android-base/unique_fd.h> #include <utils/StrongPointer.h> -#include <vk/GrVkBackendContext.h> -#include <vk/GrVkExtensions.h> +#include <vk/VulkanExtensions.h> #include <vulkan/vulkan.h> // VK_ANDROID_frame_boundary is a bespoke extension defined by AGI @@ -127,7 +126,7 @@ private: // Sets up the VkInstance and VkDevice objects. Also fills out the passed in // VkPhysicalDeviceFeatures struct. - void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&); + void setupDevice(skgpu::VulkanExtensions&, VkPhysicalDeviceFeatures2&); // simple wrapper class that exists only to initialize a pointer to NULL template <typename FNPTR_TYPE> @@ -206,7 +205,7 @@ private: BufferAge, }; SwapBehavior mSwapBehavior = SwapBehavior::Discard; - GrVkExtensions mExtensions; + skgpu::VulkanExtensions mExtensions; uint32_t mDriverVersion = 0; std::once_flag mInitFlag; diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 386a606c61c6..e134c23dfbca 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -4069,8 +4069,10 @@ public class AudioManager { private boolean delegateSoundEffectToVdm(@SystemSoundEffect int effectType) { if (hasCustomPolicyVirtualDeviceContext()) { VirtualDeviceManager vdm = getVirtualDeviceManager(); - vdm.playSoundEffect(mOriginalContextDeviceId, effectType); - return true; + if (vdm != null) { + vdm.playSoundEffect(mOriginalContextDeviceId, effectType); + return true; + } } return false; } diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java index 0589c0f12ab6..e048d5c56cfe 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -26,6 +26,7 @@ import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.net.Uri; import android.os.Bundle; @@ -813,6 +814,34 @@ public final class MediaRoute2Info implements Parcelable { || mAllowedPackages.contains(packageName); } + /** + * Returns whether this route's type can only be published by the system route provider. + * + * @see #isSystemRoute() + * @hide + */ + // The default case catches all other types. + @SuppressLint("SwitchIntDef") + public boolean isSystemRouteType() { + return switch (mType) { + case TYPE_BUILTIN_SPEAKER, + TYPE_BLUETOOTH_A2DP, + TYPE_DOCK, + TYPE_BLE_HEADSET, + TYPE_HEARING_AID, + TYPE_HDMI, + TYPE_HDMI_ARC, + TYPE_HDMI_EARC, + TYPE_USB_ACCESSORY, + TYPE_USB_DEVICE, + TYPE_USB_HEADSET, + TYPE_WIRED_HEADPHONES, + TYPE_WIRED_HEADSET -> + true; + default -> false; + }; + } + /** Returns the route suitability status. */ @SuitabilityStatus @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES) diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index cce3d4fc67d5..a14f1fd15f27 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -475,9 +475,25 @@ public abstract class MediaRoute2ProviderService extends Service { */ public final void notifyRoutes(@NonNull Collection<MediaRoute2Info> routes) { Objects.requireNonNull(routes, "routes must not be null"); - mProviderInfo = new MediaRoute2ProviderInfo.Builder() - .addRoutes(routes) - .build(); + List<MediaRoute2Info> sanitizedRoutes = new ArrayList<>(routes.size()); + + for (MediaRoute2Info route : routes) { + if (route.isSystemRouteType()) { + Log.w( + TAG, + "Attempting to add a system route type from a non-system route " + + "provider. Overriding type to TYPE_UNKNOWN. Route: " + + route); + sanitizedRoutes.add( + new MediaRoute2Info.Builder(route) + .setType(MediaRoute2Info.TYPE_UNKNOWN) + .build()); + } else { + sanitizedRoutes.add(route); + } + } + + mProviderInfo = new MediaRoute2ProviderInfo.Builder().addRoutes(sanitizedRoutes).build(); schedulePublishState(); } diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java index 5770c5104dee..66ab81bf02b1 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java @@ -16,10 +16,7 @@ package com.android.companiondevicemanager; -import static android.companion.CompanionDeviceManager.REASON_CANCELED; -import static android.companion.CompanionDeviceManager.REASON_DISCOVERY_TIMEOUT; -import static android.companion.CompanionDeviceManager.REASON_INTERNAL_ERROR; -import static android.companion.CompanionDeviceManager.REASON_USER_REJECTED; +import static android.companion.CompanionDeviceManager.RESULT_CANCELED; import static android.companion.CompanionDeviceManager.RESULT_DISCOVERY_TIMEOUT; import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR; import static android.companion.CompanionDeviceManager.RESULT_USER_REJECTED; @@ -234,8 +231,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false); if (forCancelDialog) { Slog.i(TAG, "Cancelling the user confirmation"); - cancel(/* discoveryTimeOut */ false, /* userRejected */ false, - /* internalError */ false); + cancel(RESULT_CANCELED); return; } @@ -243,8 +239,14 @@ public class CompanionAssociationActivity extends FragmentActivity implements // yet). We can only "process" one request at a time. final IAssociationRequestCallback appCallback = IAssociationRequestCallback.Stub .asInterface(intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK)); + + if (appCallback == null) { + return; + } + Slog.e(TAG, "More than one AssociationRequests are processing."); + try { - requireNonNull(appCallback).onFailure("Busy."); + appCallback.onFailure(RESULT_INTERNAL_ERROR); } catch (RemoteException ignore) { } } @@ -255,8 +257,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements // TODO: handle config changes without cancelling. if (!isDone()) { - cancel(/* discoveryTimeOut */ false, - /* userRejected */ false, /* internalError */ false); // will finish() + cancel(RESULT_CANCELED); // will finish() } } @@ -330,8 +331,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements && CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) { synchronized (LOCK) { if (sDiscoveryStarted) { - cancel(/* discoveryTimeOut */ true, - /* userRejected */ false, /* internalError */ false); + cancel(RESULT_DISCOVERY_TIMEOUT); } } } @@ -371,7 +371,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements mCdmServiceReceiver.send(RESULT_CODE_ASSOCIATION_APPROVED, data); } - private void cancel(boolean discoveryTimeout, boolean userRejected, boolean internalError) { + private void cancel(int failureCode) { if (isDone()) { Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); return; @@ -379,35 +379,19 @@ public class CompanionAssociationActivity extends FragmentActivity implements mCancelled = true; // Stop discovery service if it was used. - if (!mRequest.isSelfManaged() || discoveryTimeout) { + if (!mRequest.isSelfManaged()) { CompanionDeviceDiscoveryService.stop(this); } - final String cancelReason; - final int resultCode; - if (userRejected) { - cancelReason = REASON_USER_REJECTED; - resultCode = RESULT_USER_REJECTED; - } else if (discoveryTimeout) { - cancelReason = REASON_DISCOVERY_TIMEOUT; - resultCode = RESULT_DISCOVERY_TIMEOUT; - } else if (internalError) { - cancelReason = REASON_INTERNAL_ERROR; - resultCode = RESULT_INTERNAL_ERROR; - } else { - cancelReason = REASON_CANCELED; - resultCode = CompanionDeviceManager.RESULT_CANCELED; - } - // First send callback to the app directly... try { - Slog.i(TAG, "Sending onFailure to app due to reason=" + cancelReason); - mAppCallback.onFailure(cancelReason); + Slog.i(TAG, "Sending onFailure to app due to failureCode=" + failureCode); + mAppCallback.onFailure(failureCode); } catch (RemoteException ignore) { } // ... then set result and finish ("sending" onActivityResult()). - setResultAndFinish(null, resultCode); + setResultAndFinish(null, failureCode); } private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) { @@ -452,8 +436,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements } } catch (PackageManager.NameNotFoundException e) { Slog.e(TAG, "Package u" + userId + "/" + packageName + " not found."); - cancel(/* discoveryTimeout */ false, - /* userRejected */ false, /* internalError */ true); + cancel(RESULT_INTERNAL_ERROR); return; } @@ -637,7 +620,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements // Disable the button, to prevent more clicks. v.setEnabled(false); - cancel(/* discoveryTimeout */ false, /* userRejected */ true, /* internalError */ false); + cancel(RESULT_USER_REJECTED); } private void onShowHelperDialog(View view) { @@ -763,7 +746,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements @Override public void onShowHelperDialogFailed() { - cancel(/* discoveryTimeout */ false, /* userRejected */ false, /* internalError */ true); + cancel(RESULT_INTERNAL_ERROR); } @Override diff --git a/packages/CtsShim/apk/riscv64/CtsShim.apk b/packages/CtsShim/apk/riscv64/CtsShim.apk Binary files differindex af306a504d30..5ab190d19514 100644 --- a/packages/CtsShim/apk/riscv64/CtsShim.apk +++ b/packages/CtsShim/apk/riscv64/CtsShim.apk diff --git a/packages/CtsShim/apk/riscv64/CtsShimPriv.apk b/packages/CtsShim/apk/riscv64/CtsShimPriv.apk Binary files differindex 9a9997dc4155..441f86f04625 100644 --- a/packages/CtsShim/apk/riscv64/CtsShimPriv.apk +++ b/packages/CtsShim/apk/riscv64/CtsShimPriv.apk diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS index 5966c9f759fb..62ed66cdce67 100644 --- a/packages/SettingsLib/OWNERS +++ b/packages/SettingsLib/OWNERS @@ -11,3 +11,6 @@ ykhung@google.com # Exempt resource files (because they are in a flat directory and too hard to manage via OWNERS) per-file *.xml=* + +# Notification-related utilities +per-file */notification/* = file:/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig index 32557b979bf5..a1587562d681 100644 --- a/packages/SettingsLib/aconfig/settingslib.aconfig +++ b/packages/SettingsLib/aconfig/settingslib.aconfig @@ -79,3 +79,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "enable_determining_spatial_audio_attributes_by_profile" + namespace: "cross_device_experiences" + description: "Use bluetooth profile connection policy to determine spatial audio attributes" + bug: "341005211" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt index 20b949f4a30f..8ec5ba193dba 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt @@ -20,6 +20,7 @@ import android.content.ContentResolver import android.database.ContentObserver import android.media.AudioDeviceInfo import android.media.AudioManager +import android.media.AudioManager.AudioDeviceCategory import android.media.AudioManager.OnCommunicationDeviceChangedListener import android.provider.Settings import androidx.concurrent.futures.DirectExecutor @@ -85,6 +86,10 @@ interface AudioRepository { suspend fun setMuted(audioStream: AudioStream, isMuted: Boolean): Boolean suspend fun setRingerMode(audioStream: AudioStream, mode: RingerMode) + + /** Gets audio device category. */ + @AudioDeviceCategory + suspend fun getBluetoothAudioDeviceCategory(bluetoothAddress: String): Int } class AudioRepositoryImpl( @@ -211,6 +216,13 @@ class AudioRepositoryImpl( withContext(backgroundCoroutineContext) { audioManager.ringerMode = mode.value } } + @AudioDeviceCategory + override suspend fun getBluetoothAudioDeviceCategory(bluetoothAddress: String): Int { + return withContext(backgroundCoroutineContext) { + audioManager.getBluetoothAudioDeviceCategory(bluetoothAddress) + } + } + private fun getMinVolume(stream: AudioStream): Int = try { audioManager.getStreamMinVolume(stream.value) diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt index 683759db95f9..844dc12ee911 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/volume/data/repository/AudioRepositoryTest.kt @@ -247,6 +247,19 @@ class AudioRepositoryTest { } } + @Test + fun getBluetoothAudioDeviceCategory() { + testScope.runTest { + `when`(audioManager.getBluetoothAudioDeviceCategory("12:34:56:78")).thenReturn( + AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES) + + val category = underTest.getBluetoothAudioDeviceCategory("12:34:56:78") + runCurrent() + + assertThat(category).isEqualTo(AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES) + } + } + private fun triggerConnectedDeviceChange(communicationDevice: AudioDeviceInfo?) { verify(audioManager) .addOnCommunicationDeviceChangedListener( diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index fde7c2caca06..bd7c9a0e1e55 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -98,13 +98,66 @@ filegroup { ], } -// Tests where robolectric failed at runtime. (go/multivalent-tests) +// Tests where robolectric failed at runtime. (go/central-multivalent) filegroup { name: "SystemUI-tests-broken-robofiles-run", srcs: [ + "tests/src/**/systemui/ExpandHelperTest.java", + "tests/src/**/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java", + "tests/src/**/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java", + "tests/src/**/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java", + "tests/src/**/systemui/screenshot/appclips/AppClipsActivityTest.java", + "tests/src/**/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java", + "tests/src/**/systemui/screenshot/appclips/AppClipsViewModelTest.java", + "tests/src/**/systemui/appops/AppOpsControllerTest.java", + "tests/src/**/systemui/biometrics/BiometricNotificationServiceTest.java", + "tests/src/**/systemui/bluetooth/BroadcastDialogDelegateTest.java", + "tests/src/**/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java", + "tests/src/**/systemui/communal/data/backup/CommunalBackupHelperTest.kt", + "tests/src/**/systemui/controls/ui/ControlsPopupMenuTest.kt", + "tests/src/**/systemui/classifier/DistanceClassifierTest.java", + "tests/src/**/systemui/doze/DozeScreenBrightnessTest.java", + "tests/src/**/systemui/doze/DozeSensorsTest.java", + "tests/src/**/systemui/doze/DozeTriggersTest.java", + "tests/src/**/systemui/classifier/FalsingDataProviderTest.java", + "tests/src/**/systemui/screenshot/ImageExporterTest.java", + "tests/src/**/systemui/bouncer/data/repository/KeyguardBouncerRepositoryTest.kt", + "tests/src/**/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt", + "tests/src/**/systemui/logcat/LogAccessDialogActivityTest.java", + "tests/src/**/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt", + "tests/src/**/systemui/media/controls/domain/pipeline/MediaSessionBasedFilterTest.kt", + "tests/src/**/systemui/accessibility/floatingmenu/MenuNotificationFactoryTest.java", + "tests/src/**/systemui/accessibility/floatingmenu/MenuViewLayerTest.java", + "tests/src/**/systemui/accessibility/floatingmenu/MenuViewTest.java", + "tests/src/**/systemui/classifier/PointerCountClassifierTest.java", + "tests/src/**/systemui/qs/tileimpl/QSIconViewImplTest_311121830.kt", + "tests/src/**/systemui/accessibility/floatingmenu/RadiiAnimatorTest.java", + "tests/src/**/systemui/screenrecord/RecordingControllerTest.java", + "tests/src/**/systemui/screenshot/RequestProcessorTest.kt", + "tests/src/**/systemui/media/controls/domain/resume/ResumeMediaBrowserTest.kt", + "tests/src/**/systemui/screenshot/SaveImageInBackgroundTaskTest.kt", + "tests/src/**/systemui/screenshot/scroll/ScrollCaptureClientTest.java", + "tests/src/**/systemui/accessibility/SecureSettingsContentObserverTest.java", + "tests/src/**/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt", + "tests/src/**/systemui/qs/external/TileServicesTest.java", + "tests/src/**/systemui/ambient/touch/TouchMonitorTest.java", + "tests/src/**/systemui/accessibility/WindowMagnificationControllerWindowlessMagnifierTest.java", + "tests/src/**/systemui/accessibility/WindowMagnificationSettingsTest.java", + "tests/src/androidx/core/animation/AnimatorTestRuleIsolationTest.kt", + "tests/src/**/systemui/CameraProtectionLoaderImplTest.kt", + "tests/src/**/systemui/DependencyTest.java", + "tests/src/**/systemui/InitControllerTest.java", + "tests/src/**/systemui/SliceBroadcastRelayHandlerTest.java", + "tests/src/**/systemui/SystemUIApplicationTest.kt", + "tests/src/**/systemui/SysUICutoutProviderTest.kt", + "tests/src/**/keyguard/ActiveUnlockConfigTest.kt", + "tests/src/**/keyguard/AdminSecondaryLockScreenControllerTest.java", + "tests/src/**/keyguard/KeyguardClockAccessibilityDelegateTest.java", + "tests/src/**/keyguard/KeyguardStatusViewControllerTest.java", "tests/src/**/systemui/accessibility/AccessibilityButtonModeObserverTest.java", "tests/src/**/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java", "tests/src/**/systemui/accessibility/FullscreenMagnificationControllerTest.java", + "tests/src/**/systemui/accessibility/MagnificationTest.java", "tests/src/**/systemui/accessibility/WindowMagnificationAnimationControllerTest.java", "tests/src/**/systemui/animation/FontInterpolatorTest.kt", "tests/src/**/systemui/animation/TextAnimatorTest.kt", @@ -160,6 +213,7 @@ filegroup { "tests/src/**/systemui/statusbar/KeyboardShortcutsTest.java", "tests/src/**/systemui/statusbar/KeyguardIndicationControllerWithCoroutinesTest.kt", "tests/src/**/systemui/statusbar/notification/AssistantFeedbackControllerTest.java", + "tests/src/**/systemui/statusbar/notification/PropertyAnimatorTest.java", "tests/src/**/systemui/statusbar/notification/collection/NotifCollectionTest.java", "tests/src/**/systemui/statusbar/notification/collection/NotificationEntryTest.java", "tests/src/**/systemui/statusbar/notification/collection/render/GroupExpansionManagerTest.kt", diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt index 18085ab29135..7d829208ee89 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt @@ -29,6 +29,7 @@ import com.android.systemui.communal.smartspace.SmartspaceInteractionHandler import com.android.systemui.communal.ui.compose.section.AmbientStatusBarSection import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.keyguard.ui.composable.blueprint.BlueprintAlignmentLines +import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection import com.android.systemui.keyguard.ui.composable.section.LockSection import com.android.systemui.statusbar.phone.SystemUIDialogFactory import javax.inject.Inject @@ -41,8 +42,10 @@ constructor( private val interactionHandler: SmartspaceInteractionHandler, private val dialogFactory: SystemUIDialogFactory, private val lockSection: LockSection, + private val bottomAreaSection: BottomAreaSection, private val ambientStatusBarSection: AmbientStatusBarSection, ) { + @Composable fun SceneScope.Content(modifier: Modifier = Modifier) { Layout( @@ -65,10 +68,16 @@ constructor( modifier = Modifier.element(Communal.Elements.LockIcon) ) } + with(bottomAreaSection) { + IndicationArea( + Modifier.element(Communal.Elements.IndicationArea).fillMaxWidth() + ) + } } ) { measurables, constraints -> val communalGridMeasurable = measurables[0] val lockIconMeasurable = measurables[1] + val bottomAreaMeasurable = measurables[2] val noMinConstraints = constraints.copy( @@ -85,6 +94,13 @@ constructor( bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom], ) + val bottomAreaPlaceable = + bottomAreaMeasurable.measure( + noMinConstraints.copy( + maxHeight = (constraints.maxHeight - lockIconBounds.bottom).coerceAtLeast(0) + ) + ) + val communalGridPlaceable = communalGridMeasurable.measure( noMinConstraints.copy(maxHeight = lockIconBounds.top) @@ -99,6 +115,10 @@ constructor( x = lockIconBounds.left, y = lockIconBounds.top, ) + bottomAreaPlaceable.place( + x = 0, + y = constraints.maxHeight - bottomAreaPlaceable.height, + ) } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index 4dc801c9a701..7062489dd393 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -52,10 +52,12 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridItemSpan @@ -75,12 +77,15 @@ import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonColors import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State @@ -153,7 +158,7 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.phone.SystemUIDialogFactory import kotlinx.coroutines.launch -@OptIn(ExperimentalComposeUiApi::class) +@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class) @Composable fun CommunalHub( modifier: Modifier = Modifier, @@ -378,6 +383,33 @@ fun CommunalHub( onCancel = viewModel::onEnableWorkProfileDialogCancel ) } + + if (viewModel is CommunalEditModeViewModel) { + val showBottomSheet by viewModel.showDisclaimer.collectAsStateWithLifecycle(false) + + if (showBottomSheet) { + val scope = rememberCoroutineScope() + val sheetState = rememberModalBottomSheetState() + val colors = LocalAndroidColorScheme.current + + ModalBottomSheet( + onDismissRequest = viewModel::onDisclaimerDismissed, + sheetState = sheetState, + dragHandle = null, + containerColor = colors.surfaceContainer, + ) { + DisclaimerBottomSheetContent { + scope + .launch { sheetState.hide() } + .invokeOnCompletion { + if (!sheetState.isVisible) { + viewModel.onDisclaimerDismissed() + } + } + } + } + } + } } } @@ -389,6 +421,47 @@ private fun onMotionEvent(viewModel: BaseCommunalViewModel) { viewModel.signalUserInteraction() } +@Composable +private fun DisclaimerBottomSheetContent(onButtonClicked: () -> Unit) { + val colors = LocalAndroidColorScheme.current + + Column( + modifier = Modifier.fillMaxWidth().padding(horizontal = 32.dp, vertical = 24.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Icon( + imageVector = Icons.Outlined.Widgets, + contentDescription = null, + tint = colors.primary, + modifier = Modifier.size(32.dp) + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(R.string.communal_widgets_disclaimer_title), + style = MaterialTheme.typography.headlineMedium, + color = colors.onSurface, + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(R.string.communal_widgets_disclaimer_text), + color = colors.onSurfaceVariant, + ) + Button( + modifier = + Modifier.padding(horizontal = 26.dp, vertical = 16.dp) + .widthIn(min = 200.dp) + .heightIn(min = 56.dp), + onClick = { onButtonClicked() } + ) { + Text( + stringResource(R.string.communal_widgets_disclaimer_button), + style = MaterialTheme.typography.labelLarge, + ) + } + } +} + /** * Observes communal content and scrolls to any added or updated live content, e.g. a new media * session is started, or a paused timer is resumed. diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt index 97d5b41000de..86639fa02a92 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt @@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.DpSize @@ -183,7 +184,7 @@ constructor( indicationController: KeyguardIndicationController, modifier: Modifier = Modifier, ) { - val (disposable, setDisposable) = mutableStateOf<DisposableHandle?>(null) + val (disposable, setDisposable) = remember { mutableStateOf<DisposableHandle?>(null) } AndroidView( factory = { context -> diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt index c2dd80375d5a..ea740a8d8de4 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt @@ -48,8 +48,15 @@ internal fun CoroutineScope.animateToScene( } return when (transitionState) { - is TransitionState.Idle -> - animate(layoutState, target, transitionKey, isInitiatedByUserInput = false) + is TransitionState.Idle -> { + animate( + layoutState, + target, + transitionKey, + isInitiatedByUserInput = false, + replacedTransition = null, + ) + } is TransitionState.Transition -> { val isInitiatedByUserInput = transitionState.isInitiatedByUserInput @@ -79,6 +86,7 @@ internal fun CoroutineScope.animateToScene( isInitiatedByUserInput, initialProgress = progress, initialVelocity = transitionState.progressVelocity, + replacedTransition = transitionState, ) } } else if (transitionState.fromScene == target) { @@ -101,6 +109,7 @@ internal fun CoroutineScope.animateToScene( initialProgress = progress, initialVelocity = transitionState.progressVelocity, reversed = true, + replacedTransition = transitionState, ) } } else { @@ -137,6 +146,7 @@ internal fun CoroutineScope.animateToScene( isInitiatedByUserInput, fromScene = animateFrom, chain = chain, + replacedTransition = null, ) } } @@ -148,6 +158,7 @@ private fun CoroutineScope.animate( targetScene: SceneKey, transitionKey: TransitionKey?, isInitiatedByUserInput: Boolean, + replacedTransition: TransitionState.Transition?, initialProgress: Float = 0f, initialVelocity: Float = 0f, reversed: Boolean = false, @@ -164,6 +175,7 @@ private fun CoroutineScope.animate( currentScene = targetScene, isInitiatedByUserInput = isInitiatedByUserInput, isUserInputOngoing = false, + replacedTransition = replacedTransition, ) } else { OneOffTransition( @@ -173,6 +185,7 @@ private fun CoroutineScope.animate( currentScene = targetScene, isInitiatedByUserInput = isInitiatedByUserInput, isUserInputOngoing = false, + replacedTransition = replacedTransition, ) } @@ -214,7 +227,8 @@ private class OneOffTransition( override val currentScene: SceneKey, override val isInitiatedByUserInput: Boolean, override val isUserInputOngoing: Boolean, -) : TransitionState.Transition(fromScene, toScene) { + replacedTransition: TransitionState.Transition?, +) : TransitionState.Transition(fromScene, toScene, replacedTransition) { /** * The animatable used to animate this transition. * diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt index cfaed41cd275..e313aa52faea 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt @@ -37,7 +37,7 @@ import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Job import kotlinx.coroutines.launch -interface DraggableHandler { +internal interface DraggableHandler { /** * Start a drag in the given [startedPosition], with the given [overSlop] and number of * [pointersDown]. @@ -51,7 +51,7 @@ interface DraggableHandler { * The [DragController] provides control over the transition between two scenes through the [onDrag] * and [onStop] methods. */ -interface DragController { +internal interface DragController { /** Drag the current scene by [delta] pixels. */ fun onDrag(delta: Float) @@ -395,10 +395,11 @@ private class DragControllerImpl( if ( distance != DistanceUnspecified && shouldCommitSwipe( - offset, - distance, - velocity, + offset = offset, + distance = distance, + velocity = velocity, wasCommitted = swipeTransition._currentScene == toScene, + requiresFullDistanceSwipe = swipeTransition.requiresFullDistanceSwipe, ) ) { targetScene = toScene @@ -472,7 +473,12 @@ private class DragControllerImpl( distance: Float, velocity: Float, wasCommitted: Boolean, + requiresFullDistanceSwipe: Boolean, ): Boolean { + if (requiresFullDistanceSwipe && !wasCommitted) { + return offset / distance >= 1f + } + fun isCloserToTarget(): Boolean { return (offset - distance).absoluteValue < offset.absoluteValue } @@ -530,6 +536,8 @@ private fun SwipeTransition( userActionDistanceScope = layoutImpl.userActionDistanceScope, orientation = orientation, isUpOrLeft = isUpOrLeft, + requiresFullDistanceSwipe = result.requiresFullDistanceSwipe, + replacedTransition = null, ) } @@ -545,6 +553,8 @@ private fun SwipeTransition(old: SwipeTransition): SwipeTransition { orientation = old.orientation, isUpOrLeft = old.isUpOrLeft, lastDistance = old.lastDistance, + requiresFullDistanceSwipe = old.requiresFullDistanceSwipe, + replacedTransition = old, ) .apply { _currentScene = old._currentScene @@ -562,9 +572,11 @@ private class SwipeTransition( val userActionDistanceScope: UserActionDistanceScope, override val orientation: Orientation, override val isUpOrLeft: Boolean, + val requiresFullDistanceSwipe: Boolean, + replacedTransition: SwipeTransition?, var lastDistance: Float = DistanceUnspecified, ) : - TransitionState.Transition(_fromScene.key, _toScene.key), + TransitionState.Transition(_fromScene.key, _toScene.key, replacedTransition), TransitionState.HasOverscrollProperties { var _currentScene by mutableStateOf(_fromScene) override val currentScene: SceneKey diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt index 09d11b7988b9..69124c1f6dad 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt @@ -306,7 +306,6 @@ internal class ElementNode( return layout(placeable.width, placeable.height) { place(transition, placeable) } } - @OptIn(ExperimentalComposeUiApi::class) private fun Placeable.PlacementScope.place( transition: TransitionState.Transition?, placeable: Placeable, @@ -496,6 +495,10 @@ private fun prepareInterruption( transition: TransitionState.Transition, previousTransition: TransitionState.Transition, ) { + if (transition.replacedTransition == previousTransition) { + return + } + val sceneStates = element.sceneStates fun updatedSceneState(key: SceneKey): Element.SceneState? { return sceneStates[key]?.also { it.selfUpdateValuesBeforeInterruption() } @@ -561,10 +564,20 @@ private fun reconcileStates( } private fun Element.SceneState.selfUpdateValuesBeforeInterruption() { - offsetBeforeInterruption = lastOffset sizeBeforeInterruption = lastSize - scaleBeforeInterruption = lastScale - alphaBeforeInterruption = lastAlpha + + if (lastAlpha > 0f) { + offsetBeforeInterruption = lastOffset + scaleBeforeInterruption = lastScale + alphaBeforeInterruption = lastAlpha + } else { + // Consider the element as not placed in this scene if it was fully transparent. + // TODO(b/290930950): Look into using derived state inside place() instead to not even place + // the element at all when alpha == 0f. + offsetBeforeInterruption = Offset.Unspecified + scaleBeforeInterruption = Scale.Unspecified + alphaBeforeInterruption = Element.AlphaUnspecified + } } private fun Element.SceneState.updateValuesBeforeInterruption(lastState: Element.SceneState) { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt index 33063c893814..7c8fce8f297d 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt @@ -459,6 +459,13 @@ data class UserActionResult( /** The key of the transition that should be used. */ val transitionKey: TransitionKey? = null, + + /** + * If `true`, the swipe will be committed and we will settle to [toScene] if only if the user + * swiped at least the swipe distance, i.e. the transition progress was already equal to or + * bigger than 100% when the user released their finger. ` + */ + val requiresFullDistanceSwipe: Boolean = false, ) fun interface UserActionDistance { diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt index a8df6f4ae8b1..5b4fbf036083 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt @@ -224,6 +224,9 @@ sealed interface TransitionState { /** The scene this transition is going to. Can't be the same as fromScene */ val toScene: SceneKey, + + /** The transition that `this` transition is replacing, if any. */ + internal val replacedTransition: Transition? = null, ) : TransitionState { /** * The key of this transition. This should usually be null, but it can be specified to use a @@ -279,6 +282,11 @@ sealed interface TransitionState { init { check(fromScene != toScene) + check( + replacedTransition == null || + (replacedTransition.fromScene == fromScene && + replacedTransition.toScene == toScene) + ) } /** @@ -321,6 +329,10 @@ sealed interface TransitionState { return 0f } + if (replacedTransition != null) { + return replacedTransition.interruptionProgress(layoutImpl) + } + fun create(): Animatable<Float, AnimationVector1D> { val animatable = Animatable(1f, visibilityThreshold = ProgressVisibilityThreshold) layoutImpl.coroutineScope.launch { @@ -521,6 +533,10 @@ internal abstract class BaseSceneTransitionLayoutState( check(transitionStates.size == 1) check(transitionStates[0] is TransitionState.Idle) transitionStates = listOf(transition) + } else if (currentState == transition.replacedTransition) { + // Replace the transition. + transitionStates = + transitionStates.subList(0, transitionStates.lastIndex) + transition } else { // Append the new transition. transitionStates = transitionStates + transition diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt index be3bca70d546..55a342cc13c7 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt @@ -1215,4 +1215,35 @@ class DraggableHandlerTest { onDragStartedImmediately() assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f) } + + @Test + fun requireFullDistanceSwipe() = runGestureTest { + mutableUserActionsA[Swipe.Up] = UserActionResult(SceneB, requiresFullDistanceSwipe = true) + + val controller = onDragStarted(overSlop = up(fractionOfScreen = 0.9f)) + assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.9f) + + controller.onDragStopped(velocity = 0f) + advanceUntilIdle() + assertIdle(SceneA) + + val otherController = onDragStarted(overSlop = up(fractionOfScreen = 1f)) + assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f) + otherController.onDragStopped(velocity = 0f) + advanceUntilIdle() + assertIdle(SceneB) + } + + @Test + fun interceptingTransitionReplacesCurrentTransition() = runGestureTest { + val controller = onDragStarted(overSlop = up(fractionOfScreen = 0.5f)) + val transition = assertThat(layoutState.transitionState).isTransition() + controller.onDragStopped(velocity = 0f) + + // Intercept the transition. + onDragStartedImmediately() + val newTransition = assertThat(layoutState.transitionState).isTransition() + assertThat(newTransition).isNotSameInstanceAs(transition) + assertThat(newTransition.replacedTransition).isSameInstanceAs(transition) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt index 615a42fb103f..9646bc2fbca6 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt @@ -851,11 +851,12 @@ class ElementTest { rule.runOnUiThread { MutableSceneTransitionLayoutState( initialScene = SceneA, - transitions = transitions { - from(SceneA, to = SceneB) { - translate(TestElements.Foo, y = translateY) - } - }, + transitions = + transitions { + from(SceneA, to = SceneB) { + translate(TestElements.Foo, y = translateY) + } + }, ) as MutableSceneTransitionLayoutStateImpl } @@ -2010,4 +2011,119 @@ class ElementTest { ) .isEqualTo(Element.SizeUnspecified) } + + @Test + fun transparentElementIsNotImpactingInterruption() = runTest { + val state = + rule.runOnIdle { + MutableSceneTransitionLayoutStateImpl( + SceneA, + transitions { + from(SceneA, to = SceneB) { + // In A => B, Foo is not shared and first fades out from A then fades in + // B. + sharedElement(TestElements.Foo, enabled = false) + fractionRange(end = 0.5f) { fade(TestElements.Foo.inScene(SceneA)) } + fractionRange(start = 0.5f) { fade(TestElements.Foo.inScene(SceneB)) } + } + + from(SceneB, to = SceneA) { + // In B => A, Foo is shared. + sharedElement(TestElements.Foo, enabled = true) + } + } + ) + } + + @Composable + fun SceneScope.Foo(modifier: Modifier = Modifier) { + Box(modifier.element(TestElements.Foo).size(10.dp)) + } + + rule.setContent { + SceneTransitionLayout(state) { + scene(SceneB) { Foo(Modifier.offset(40.dp, 60.dp)) } + + // Define A after B so that Foo is placed in A during A <=> B. + scene(SceneA) { Foo() } + } + } + + // Start A => B at 70%. + rule.runOnUiThread { + state.startTransition( + transition( + from = SceneA, + to = SceneB, + progress = { 0.7f }, + onFinish = neverFinish(), + ) + ) + } + + rule.onNode(isElement(TestElements.Foo, SceneA)).assertPositionInRootIsEqualTo(0.dp, 0.dp) + rule.onNode(isElement(TestElements.Foo, SceneB)).assertPositionInRootIsEqualTo(40.dp, 60.dp) + + // Start B => A at 50% with interruptionProgress = 100%. Foo is placed in A and should still + // be at (40dp, 60dp) given that it was fully transparent in A before the interruption. + var interruptionProgress by mutableStateOf(1f) + rule.runOnUiThread { + state.startTransition( + transition( + from = SceneB, + to = SceneA, + progress = { 0.5f }, + interruptionProgress = { interruptionProgress }, + onFinish = neverFinish(), + ) + ) + } + + rule.onNode(isElement(TestElements.Foo, SceneA)).assertPositionInRootIsEqualTo(40.dp, 60.dp) + rule.onNode(isElement(TestElements.Foo, SceneB)).assertIsNotDisplayed() + + // Set the interruption progress to 0%. Foo should be at (20dp, 30dp) given that B => is at + // 50%. + interruptionProgress = 0f + rule.onNode(isElement(TestElements.Foo, SceneA)).assertPositionInRootIsEqualTo(20.dp, 30.dp) + rule.onNode(isElement(TestElements.Foo, SceneB)).assertIsNotDisplayed() + } + + @Test + fun replacedTransitionDoesNotTriggerInterruption() = runTest { + val state = rule.runOnIdle { MutableSceneTransitionLayoutStateImpl(SceneA) } + + @Composable + fun SceneScope.Foo(modifier: Modifier = Modifier) { + Box(modifier.element(TestElements.Foo).size(10.dp)) + } + + rule.setContent { + SceneTransitionLayout(state) { + scene(SceneA) { Foo() } + scene(SceneB) { Foo(Modifier.offset(40.dp, 60.dp)) } + } + } + + // Start A => B at 50%. + val aToB1 = + transition(from = SceneA, to = SceneB, progress = { 0.5f }, onFinish = neverFinish()) + rule.runOnUiThread { state.startTransition(aToB1) } + rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed() + rule.onNode(isElement(TestElements.Foo, SceneB)).assertPositionInRootIsEqualTo(20.dp, 30.dp) + + // Replace A => B by another A => B at 100%. Even with interruption progress at 100%, Foo + // should be at (40dp, 60dp) given that aToB1 was replaced by aToB2. + val aToB2 = + transition( + from = SceneA, + to = SceneB, + progress = { 1f }, + interruptionProgress = { 1f }, + replacedTransition = aToB1, + ) + rule.runOnUiThread { state.startTransition(aToB2) } + rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed() + rule.onNode(isElement(TestElements.Foo, SceneB)).assertPositionInRootIsEqualTo(40.dp, 60.dp) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt index 09d1a827d0c7..3552d3d0bc1b 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt @@ -131,10 +131,6 @@ class InterruptionHandlerTest { assertThat(state.currentTransitions) .comparingElementsUsing(FromToCurrentTriple) .containsExactly( - // Initial transition A to B. This transition will never be consumed by anyone given - // that it has the same (from, to) pair as the next transition. - Triple(SceneA, SceneB, SceneB), - // Initial transition reversed, B back to A. Triple(SceneA, SceneB, SceneA), diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt index 322b0355c2bd..65f4f9e6e393 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt @@ -37,8 +37,11 @@ fun transition( bouncingScene: SceneKey? = null, orientation: Orientation = Orientation.Horizontal, onFinish: ((TransitionState.Transition) -> Job)? = null, + replacedTransition: TransitionState.Transition? = null, ): TransitionState.Transition { - return object : TransitionState.Transition(from, to), TransitionState.HasOverscrollProperties { + return object : + TransitionState.Transition(from, to, replacedTransition), + TransitionState.HasOverscrollProperties { override val currentScene: SceneKey get() = current() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt index 303548131788..68cfa28dabd7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt @@ -29,7 +29,6 @@ import com.android.systemui.biometrics.data.repository.fingerprintPropertyReposi import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor -import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.biometricSettingsRepository @@ -223,23 +222,14 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { } private fun givenAlternateBouncerSupported() { - if (DeviceEntryUdfpsRefactor.isEnabled) { - kosmos.fingerprintPropertyRepository.supportsUdfps() - } else { - kosmos.keyguardBouncerRepository.setAlternateBouncerUIAvailable(true) - } + kosmos.givenAlternateBouncerSupported() } private fun givenCanShowAlternateBouncer() { - givenAlternateBouncerSupported() - kosmos.keyguardBouncerRepository.setPrimaryShow(false) - kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) - kosmos.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true) - whenever(kosmos.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false) - whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(false) + kosmos.givenCanShowAlternateBouncer() } private fun givenCannotShowAlternateBouncer() { - kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) + kosmos.givenCannotShowAlternateBouncer() } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalPrefsRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalPrefsRepositoryImplTest.kt index 5e120b5f9560..a8bdc7c632d2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalPrefsRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalPrefsRepositoryImplTest.kt @@ -18,8 +18,8 @@ package com.android.systemui.communal.data.repository import android.content.Context import android.content.Intent -import android.content.SharedPreferences import android.content.pm.UserInfo +import android.content.pm.UserInfo.FLAG_MAIN import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase @@ -30,108 +30,87 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.log.logcatLogBuffer -import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.settings.UserFileManager +import com.android.systemui.settings.fakeUserFileManager import com.android.systemui.testKosmos -import com.android.systemui.user.data.repository.FakeUserRepository -import com.android.systemui.user.data.repository.fakeUserRepository -import com.android.systemui.util.FakeSharedPreferences import com.google.common.truth.Truth.assertThat -import java.io.File import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.Mockito import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations +import org.mockito.kotlin.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class CommunalPrefsRepositoryImplTest : SysuiTestCase() { - @Mock private lateinit var tableLogBuffer: TableLogBuffer - - private lateinit var underTest: CommunalPrefsRepositoryImpl - private val kosmos = testKosmos() private val testScope = kosmos.testScope - private lateinit var userRepository: FakeUserRepository - private lateinit var userFileManager: UserFileManager - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) + private val userFileManager: UserFileManager = spy(kosmos.fakeUserFileManager) - userRepository = kosmos.fakeUserRepository - userRepository.setUserInfos(USER_INFOS) - - userFileManager = - FakeUserFileManager( - mapOf( - USER_INFOS[0].id to FakeSharedPreferences(), - USER_INFOS[1].id to FakeSharedPreferences() - ) - ) + private val underTest: CommunalPrefsRepositoryImpl by lazy { + CommunalPrefsRepositoryImpl( + kosmos.testDispatcher, + userFileManager, + kosmos.broadcastDispatcher, + logcatLogBuffer("CommunalPrefsRepositoryImplTest"), + ) } @Test fun isCtaDismissedValue_byDefault_isFalse() = testScope.runTest { - underTest = createCommunalPrefsRepositoryImpl(userFileManager) - val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed(MAIN_USER)) assertThat(isCtaDismissed).isFalse() } @Test fun isCtaDismissedValue_onSet_isTrue() = testScope.runTest { - underTest = createCommunalPrefsRepositoryImpl(userFileManager) - val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed(MAIN_USER)) - underTest.setCtaDismissedForCurrentUser() + underTest.setCtaDismissed(MAIN_USER) assertThat(isCtaDismissed).isTrue() } @Test - fun isCtaDismissedValue_whenSwitchUser() = + fun isCtaDismissedValue_onSetForDifferentUser_isStillFalse() = testScope.runTest { - underTest = createCommunalPrefsRepositoryImpl(userFileManager) - val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) - underTest.setCtaDismissedForCurrentUser() - - // dismissed true for primary user - assertThat(isCtaDismissed).isTrue() - - // switch to secondary user - userRepository.setSelectedUserInfo(USER_INFOS[1]) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed(MAIN_USER)) - // dismissed is false for secondary user + underTest.setCtaDismissed(SECONDARY_USER) assertThat(isCtaDismissed).isFalse() + } + + @Test + fun isDisclaimerDismissed_byDefault_isFalse() = + testScope.runTest { + val isDisclaimerDismissed by + collectLastValue(underTest.isDisclaimerDismissed(MAIN_USER)) + assertThat(isDisclaimerDismissed).isFalse() + } - // switch back to primary user - userRepository.setSelectedUserInfo(USER_INFOS[0]) + @Test + fun isDisclaimerDismissed_onSet_isTrue() = + testScope.runTest { + val isDisclaimerDismissed by + collectLastValue(underTest.isDisclaimerDismissed(MAIN_USER)) - // dismissed is true for primary user - assertThat(isCtaDismissed).isTrue() + underTest.setDisclaimerDismissed(MAIN_USER) + assertThat(isDisclaimerDismissed).isTrue() } @Test fun getSharedPreferences_whenFileRestored() = testScope.runTest { - val userFileManagerSpy = Mockito.spy(userFileManager) - underTest = createCommunalPrefsRepositoryImpl(userFileManagerSpy) - - val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) - userRepository.setSelectedUserInfo(USER_INFOS[0]) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed(MAIN_USER)) assertThat(isCtaDismissed).isFalse() - clearInvocations(userFileManagerSpy) + clearInvocations(userFileManager) // Received restore finished event. kosmos.broadcastDispatcher.sendIntentToMatchingReceiversOnly( @@ -141,48 +120,12 @@ class CommunalPrefsRepositoryImplTest : SysuiTestCase() { runCurrent() // Get shared preferences from the restored file. - verify(userFileManagerSpy, atLeastOnce()) - .getSharedPreferences( - FILE_NAME, - Context.MODE_PRIVATE, - userRepository.getSelectedUserInfo().id - ) - } - - private fun createCommunalPrefsRepositoryImpl(userFileManager: UserFileManager) = - CommunalPrefsRepositoryImpl( - testScope.backgroundScope, - kosmos.testDispatcher, - userRepository, - userFileManager, - kosmos.broadcastDispatcher, - logcatLogBuffer("CommunalPrefsRepositoryImplTest"), - tableLogBuffer, - ) - - private class FakeUserFileManager(private val sharedPrefs: Map<Int, SharedPreferences>) : - UserFileManager { - override fun getFile(fileName: String, userId: Int): File { - throw UnsupportedOperationException() + verify(userFileManager, atLeastOnce()) + .getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE, MAIN_USER.id) } - override fun getSharedPreferences( - fileName: String, - mode: Int, - userId: Int - ): SharedPreferences { - if (fileName != FILE_NAME) { - throw IllegalArgumentException("Preference files must be $FILE_NAME") - } - return sharedPrefs.getValue(userId) - } - } - companion object { - val USER_INFOS = - listOf( - UserInfo(/* id= */ 0, "zero", /* flags= */ 0), - UserInfo(/* id= */ 1, "secondary", /* flags= */ 0), - ) + val MAIN_USER = UserInfo(0, "main", FLAG_MAIN) + val SECONDARY_USER = UserInfo(1, "secondary", 0) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index 3d454a202220..d951cca89f64 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -488,8 +488,16 @@ class CommunalInteractorTest : SysuiTestCase() { @Test fun ctaTile_afterDismiss_doesNotShow() = testScope.runTest { + // Set to main user, so we can dismiss the tile for the main user. + val user = userRepository.asMainUser() + userTracker.set( + userInfos = listOf(user), + selectedUserIndex = 0, + ) + runCurrent() + tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) - communalPrefsRepository.setCtaDismissedForCurrentUser() + communalPrefsRepository.setCtaDismissed(user) val ctaTileContent by collectLastValue(underTest.ctaTileContent) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractorTest.kt new file mode 100644 index 000000000000..7b79d2817478 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractorTest.kt @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import android.content.pm.UserInfo +import android.content.pm.UserInfo.FLAG_MAIN +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope +import com.android.systemui.settings.fakeUserTracker +import com.android.systemui.testKosmos +import com.android.systemui.user.data.repository.fakeUserRepository +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class CommunalPrefsInteractorTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val underTest by lazy { kosmos.communalPrefsInteractor } + + @Test + fun setCtaDismissed_currentUser() = + testScope.runTest { + setSelectedUser(MAIN_USER) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) + + assertThat(isCtaDismissed).isFalse() + underTest.setCtaDismissed(MAIN_USER) + assertThat(isCtaDismissed).isTrue() + } + + @Test + fun setCtaDismissed_anotherUser() = + testScope.runTest { + setSelectedUser(MAIN_USER) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) + + assertThat(isCtaDismissed).isFalse() + underTest.setCtaDismissed(SECONDARY_USER) + assertThat(isCtaDismissed).isFalse() + } + + @Test + fun isCtaDismissed_userSwitch() = + testScope.runTest { + setSelectedUser(MAIN_USER) + underTest.setCtaDismissed(MAIN_USER) + val isCtaDismissed by collectLastValue(underTest.isCtaDismissed) + + assertThat(isCtaDismissed).isTrue() + setSelectedUser(SECONDARY_USER) + assertThat(isCtaDismissed).isFalse() + } + + @Test + fun setDisclaimerDismissed_currentUser() = + testScope.runTest { + setSelectedUser(MAIN_USER) + val isDisclaimerDismissed by collectLastValue(underTest.isDisclaimerDismissed) + + assertThat(isDisclaimerDismissed).isFalse() + underTest.setDisclaimerDismissed(MAIN_USER) + assertThat(isDisclaimerDismissed).isTrue() + } + + @Test + fun setDisclaimerDismissed_anotherUser() = + testScope.runTest { + setSelectedUser(MAIN_USER) + val isDisclaimerDismissed by collectLastValue(underTest.isDisclaimerDismissed) + + assertThat(isDisclaimerDismissed).isFalse() + underTest.setDisclaimerDismissed(SECONDARY_USER) + assertThat(isDisclaimerDismissed).isFalse() + } + + @Test + fun isDisclaimerDismissed_userSwitch() = + testScope.runTest { + setSelectedUser(MAIN_USER) + underTest.setDisclaimerDismissed(MAIN_USER) + val isDisclaimerDismissed by collectLastValue(underTest.isDisclaimerDismissed) + + assertThat(isDisclaimerDismissed).isTrue() + setSelectedUser(SECONDARY_USER) + assertThat(isDisclaimerDismissed).isFalse() + } + + private suspend fun setSelectedUser(user: UserInfo) { + with(kosmos.fakeUserRepository) { + setUserInfos(listOf(user)) + setSelectedUserInfo(user) + } + kosmos.fakeUserTracker.set(userInfos = listOf(user), selectedUserIndex = 0) + } + + private companion object { + val MAIN_USER = UserInfo(0, "main", FLAG_MAIN) + val SECONDARY_USER = UserInfo(1, "secondary", 0) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt index d5fe2a1b2e47..0190ccba3caa 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt @@ -40,6 +40,7 @@ import com.android.systemui.communal.data.repository.fakeCommunalTutorialReposit import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.communalPrefsInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalSettingsInteractor import com.android.systemui.communal.domain.model.CommunalContentModel @@ -48,6 +49,8 @@ import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.shared.model.EditModeState import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.Flags +import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope @@ -57,6 +60,7 @@ import com.android.systemui.settings.fakeUserTracker import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository import com.android.systemui.testKosmos +import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat @@ -104,10 +108,12 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { smartspaceRepository = kosmos.fakeSmartspaceRepository mediaRepository = kosmos.fakeCommunalMediaRepository communalSceneInteractor = kosmos.communalSceneInteractor + kosmos.fakeUserRepository.setUserInfos(listOf(MAIN_USER_INFO)) kosmos.fakeUserTracker.set( userInfos = listOf(MAIN_USER_INFO), selectedUserIndex = 0, ) + kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true) whenever(providerInfo.profile).thenReturn(UserHandle(MAIN_USER_INFO.id)) underTest = @@ -120,6 +126,7 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { uiEventLogger, logcatLogBuffer("CommunalEditModeViewModelTest"), kosmos.testDispatcher, + kosmos.communalPrefsInteractor, ) } @@ -312,6 +319,29 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { } } + @Test + fun showDisclaimer_trueAfterEditModeShowing() = + testScope.runTest { + val showDisclaimer by collectLastValue(underTest.showDisclaimer) + + assertThat(showDisclaimer).isFalse() + underTest.setEditModeState(EditModeState.SHOWING) + assertThat(showDisclaimer).isTrue() + } + + @Test + fun showDisclaimer_falseWhenDismissed() = + testScope.runTest { + underTest.setEditModeState(EditModeState.SHOWING) + kosmos.fakeUserRepository.setSelectedUserInfo(MAIN_USER_INFO) + + val showDisclaimer by collectLastValue(underTest.showDisclaimer) + + assertThat(showDisclaimer).isTrue() + underTest.onDisclaimerDismissed() + assertThat(showDisclaimer).isFalse() + } + private companion object { val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) const val WIDGET_PICKER_PACKAGE_NAME = "widget_picker_package_name" diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt index e7a7b152d936..7a5f81c1ed29 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt @@ -100,7 +100,6 @@ import platform.test.runner.parameterized.Parameters @RunWith(ParameterizedAndroidJunit4::class) class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { @Mock private lateinit var mediaHost: MediaHost - @Mock private lateinit var user: UserInfo @Mock private lateinit var providerInfo: AppWidgetProviderInfo private val kosmos = testKosmos() @@ -315,6 +314,7 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun dismissCta_hidesCtaTileAndShowsPopup_thenHidesPopupAfterTimeout() = testScope.runTest { + setIsMainUser(true) tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED) val communalContent by collectLastValue(underTest.communalContent) @@ -338,6 +338,7 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { @Test fun popup_onDismiss_hidesImmediately() = testScope.runTest { + setIsMainUser(true) tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED) val currentPopup by collectLastValue(underTest.currentPopup) @@ -743,13 +744,17 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { } private suspend fun setIsMainUser(isMainUser: Boolean) { - whenever(user.isMain).thenReturn(isMainUser) - userRepository.setUserInfos(listOf(user)) - userRepository.setSelectedUserInfo(user) + val user = if (isMainUser) MAIN_USER_INFO else SECONDARY_USER_INFO + with(userRepository) { + setUserInfos(listOf(user)) + setSelectedUserInfo(user) + } + kosmos.fakeUserTracker.set(userInfos = listOf(user), selectedUserIndex = 0) } private companion object { val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) + val SECONDARY_USER_INFO = UserInfo(1, "secondary", 0) @JvmStatic @Parameters(name = "{0}") diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt index d20fec44d60f..5115f5af94f0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt @@ -90,7 +90,11 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { ) reset(transitionRepository) + kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null) kosmos.fakeKeyguardRepository.setKeyguardOccluded(true) + runCurrent() + assertThat(transitionRepository).noTransitionsStarted() + kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true) runCurrent() kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt index 6d9c271d0f4a..b49e546c6e78 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelTest.kt @@ -227,6 +227,15 @@ class DeviceEntryIconViewModelTest : SysuiTestCase() { assertThat(accessibilityDelegateHint) .isEqualTo(DeviceEntryIconView.AccessibilityHintType.BOUNCER) + // udfps running + setUpState( + isUdfpsSupported = true, + isUdfpsRunning = true, + ) + + assertThat(accessibilityDelegateHint) + .isEqualTo(DeviceEntryIconView.AccessibilityHintType.BOUNCER) + // non-interactive lock icon fingerprintPropertyRepository.supportsRearFps() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt index bc0512a1468d..f43fa5048298 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryTest.kt @@ -30,11 +30,21 @@ import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel +import com.android.systemui.media.controls.util.SmallHash +import com.android.systemui.media.controls.util.mediaSmartspaceLogger +import com.android.systemui.media.controls.util.mockMediaSmartspaceLogger import com.android.systemui.testKosmos +import com.android.systemui.util.time.systemClock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.eq +import org.mockito.kotlin.never +import org.mockito.kotlin.reset +import org.mockito.kotlin.verify @SmallTest @RunWith(AndroidJUnit4::class) @@ -42,8 +52,20 @@ class MediaFilterRepositoryTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope + private val smartspaceLogger = kosmos.mockMediaSmartspaceLogger + private val icon = Icon.createWithResource(context, R.drawable.ic_media_play) + private val mediaRecommendation = + SmartspaceMediaData( + targetId = KEY_MEDIA_SMARTSPACE, + isActive = true, + recommendations = MediaTestHelper.getValidRecommendationList(icon), + ) - private val underTest: MediaFilterRepository = kosmos.mediaFilterRepository + private val underTest: MediaFilterRepository = + with(kosmos) { + mediaSmartspaceLogger = mockMediaSmartspaceLogger + mediaFilterRepository + } @Test fun addSelectedUserMediaEntry_activeThenInactivate() = @@ -137,14 +159,6 @@ class MediaFilterRepositoryTest : SysuiTestCase() { testScope.runTest { val smartspaceMediaData by collectLastValue(underTest.smartspaceMediaData) - val icon = Icon.createWithResource(context, R.drawable.ic_media_play) - val mediaRecommendation = - SmartspaceMediaData( - targetId = KEY_MEDIA_SMARTSPACE, - isActive = true, - recommendations = MediaTestHelper.getValidRecommendationList(icon), - ) - underTest.setRecommendation(mediaRecommendation) assertThat(smartspaceMediaData).isEqualTo(mediaRecommendation) @@ -164,16 +178,38 @@ class MediaFilterRepositoryTest : SysuiTestCase() { val playingData = createMediaData("app1", true, LOCAL, false, playingInstanceId) val remoteData = createMediaData("app2", true, REMOTE, false, remoteInstanceId) + underTest.setRecommendation(mediaRecommendation) + underTest.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) + ) underTest.addSelectedUserMediaEntry(playingData) underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(playingInstanceId)) + + verify(smartspaceLogger) + .logSmartspaceCardReceived( + playingData.smartspaceId, + playingData.appUid, + cardinality = 2 + ) + underTest.addSelectedUserMediaEntry(remoteData) underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(remoteInstanceId)) - assertThat(currentMedia?.size).isEqualTo(2) + verify(smartspaceLogger) + .logSmartspaceCardReceived( + remoteData.smartspaceId, + playingData.appUid, + cardinality = 3, + rank = 1 + ) + assertThat(currentMedia?.size).isEqualTo(3) assertThat(currentMedia) .containsExactly( MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId)), - MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(remoteInstanceId)) + MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(remoteInstanceId)), + MediaCommonModel.MediaRecommendations( + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) + ) ) .inOrder() } @@ -222,6 +258,16 @@ class MediaFilterRepositoryTest : SysuiTestCase() { underTest.setOrderedMedia() + verify(smartspaceLogger, never()) + .logSmartspaceCardReceived( + anyInt(), + anyInt(), + anyInt(), + anyBoolean(), + anyBoolean(), + anyInt(), + anyInt() + ) assertThat(currentMedia?.size).isEqualTo(2) assertThat(currentMedia) .containsExactly( @@ -248,14 +294,6 @@ class MediaFilterRepositoryTest : SysuiTestCase() { val stoppedAndRemoteData = createMediaData("app4", false, REMOTE, false, instanceId4) val canResumeData = createMediaData("app5", false, LOCAL, true, instanceId5) - val icon = Icon.createWithResource(context, R.drawable.ic_media_play) - val mediaRecommendations = - SmartspaceMediaData( - targetId = KEY_MEDIA_SMARTSPACE, - isActive = true, - recommendations = MediaTestHelper.getValidRecommendationList(icon), - ) - underTest.addSelectedUserMediaEntry(stoppedAndLocalData) underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId3)) @@ -271,11 +309,33 @@ class MediaFilterRepositoryTest : SysuiTestCase() { underTest.addSelectedUserMediaEntry(playingAndRemoteData) underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId2)) - underTest.setRecommendation(mediaRecommendations) + underTest.setRecommendation(mediaRecommendation) underTest.setRecommendationsLoadingState( SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) ) + underTest.setOrderedMedia() + val smartspaceId = SmallHash.hash(mediaRecommendation.targetId) + verify(smartspaceLogger) + .logSmartspaceCardReceived( + eq(smartspaceId), + anyInt(), + eq(6), + anyBoolean(), + anyBoolean(), + eq(2), + anyInt() + ) + verify(smartspaceLogger, never()) + .logSmartspaceCardReceived( + eq(playingAndLocalData.smartspaceId), + anyInt(), + anyInt(), + anyBoolean(), + anyBoolean(), + anyInt(), + anyInt() + ) assertThat(currentMedia?.size).isEqualTo(6) assertThat(currentMedia) .containsExactly( @@ -312,18 +372,10 @@ class MediaFilterRepositoryTest : SysuiTestCase() { isPlaying = true, notificationKey = KEY_2 ) - val icon = Icon.createWithResource(context, R.drawable.ic_media_play) - val mediaRecommendations = - SmartspaceMediaData( - targetId = KEY_MEDIA_SMARTSPACE, - isActive = true, - packageName = PACKAGE_NAME, - recommendations = MediaTestHelper.getValidRecommendationList(icon), - ) underTest.setMediaFromRecPackageName(PACKAGE_NAME) underTest.addSelectedUserMediaEntry(data) - underTest.setRecommendation(mediaRecommendations) + underTest.setRecommendation(mediaRecommendation) underTest.setRecommendationsLoadingState( SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE) ) @@ -365,6 +417,88 @@ class MediaFilterRepositoryTest : SysuiTestCase() { fun hasActiveMedia_noMediaSet_returnsFalse() = testScope.runTest { assertThat(underTest.hasActiveMedia()).isFalse() } + @Test + fun updateMediaWithLatency_smartspaceIsLogged() = + testScope.runTest { + val instanceId = InstanceId.fakeInstanceId(123) + val data = createMediaData("app", true, LOCAL, false, instanceId) + + underTest.setRecommendation(mediaRecommendation) + underTest.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) + ) + + val smartspaceId = SmallHash.hash(mediaRecommendation.targetId) + verify(smartspaceLogger) + .logSmartspaceCardReceived( + eq(smartspaceId), + anyInt(), + eq(1), + eq(true), + anyBoolean(), + eq(0), + anyInt() + ) + reset(smartspaceLogger) + + underTest.addSelectedUserMediaEntry(data) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId)) + + verify(smartspaceLogger) + .logSmartspaceCardReceived(data.smartspaceId, data.appUid, cardinality = 2) + + reset(smartspaceLogger) + + underTest.addSelectedUserMediaEntry(data) + underTest.addMediaDataLoadingState( + MediaDataLoadingModel.Loaded(instanceId, receivedSmartspaceCardLatency = 123) + ) + + verify(smartspaceLogger) + .logSmartspaceCardReceived( + SmallHash.hash(data.appUid + kosmos.systemClock.currentTimeMillis().toInt()), + data.appUid, + cardinality = 2, + rank = 0, + receivedLatencyMillis = 123 + ) + } + + @Test + fun resumeMedia_loadSmartspace_allSmartspaceIsLogged() = + testScope.runTest { + val resumeInstanceId = InstanceId.fakeInstanceId(123) + val data = createMediaData("app", false, LOCAL, true, resumeInstanceId) + + underTest.addSelectedUserMediaEntry(data.copy(active = false)) + underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(resumeInstanceId)) + underTest.setRecommendation(mediaRecommendation) + underTest.setRecommendationsLoadingState( + SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true) + ) + + assertThat(underTest.hasActiveMedia()).isFalse() + assertThat(underTest.hasAnyMedia()).isTrue() + val smartspaceId = SmallHash.hash(mediaRecommendation.targetId) + verify(smartspaceLogger) + .logSmartspaceCardReceived( + eq(smartspaceId), + anyInt(), + eq(2), + eq(true), + anyBoolean(), + eq(0), + anyInt() + ) + verify(smartspaceLogger) + .logSmartspaceCardReceived( + SmallHash.hash(data.appUid + kosmos.systemClock.currentTimeMillis().toInt()), + data.appUid, + cardinality = 2, + rank = 1 + ) + } + private fun createMediaData( app: String, playing: Boolean, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/SpatialAudioComponentKosmos.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/SpatialAudioComponentKosmos.kt index 777240c57c2e..5826b3feae37 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/SpatialAudioComponentKosmos.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/SpatialAudioComponentKosmos.kt @@ -17,8 +17,10 @@ package com.android.systemui.volume.panel.component.spatial import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.backgroundCoroutineContext import com.android.systemui.kosmos.testScope import com.android.systemui.media.spatializerInteractor +import com.android.systemui.volume.data.repository.audioRepository import com.android.systemui.volume.domain.interactor.audioOutputInteractor import com.android.systemui.volume.panel.component.spatial.domain.interactor.SpatialAudioComponentInteractor @@ -27,6 +29,8 @@ val Kosmos.spatialAudioComponentInteractor by SpatialAudioComponentInteractor( audioOutputInteractor, spatializerInteractor, + audioRepository, + backgroundCoroutineContext, testScope.backgroundScope ) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt index c6c46faf97f7..555d77c95fe7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorTest.kt @@ -16,14 +16,22 @@ package com.android.systemui.volume.panel.component.spatial.domain.interactor +import android.bluetooth.BluetoothDevice +import android.bluetooth.BluetoothProfile import android.media.AudioDeviceAttributes import android.media.AudioDeviceInfo import android.media.session.MediaSession import android.media.session.PlaybackState +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.SetFlagsRule import android.testing.TestableLooper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.settingslib.bluetooth.A2dpProfile import com.android.settingslib.bluetooth.CachedBluetoothDevice +import com.android.settingslib.bluetooth.HearingAidProfile +import com.android.settingslib.bluetooth.LeAudioProfile +import com.android.settingslib.flags.Flags import com.android.settingslib.media.BluetoothMediaDevice import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -44,6 +52,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -52,15 +61,29 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class SpatialAudioComponentInteractorTest : SysuiTestCase() { + @get:Rule val setFlagsRule = SetFlagsRule() private val kosmos = testKosmos() private lateinit var underTest: SpatialAudioComponentInteractor + private val a2dpProfile: A2dpProfile = mock { + whenever(profileId).thenReturn(BluetoothProfile.A2DP) + } + private val leAudioProfile: LeAudioProfile = mock { + whenever(profileId).thenReturn(BluetoothProfile.LE_AUDIO) + } + private val hearingAidProfile: HearingAidProfile = mock { + whenever(profileId).thenReturn(BluetoothProfile.HEARING_AID) + } + private val bluetoothDevice: BluetoothDevice = mock {} @Before fun setup() { with(kosmos) { val cachedBluetoothDevice: CachedBluetoothDevice = mock { whenever(address).thenReturn("test_address") + whenever(device).thenReturn(bluetoothDevice) + whenever(profiles) + .thenReturn(listOf(a2dpProfile, leAudioProfile, hearingAidProfile)) } localMediaRepository.updateCurrentConnectedDevice( mock<BluetoothMediaDevice> { @@ -83,7 +106,7 @@ class SpatialAudioComponentInteractorTest : SysuiTestCase() { fun setEnabled_changesIsEnabled() { with(kosmos) { testScope.runTest { - spatializerRepository.setIsSpatialAudioAvailable(headset, true) + spatializerRepository.setIsSpatialAudioAvailable(bleHeadsetAttributes, true) val values by collectValues(underTest.isEnabled) underTest.setEnabled(SpatialAudioEnabledModel.Disabled) @@ -106,10 +129,39 @@ class SpatialAudioComponentInteractorTest : SysuiTestCase() { } @Test + @EnableFlags(Flags.FLAG_ENABLE_DETERMINING_SPATIAL_AUDIO_ATTRIBUTES_BY_PROFILE) + fun setEnabled_determinedByBluetoothProfile_a2dpProfileEnabled() { + with(kosmos) { + testScope.runTest { + whenever(a2dpProfile.isEnabled(bluetoothDevice)).thenReturn(true) + whenever(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(false) + whenever(hearingAidProfile.isEnabled(bluetoothDevice)).thenReturn(false) + spatializerRepository.setIsSpatialAudioAvailable(a2dpAttributes, true) + val values by collectValues(underTest.isEnabled) + + underTest.setEnabled(SpatialAudioEnabledModel.Disabled) + runCurrent() + underTest.setEnabled(SpatialAudioEnabledModel.SpatialAudioEnabled) + runCurrent() + + assertThat(values) + .containsExactly( + SpatialAudioEnabledModel.Unknown, + SpatialAudioEnabledModel.Disabled, + SpatialAudioEnabledModel.SpatialAudioEnabled, + ) + .inOrder() + assertThat(spatializerRepository.getSpatialAudioCompatibleDevices()) + .containsExactly(a2dpAttributes) + } + } + } + + @Test fun connectedDeviceSupports_isAvailable_SpatialAudio() { with(kosmos) { testScope.runTest { - spatializerRepository.setIsSpatialAudioAvailable(headset, true) + spatializerRepository.setIsSpatialAudioAvailable(bleHeadsetAttributes, true) val isAvailable by collectLastValue(underTest.isAvailable) @@ -123,8 +175,8 @@ class SpatialAudioComponentInteractorTest : SysuiTestCase() { fun connectedDeviceSupportsHeadTracking_isAvailable_HeadTracking() { with(kosmos) { testScope.runTest { - spatializerRepository.setIsSpatialAudioAvailable(headset, true) - spatializerRepository.setIsHeadTrackingAvailable(headset, true) + spatializerRepository.setIsSpatialAudioAvailable(bleHeadsetAttributes, true) + spatializerRepository.setIsHeadTrackingAvailable(bleHeadsetAttributes, true) val isAvailable by collectLastValue(underTest.isAvailable) @@ -138,7 +190,7 @@ class SpatialAudioComponentInteractorTest : SysuiTestCase() { fun connectedDeviceDoesntSupport_isAvailable_Unavailable() { with(kosmos) { testScope.runTest { - spatializerRepository.setIsSpatialAudioAvailable(headset, false) + spatializerRepository.setIsSpatialAudioAvailable(bleHeadsetAttributes, false) val isAvailable by collectLastValue(underTest.isAvailable) @@ -179,7 +231,13 @@ class SpatialAudioComponentInteractorTest : SysuiTestCase() { } private companion object { - val headset = + val a2dpAttributes = + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, + "test_address" + ) + val bleHeadsetAttributes = AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLE_HEADSET, diff --git a/packages/SystemUI/res/layout/app_clips_screenshot.xml b/packages/SystemUI/res/layout/app_clips_screenshot.xml index bcc7bca8c915..a3af9490f585 100644 --- a/packages/SystemUI/res/layout/app_clips_screenshot.xml +++ b/packages/SystemUI/res/layout/app_clips_screenshot.xml @@ -51,6 +51,15 @@ app:layout_constraintStart_toEndOf="@id/save" app:layout_constraintTop_toTopOf="parent" /> + <TextView + android:id="@+id/backlinks_data" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:visibility="gone" + app:layout_constraintStart_toEndOf="@id/cancel" + app:layout_constraintTop_toTopOf="parent" /> + <ImageView android:id="@+id/preview" android:layout_width="0px" diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml index 84ab0f1b6ee5..fff1de7c1049 100644 --- a/packages/SystemUI/res/layout/screenshot_shelf.xml +++ b/packages/SystemUI/res/layout/screenshot_shelf.xml @@ -51,7 +51,6 @@ android:layout_marginBottom="@dimen/overlay_border_width" android:layout_gravity="center" android:elevation="4dp" - android:contentDescription="@string/screenshot_edit_description" android:scaleType="fitEnd" android:background="@drawable/overlay_preview_background" android:adjustViewBounds="true" @@ -67,7 +66,6 @@ android:layout_marginBottom="@dimen/overlay_border_width" android:layout_gravity="center" android:elevation="4dp" - android:contentDescription="@string/screenshot_edit_description" android:scaleType="fitEnd" android:background="@drawable/overlay_preview_background" android:adjustViewBounds="true" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 82dafc3ed1df..abafb01cc646 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -269,6 +269,8 @@ <string name="screenshot_detected_multiple_template"><xliff:g id="appName" example="Google Chrome">%1$s</xliff:g> and other open apps detected this screenshot.</string> <!-- Add to note button used in App Clips flow to return the saved screenshot image to notes app. [CHAR LIMIT=NONE] --> <string name="app_clips_save_add_to_note">Add to note</string> + <!-- TODO(b/300307759): Temporary string for text view that displays backlinks data. [CHAR LIMIT=NONE] --> + <string name="backlinks_string" translatable="false">Open <xliff:g id="appName" example="Google Chrome">%1$s</xliff:g></string> <!-- Notification title displayed for screen recording [CHAR LIMIT=50]--> <string name="screenrecord_title">Screen Recorder</string> @@ -1222,6 +1224,12 @@ <string name="accessibility_action_label_remove_widget">remove widget</string> <!-- Label for accessibility action to place a widget in edit mode after selecting move widget. [CHAR LIMIT=NONE] --> <string name="accessibility_action_label_place_widget">place selected widget</string> + <!-- Title shown above information regarding lock screen widgets. [CHAR LIMIT=50] --> + <string name="communal_widgets_disclaimer_title">Lock screen widgets</string> + <!-- Information about lock screen widgets presented to the user. [CHAR LIMIT=NONE] --> + <string name="communal_widgets_disclaimer_text">To open an app using a widget, you\u2019ll need to verify it\u2019s you. Also, keep in mind that anyone can view them, even when your tablet\u2019s locked. Some widgets may not have been intended for your lock screen and may be unsafe to add here.</string> + <!-- Button for user to verify they understand the information presented. [CHAR LIMIT=50] --> + <string name="communal_widgets_disclaimer_button">Got it</string> <!-- Related to user switcher --><skip/> @@ -1380,6 +1388,15 @@ <!-- Text which is shown in the expanded notification shade when there are currently no notifications visible that the user hasn't already seen. [CHAR LIMIT=30] --> <string name="no_unseen_notif_text">No new notifications</string> + <!-- Title of heads up notification for adaptive notifications user education. [CHAR LIMIT=30] --> + <string name="adaptive_notification_edu_hun_title">Adaptive notifications is on</string> + + <!-- Text of heads up notification for adaptive notifications user education. [CHAR LIMIT=100] --> + <string name="adaptive_notification_edu_hun_text">Your device now lowers the volume and reduces pop-ups on the screen for up to two minutes when you receive many notifications in a short time span.</string> + + <!-- Action label for going to adaptive notification settings [CHAR LIMIT=20] --> + <string name="go_to_adaptive_notification_settings">Turn off</string> + <!-- Text which is shown in the locked notification shade when there are currently no notifications, but if the user were to unlock, notifications would appear. [CHAR LIMIT=40] --> <string name="unlock_to_see_notif_text">Unlock to see older notifications</string> diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java index 68a69d34b75a..37e9dc1a9d48 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java @@ -42,6 +42,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.Flags; import com.android.internal.R; import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity; @@ -178,6 +179,18 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con private static final int SYSTEM_ACTION_ID_DPAD_CENTER = AccessibilityService.GLOBAL_ACTION_DPAD_CENTER; // 20 + /** + * Action ID to trigger menu key event. + */ + private static final int SYSTEM_ACTION_ID_MENU = + AccessibilityService.GLOBAL_ACTION_MENU; // 21 + + /** + * Action ID to trigger media play/pause key event. + */ + private static final int SYSTEM_ACTION_ID_MEDIA_PLAY_PAUSE = + AccessibilityService.GLOBAL_ACTION_MEDIA_PLAY_PAUSE; // 22 + private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; private final SystemActionsBroadcastReceiver mReceiver; @@ -307,6 +320,14 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con R.string.accessibility_system_action_dpad_center_label, SystemActionsBroadcastReceiver.INTENT_ACTION_DPAD_CENTER); + RemoteAction actionMenu = createRemoteAction( + R.string.accessibility_system_action_menu_label, + SystemActionsBroadcastReceiver.INTENT_ACTION_MENU); + + RemoteAction actionMediaPlayPause = createRemoteAction( + R.string.accessibility_system_action_media_play_pause_label, + SystemActionsBroadcastReceiver.INTENT_ACTION_MEDIA_PLAY_PAUSE); + mA11yManager.registerSystemAction(actionBack, SYSTEM_ACTION_ID_BACK); mA11yManager.registerSystemAction(actionHome, SYSTEM_ACTION_ID_HOME); mA11yManager.registerSystemAction(actionRecents, SYSTEM_ACTION_ID_RECENTS); @@ -326,6 +347,8 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con mA11yManager.registerSystemAction(actionDpadLeft, SYSTEM_ACTION_ID_DPAD_LEFT); mA11yManager.registerSystemAction(actionDpadRight, SYSTEM_ACTION_ID_DPAD_RIGHT); mA11yManager.registerSystemAction(actionDpadCenter, SYSTEM_ACTION_ID_DPAD_CENTER); + mA11yManager.registerSystemAction(actionMenu, SYSTEM_ACTION_ID_MENU); + mA11yManager.registerSystemAction(actionMediaPlayPause, SYSTEM_ACTION_ID_MEDIA_PLAY_PAUSE); registerOrUnregisterDismissNotificationShadeAction(); } @@ -435,6 +458,14 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con labelId = R.string.accessibility_system_action_dpad_center_label; intent = SystemActionsBroadcastReceiver.INTENT_ACTION_DPAD_CENTER; break; + case SYSTEM_ACTION_ID_MENU: + labelId = R.string.accessibility_system_action_menu_label; + intent = SystemActionsBroadcastReceiver.INTENT_ACTION_MENU; + break; + case SYSTEM_ACTION_ID_MEDIA_PLAY_PAUSE: + labelId = R.string.accessibility_system_action_media_play_pause_label; + intent = SystemActionsBroadcastReceiver.INTENT_ACTION_MEDIA_PLAY_PAUSE; + break; default: return; } @@ -570,6 +601,16 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_CENTER); } + @VisibleForTesting + void handleMenu() { + sendDownAndUpKeyEvents(KeyEvent.KEYCODE_MENU); + } + + @VisibleForTesting + void handleMediaPlayPause() { + sendDownAndUpKeyEvents(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); + } + private class SystemActionsBroadcastReceiver extends BroadcastReceiver { private static final String INTENT_ACTION_BACK = "SYSTEM_ACTION_BACK"; private static final String INTENT_ACTION_HOME = "SYSTEM_ACTION_HOME"; @@ -593,6 +634,9 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con private static final String INTENT_ACTION_DPAD_LEFT = "SYSTEM_ACTION_DPAD_LEFT"; private static final String INTENT_ACTION_DPAD_RIGHT = "SYSTEM_ACTION_DPAD_RIGHT"; private static final String INTENT_ACTION_DPAD_CENTER = "SYSTEM_ACTION_DPAD_CENTER"; + private static final String INTENT_ACTION_MENU = "SYSTEM_ACTION_MENU"; + private static final String INTENT_ACTION_MEDIA_PLAY_PAUSE = + "SYSTEM_ACTION_MEDIA_PLAY_PAUSE"; private PendingIntent createPendingIntent(Context context, String intentAction) { switch (intentAction) { @@ -613,7 +657,9 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con case INTENT_ACTION_DPAD_DOWN: case INTENT_ACTION_DPAD_LEFT: case INTENT_ACTION_DPAD_RIGHT: - case INTENT_ACTION_DPAD_CENTER: { + case INTENT_ACTION_DPAD_CENTER: + case INTENT_ACTION_MENU: + case INTENT_ACTION_MEDIA_PLAY_PAUSE: { Intent intent = new Intent(intentAction); intent.setPackage(context.getPackageName()); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); @@ -646,6 +692,8 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con intentFilter.addAction(INTENT_ACTION_DPAD_LEFT); intentFilter.addAction(INTENT_ACTION_DPAD_RIGHT); intentFilter.addAction(INTENT_ACTION_DPAD_CENTER); + intentFilter.addAction(INTENT_ACTION_MENU); + intentFilter.addAction(INTENT_ACTION_MEDIA_PLAY_PAUSE); return intentFilter; } @@ -725,6 +773,18 @@ public class SystemActions implements CoreStartable, ConfigurationController.Con handleDpadCenter(); break; } + case INTENT_ACTION_MENU: { + if (Flags.globalActionMenu()) { + handleMenu(); + } + break; + } + case INTENT_ACTION_MEDIA_PLAY_PAUSE: { + if (Flags.globalActionMediaPlayPause()) { + handleMediaPlayPause(); + } + break; + } default: break; } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java index 09bf04cb6d59..9cb26f35fa66 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java @@ -20,9 +20,10 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.time.SystemClock; -import java.util.ArrayList; +import com.google.common.collect.Sets; + import java.util.Collection; -import java.util.List; +import java.util.Set; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; @@ -52,7 +53,7 @@ public class HistoryTracker { private final SystemClock mSystemClock; DelayQueue<CombinedResult> mResults = new DelayQueue<>(); - private final List<BeliefListener> mBeliefListeners = new ArrayList<>(); + private final Set<BeliefListener> mBeliefListeners = Sets.newConcurrentHashSet(); @Inject HistoryTracker(SystemClock systemClock) { @@ -161,11 +162,15 @@ public class HistoryTracker { } void addBeliefListener(BeliefListener listener) { - mBeliefListeners.add(listener); + if (listener != null) { + mBeliefListeners.add(listener); + } } void removeBeliefListener(BeliefListener listener) { - mBeliefListeners.remove(listener); + if (listener != null) { + mBeliefListeners.remove(listener); + } } /** * Represents a falsing score combing all the classifiers together. diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt index b27fcfc2f3a7..d8067b887c67 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalPrefsRepository.kt @@ -27,26 +27,17 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.dagger.CommunalLog -import com.android.systemui.log.dagger.CommunalTableLog -import com.android.systemui.log.table.TableLogBuffer -import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.settings.UserFileManager -import com.android.systemui.user.data.repository.UserRepository import com.android.systemui.util.kotlin.SharedPreferencesExt.observe import com.android.systemui.util.kotlin.emitOnStart import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext /** @@ -56,10 +47,16 @@ import kotlinx.coroutines.withContext interface CommunalPrefsRepository { /** Whether the CTA tile has been dismissed. */ - val isCtaDismissed: Flow<Boolean> + fun isCtaDismissed(user: UserInfo): Flow<Boolean> + + /** Whether the lock screen widget disclaimer has been dismissed by the user. */ + fun isDisclaimerDismissed(user: UserInfo): Flow<Boolean> /** Save the CTA tile dismissed state for the current user. */ - suspend fun setCtaDismissedForCurrentUser() + suspend fun setCtaDismissed(user: UserInfo) + + /** Save the lock screen widget disclaimer dismissed state for the current user. */ + suspend fun setDisclaimerDismissed(user: UserInfo) } @OptIn(ExperimentalCoroutinesApi::class) @@ -67,75 +64,43 @@ interface CommunalPrefsRepository { class CommunalPrefsRepositoryImpl @Inject constructor( - @Background private val backgroundScope: CoroutineScope, @Background private val bgDispatcher: CoroutineDispatcher, - private val userRepository: UserRepository, private val userFileManager: UserFileManager, broadcastDispatcher: BroadcastDispatcher, @CommunalLog logBuffer: LogBuffer, - @CommunalTableLog tableLogBuffer: TableLogBuffer, ) : CommunalPrefsRepository { + private val logger by lazy { Logger(logBuffer, TAG) } - private val logger = Logger(logBuffer, "CommunalPrefsRepositoryImpl") + override fun isCtaDismissed(user: UserInfo): Flow<Boolean> = + readKeyForUser(user, CTA_DISMISSED_STATE) + + override fun isDisclaimerDismissed(user: UserInfo): Flow<Boolean> = + readKeyForUser(user, DISCLAIMER_DISMISSED_STATE) /** - * Emits an event each time a Backup & Restore restoration job is completed. Does not emit an - * initial value. + * Emits an event each time a Backup & Restore restoration job is completed, and once at the + * start of collection. */ private val backupRestorationEvents: Flow<Unit> = - broadcastDispatcher.broadcastFlow( - filter = IntentFilter(BackupHelper.ACTION_RESTORE_FINISHED), - flags = Context.RECEIVER_NOT_EXPORTED, - permission = BackupHelper.PERMISSION_SELF, - ) - - override val isCtaDismissed: Flow<Boolean> = - combine( - userRepository.selectedUserInfo, - // Make sure combine can emit even if we never get a Backup & Restore event, - // which is the most common case as restoration only happens on initial device - // setup. - backupRestorationEvents.emitOnStart().onEach { - logger.i("Restored state for communal preferences.") - }, - ) { user, _ -> - user - } - .flatMapLatest(::observeCtaDismissState) - .logDiffsForTable( - tableLogBuffer = tableLogBuffer, - columnPrefix = "", - columnName = "isCtaDismissed", - initialValue = false, - ) - .stateIn( - scope = backgroundScope, - started = SharingStarted.WhileSubscribed(), - initialValue = false, + broadcastDispatcher + .broadcastFlow( + filter = IntentFilter(BackupHelper.ACTION_RESTORE_FINISHED), + flags = Context.RECEIVER_NOT_EXPORTED, + permission = BackupHelper.PERMISSION_SELF, ) + .onEach { logger.i("Restored state for communal preferences.") } + .emitOnStart() - override suspend fun setCtaDismissedForCurrentUser() = + override suspend fun setCtaDismissed(user: UserInfo) = withContext(bgDispatcher) { - getSharedPrefsForUser(userRepository.getSelectedUserInfo()) - .edit() - .putBoolean(CTA_DISMISSED_STATE, true) - .apply() - + getSharedPrefsForUser(user).edit().putBoolean(CTA_DISMISSED_STATE, true).apply() logger.i("Dismissed CTA tile") } - private fun observeCtaDismissState(user: UserInfo): Flow<Boolean> = - getSharedPrefsForUser(user) - .observe() - // Emit at the start of collection to ensure we get an initial value - .onStart { emit(Unit) } - .map { getCtaDismissedState() } - .flowOn(bgDispatcher) - - private suspend fun getCtaDismissedState(): Boolean = + override suspend fun setDisclaimerDismissed(user: UserInfo) = withContext(bgDispatcher) { - getSharedPrefsForUser(userRepository.getSelectedUserInfo()) - .getBoolean(CTA_DISMISSED_STATE, false) + getSharedPrefsForUser(user).edit().putBoolean(DISCLAIMER_DISMISSED_STATE, true).apply() + logger.i("Dismissed widget disclaimer") } private fun getSharedPrefsForUser(user: UserInfo): SharedPreferences { @@ -146,9 +111,19 @@ constructor( ) } + private fun readKeyForUser(user: UserInfo, key: String): Flow<Boolean> { + return backupRestorationEvents + .flatMapLatest { + val sharedPrefs = getSharedPrefsForUser(user) + sharedPrefs.observe().emitOnStart().map { sharedPrefs.getBoolean(key, false) } + } + .flowOn(bgDispatcher) + } + companion object { - const val TAG = "CommunalRepository" + const val TAG = "CommunalPrefsRepository" const val FILE_NAME = "communal_hub_prefs" const val CTA_DISMISSED_STATE = "cta_dismissed" + const val DISCLAIMER_DISMISSED_STATE = "disclaimer_dismissed" } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index 00678a81b572..9f3ade9cd425 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -28,7 +28,6 @@ import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.communal.data.repository.CommunalMediaRepository -import com.android.systemui.communal.data.repository.CommunalPrefsRepository import com.android.systemui.communal.data.repository.CommunalWidgetRepository import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.domain.model.CommunalContentModel.WidgetContent @@ -99,7 +98,7 @@ constructor( @Background val bgDispatcher: CoroutineDispatcher, broadcastDispatcher: BroadcastDispatcher, private val widgetRepository: CommunalWidgetRepository, - private val communalPrefsRepository: CommunalPrefsRepository, + private val communalPrefsInteractor: CommunalPrefsInteractor, private val mediaRepository: CommunalMediaRepository, smartspaceRepository: SmartspaceRepository, keyguardInteractor: KeyguardInteractor, @@ -325,7 +324,7 @@ constructor( } /** Dismiss the CTA tile from the hub in view mode. */ - suspend fun dismissCtaTile() = communalPrefsRepository.setCtaDismissedForCurrentUser() + suspend fun dismissCtaTile() = communalPrefsInteractor.setCtaDismissed() /** Add a widget at the specified position. */ fun addWidget( @@ -461,7 +460,7 @@ constructor( /** CTA tile to be displayed in the glanceable hub (view mode). */ val ctaTileContent: Flow<List<CommunalContentModel.CtaTileInViewMode>> = - communalPrefsRepository.isCtaDismissed.map { isDismissed -> + communalPrefsInteractor.isCtaDismissed.map { isDismissed -> if (isDismissed) emptyList() else listOf(CommunalContentModel.CtaTileInViewMode()) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt new file mode 100644 index 000000000000..3517650c8cf3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractor.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import android.content.pm.UserInfo +import com.android.app.tracing.coroutines.launch +import com.android.systemui.communal.data.repository.CommunalPrefsRepository +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.log.dagger.CommunalTableLog +import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.log.table.logDiffsForTable +import com.android.systemui.settings.UserTracker +import com.android.systemui.user.domain.interactor.SelectedUserInteractor +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.stateIn + +@OptIn(ExperimentalCoroutinesApi::class) +@SysUISingleton +class CommunalPrefsInteractor +@Inject +constructor( + @Background private val bgScope: CoroutineScope, + private val repository: CommunalPrefsRepository, + userInteractor: SelectedUserInteractor, + private val userTracker: UserTracker, + @CommunalTableLog tableLogBuffer: TableLogBuffer +) { + + val isCtaDismissed: Flow<Boolean> = + userInteractor.selectedUserInfo + .flatMapLatest { user -> repository.isCtaDismissed(user) } + .logDiffsForTable( + tableLogBuffer = tableLogBuffer, + columnPrefix = "", + columnName = "isCtaDismissed", + initialValue = false, + ) + .stateIn( + scope = bgScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false, + ) + + suspend fun setCtaDismissed(user: UserInfo = userTracker.userInfo) = + repository.setCtaDismissed(user) + + val isDisclaimerDismissed: Flow<Boolean> = + userInteractor.selectedUserInfo + .flatMapLatest { user -> repository.isDisclaimerDismissed(user) } + .logDiffsForTable( + tableLogBuffer = tableLogBuffer, + columnPrefix = "", + columnName = "isDisclaimerDismissed", + initialValue = false, + ) + .stateIn( + scope = bgScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false, + ) + + fun setDisclaimerDismissed(user: UserInfo = userTracker.userInfo) { + bgScope.launch("$TAG#setDisclaimerDismissed") { repository.setDisclaimerDismissed(user) } + } + + private companion object { + const val TAG = "CommunalPrefsInteractor" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt index c0c586191834..9185384e79a3 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt @@ -26,6 +26,7 @@ import androidx.activity.result.ActivityResultLauncher import com.android.internal.logging.UiEventLogger import com.android.systemui.Flags.enableWidgetPickerSizeFilter import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.CommunalPrefsInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor import com.android.systemui.communal.domain.model.CommunalContentModel @@ -42,6 +43,7 @@ import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.media.dagger.MediaModule import com.android.systemui.res.R import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf +import com.android.systemui.util.kotlin.BooleanFlowOperators.not import javax.inject.Inject import javax.inject.Named import kotlinx.coroutines.CoroutineDispatcher @@ -67,6 +69,7 @@ constructor( private val uiEventLogger: UiEventLogger, @CommunalLog logBuffer: LogBuffer, @Background private val backgroundDispatcher: CoroutineDispatcher, + private val communalPrefsInteractor: CommunalPrefsInteractor, ) : BaseCommunalViewModel(communalSceneInteractor, communalInteractor, mediaHost) { private val logger = Logger(logBuffer, "CommunalEditModeViewModel") @@ -76,9 +79,16 @@ constructor( override val isCommunalContentVisible: Flow<Boolean> = communalSceneInteractor.editModeState.map { it == EditModeState.SHOWING } + val showDisclaimer: Flow<Boolean> = + allOf(isCommunalContentVisible, not(communalPrefsInteractor.isDisclaimerDismissed)) + + fun onDisclaimerDismissed() { + communalPrefsInteractor.setDisclaimerDismissed() + } + /** - * Emits when edit mode activity can show, after we've transitioned to [KeyguardState.GONE] - * and edit mode is open. + * Emits when edit mode activity can show, after we've transitioned to [KeyguardState.GONE] and + * edit mode is open. */ val canShowEditMode = allOf( diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt index d4a166f73237..0bcfa9616b76 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt @@ -178,7 +178,15 @@ constructor( .mapElementsLazily { displayId -> getDisplay(displayId) } .flowOn(backgroundCoroutineDispatcher) .debugLog("enabledDisplays") - .stateIn(bgApplicationScope, SharingStarted.WhileSubscribed(), emptySet()) + .stateIn( + bgApplicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = + setOf( + getDisplay(Display.DEFAULT_DISPLAY) + ?: error("Unable to get default display.") + ) + ) } else { oldEnabledDisplays } diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt index 73b7a8ac7bd3..e4b290d7d10e 100644 --- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt @@ -85,7 +85,7 @@ interface ConnectedDisplayInteractor { class ConnectedDisplayInteractorImpl @Inject constructor( - private val virtualDeviceManager: VirtualDeviceManager, + private val virtualDeviceManager: VirtualDeviceManager?, keyguardRepository: KeyguardRepository, displayRepository: DisplayRepository, deviceStateRepository: DeviceStateRepository, @@ -156,6 +156,7 @@ constructor( private fun isVirtualDeviceOwnedMirrorDisplay(display: Display): Boolean { return Flags.interactiveScreenMirror() && + virtualDeviceManager != null && virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(display.displayId) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/MultitaskingShortcutsSource.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/MultitaskingShortcutsSource.kt new file mode 100644 index 000000000000..34b10c727cd9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/MultitaskingShortcutsSource.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.shortcut.data.source + +import android.content.res.Resources +import android.view.KeyEvent.KEYCODE_DPAD_LEFT +import android.view.KeyEvent.KEYCODE_DPAD_RIGHT +import android.view.KeyEvent.KEYCODE_DPAD_UP +import android.view.KeyEvent.KEYCODE_TAB +import android.view.KeyEvent.META_ALT_ON +import android.view.KeyEvent.META_CTRL_ON +import android.view.KeyEvent.META_META_ON +import android.view.KeyEvent.META_SHIFT_ON +import com.android.systemui.keyboard.shortcut.shared.model.shortcut +import com.android.systemui.res.R +import javax.inject.Inject + +class MultitaskingShortcutsSource @Inject constructor(private val resources: Resources) { + + fun splitScreenShortcuts() = + listOf( + // Enter Split screen with current app to RHS: + // - Meta + Ctrl + Right arrow + shortcut(resources.getString(R.string.system_multitasking_rhs)) { + command(META_META_ON, META_CTRL_ON, KEYCODE_DPAD_RIGHT) + }, + // Enter Split screen with current app to LHS: + // - Meta + Ctrl + Left arrow + shortcut(resources.getString(R.string.system_multitasking_lhs)) { + command(META_META_ON, META_CTRL_ON, KEYCODE_DPAD_LEFT) + }, + // Switch from Split screen to full screen: + // - Meta + Ctrl + Up arrow + shortcut(resources.getString(R.string.system_multitasking_full_screen)) { + command(META_META_ON, META_CTRL_ON, KEYCODE_DPAD_UP) + }, + // Change split screen focus to RHS: + // - Meta + Alt + Right arrow + shortcut(resources.getString(R.string.system_multitasking_splitscreen_focus_rhs)) { + command(META_META_ON, META_ALT_ON, KEYCODE_DPAD_RIGHT) + }, + // Change split screen focus to LHS: + // - Meta + Alt + Left arrow + shortcut(resources.getString(R.string.system_multitasking_splitscreen_focus_rhs)) { + command(META_META_ON, META_ALT_ON, KEYCODE_DPAD_LEFT) + }, + ) + + fun recentsShortcuts() = + listOf( + // Cycle through recent apps (forward): + // - Alt + Tab + shortcut(resources.getString(R.string.group_system_cycle_forward)) { + command(META_ALT_ON, KEYCODE_TAB) + }, + // Cycle through recent apps (back): + // - Shift + Alt + Tab + shortcut(resources.getString(R.string.group_system_cycle_back)) { + command(META_SHIFT_ON, META_ALT_ON, KEYCODE_TAB) + }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt new file mode 100644 index 000000000000..a4304e5d1d33 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/source/SystemShortcutsSource.kt @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.shortcut.data.source + +import android.content.res.Resources +import android.view.KeyEvent.KEYCODE_A +import android.view.KeyEvent.KEYCODE_DEL +import android.view.KeyEvent.KEYCODE_DPAD_LEFT +import android.view.KeyEvent.KEYCODE_ENTER +import android.view.KeyEvent.KEYCODE_ESCAPE +import android.view.KeyEvent.KEYCODE_H +import android.view.KeyEvent.KEYCODE_I +import android.view.KeyEvent.KEYCODE_L +import android.view.KeyEvent.KEYCODE_N +import android.view.KeyEvent.KEYCODE_S +import android.view.KeyEvent.KEYCODE_SLASH +import android.view.KeyEvent.KEYCODE_TAB +import android.view.KeyEvent.META_CTRL_ON +import android.view.KeyEvent.META_META_ON +import com.android.systemui.keyboard.shortcut.shared.model.shortcut +import com.android.systemui.res.R +import javax.inject.Inject + +class SystemShortcutsSource @Inject constructor(private val resources: Resources) { + + fun generalShortcuts() = + listOf( + // Access list of all apps and search (i.e. Search/Launcher): + // - Meta + shortcut(resources.getString(R.string.group_system_access_all_apps_search)) { + command(META_META_ON) + }, + // Access home screen: + // - Meta + H + // - Meta + Enter + shortcut(resources.getString(R.string.group_system_access_home_screen)) { + command(META_META_ON, KEYCODE_H) + command(META_META_ON, KEYCODE_ENTER) + }, + // Overview of open apps: + // - Meta + Tab + shortcut(resources.getString(R.string.group_system_overview_open_apps)) { + command(META_META_ON, KEYCODE_TAB) + }, + // Back: go back to previous state (back button) + // - Meta + Escape OR + // - Meta + Backspace OR + // - Meta + Left arrow + shortcut(resources.getString(R.string.group_system_go_back)) { + command(META_META_ON, KEYCODE_ESCAPE) + command(META_META_ON, KEYCODE_DEL) + command(META_META_ON, KEYCODE_DPAD_LEFT) + }, + // Take a full screenshot: + // - Meta + Ctrl + S + shortcut(resources.getString(R.string.group_system_full_screenshot)) { + command(META_META_ON, META_CTRL_ON, KEYCODE_S) + }, + // Access list of system / apps shortcuts: + // - Meta + / + shortcut(resources.getString(R.string.group_system_access_system_app_shortcuts)) { + command(META_META_ON, KEYCODE_SLASH) + }, + // Access notification shade: + // - Meta + N + shortcut(resources.getString(R.string.group_system_access_notification_shade)) { + command(META_META_ON, KEYCODE_N) + }, + // Lock screen: + // - Meta + L + shortcut(resources.getString(R.string.group_system_lock_screen)) { + command(META_META_ON, KEYCODE_L) + }, + ) + + fun systemAppsShortcuts() = + listOf( + // Pull up Notes app for quick memo: + // - Meta + Ctrl + N + shortcut(resources.getString(R.string.group_system_quick_memo)) { + command(META_META_ON, META_CTRL_ON, KEYCODE_N) + }, + // Access system settings: + // - Meta + I + shortcut(resources.getString(R.string.group_system_access_system_settings)) { + command(META_META_ON, KEYCODE_I) + }, + // Access Assistant: + // - Meta + A + shortcut(resources.getString(R.string.group_system_access_google_assistant)) { + command(META_META_ON, KEYCODE_A) + }, + ) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/Shortcut.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/Shortcut.kt new file mode 100644 index 000000000000..ea90b18c06b5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/Shortcut.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.shortcut.shared.model + +import android.graphics.drawable.Icon + +data class Shortcut(val label: String, val icon: Icon? = null, val commands: List<ShortcutCommand>) + +class ShortcutBuilder(private val label: String, private val icon: Icon? = null) { + val commands = mutableListOf<ShortcutCommand>() + + fun command(vararg keyCodes: Int) { + commands += ShortcutCommand(keyCodes.toList()) + } + + fun build() = Shortcut(label, icon, commands) +} + +fun shortcut(label: String, icon: Icon? = null, block: ShortcutBuilder.() -> Unit): Shortcut = + ShortcutBuilder(label).apply(block).build() diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCommand.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCommand.kt new file mode 100644 index 000000000000..747efbaf4838 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/shared/model/ShortcutCommand.kt @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.shortcut.shared.model + +class ShortcutCommand(val keyCodes: List<Int>) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt index 49d00af61a24..5573f0d5f644 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest @@ -168,7 +169,9 @@ constructor( keyguardInteractor.isKeyguardGoingAway.filter { it }.map {}, // map to Unit keyguardInteractor.isKeyguardOccluded.flatMapLatest { keyguardOccluded -> if (keyguardOccluded) { - primaryBouncerInteractor.keyguardAuthenticatedBiometricsHandled + primaryBouncerInteractor.keyguardAuthenticatedBiometricsHandled.drop( + 1 + ) // drop the initial state } else { emptyFlow() } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt index f8063c92124d..db33acb93dc6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt @@ -115,13 +115,28 @@ constructor( } private fun removeViewFromWindowManager() { - if (alternateBouncerView == null || !alternateBouncerView!!.isAttachedToWindow) { - return - } + alternateBouncerView?.let { + alternateBouncerView = null + if (it.isAttachedToWindow) { + it.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler) + Log.d(TAG, "Removing alternate bouncer view immediately") + windowManager.get().removeView(it) + } else { + // once the view is attached, remove it + it.addOnAttachStateChangeListener( + object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(view: View) { + it.removeOnAttachStateChangeListener(this) + it.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler) + Log.d(TAG, "Removing alternate bouncer view on attached") + windowManager.get().removeView(it) + } - windowManager.get().removeView(alternateBouncerView) - alternateBouncerView!!.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler) - alternateBouncerView = null + override fun onViewDetachedFromWindow(view: View) {} + } + ) + } + } } private val onAttachAddBackGestureHandler = @@ -151,7 +166,7 @@ constructor( } private fun addViewToWindowManager() { - if (alternateBouncerView?.isAttachedToWindow == true) { + if (alternateBouncerView != null) { return } @@ -159,6 +174,7 @@ constructor( layoutInflater.get().inflate(R.layout.alternate_bouncer, null, false) as ConstraintLayout + Log.d(TAG, "Adding alternate bouncer view") windowManager.get().addView(alternateBouncerView, layoutParams) alternateBouncerView!!.addOnAttachStateChangeListener(onAttachAddBackGestureHandler) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt index 23c2491813f7..3e4253be4c3f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardIndicationAreaBinder.kt @@ -29,6 +29,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewMode import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import com.android.systemui.statusbar.KeyguardIndicationController +import com.android.systemui.util.kotlin.DisposableHandles import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -53,7 +54,15 @@ object KeyguardIndicationAreaBinder { viewModel: KeyguardIndicationAreaViewModel, indicationController: KeyguardIndicationController, ): DisposableHandle { - indicationController.setIndicationArea(view) + val disposables = DisposableHandles() + + // As the indication controller is a singleton, reset the view back to the previous view + // once the current view is disposed. + val previous = indicationController.indicationArea + indicationController.indicationArea = view + disposables += DisposableHandle { + previous?.let { indicationController.indicationArea = it } + } val indicationText: TextView = view.requireViewById(R.id.keyguard_indication_text) val indicationTextBottom: TextView = @@ -63,7 +72,7 @@ object KeyguardIndicationAreaBinder { view.clipToPadding = false val configurationBasedDimensions = MutableStateFlow(loadFromResources(view)) - val disposableHandle = + disposables += view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { launch("$TAG#viewModel.alpha") { @@ -126,7 +135,7 @@ object KeyguardIndicationAreaBinder { } } } - return disposableHandle + return disposables } private fun loadFromResources(view: View): ConfigurationBasedDimensions { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt index 46880883ac70..5ce1b5e3dcc5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt @@ -284,9 +284,9 @@ constructor( private fun DeviceEntryIconView.IconType.toAccessibilityHintType(): DeviceEntryIconView.AccessibilityHintType { return when (this) { + DeviceEntryIconView.IconType.FINGERPRINT, DeviceEntryIconView.IconType.LOCK -> DeviceEntryIconView.AccessibilityHintType.BOUNCER DeviceEntryIconView.IconType.UNLOCK -> DeviceEntryIconView.AccessibilityHintType.ENTER - DeviceEntryIconView.IconType.FINGERPRINT, DeviceEntryIconView.IconType.NONE -> DeviceEntryIconView.AccessibilityHintType.NONE } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt index 6a91d1b15325..a2d7fb152e5c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt @@ -26,6 +26,8 @@ import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel +import com.android.systemui.media.controls.util.MediaSmartspaceLogger +import com.android.systemui.media.controls.util.SmallHash import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.time.SystemClock import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow @@ -43,9 +45,10 @@ import kotlinx.coroutines.flow.asStateFlow class MediaFilterRepository @Inject constructor( - @Application applicationContext: Context, + @Application private val applicationContext: Context, private val systemClock: SystemClock, private val configurationController: ConfigurationController, + private val smartspaceLogger: MediaSmartspaceLogger, ) { val onAnyMediaConfigurationChange: Flow<Unit> = conflatedCallbackFlow { @@ -211,6 +214,12 @@ constructor( isMediaFromRec(it) ) sortedMap[sortKey] = newCommonModel + val isUpdate = + sortedMedia.values.any { commonModel -> + commonModel is MediaCommonModel.MediaControl && + commonModel.mediaLoadedModel.instanceId == + mediaDataLoadingModel.instanceId + } // On Addition or tapping on recommendations, we should show the new order of media. if (mediaFromRecPackageName == it.packageName) { @@ -218,30 +227,50 @@ constructor( mediaFromRecPackageName = null _currentMedia.value = sortedMap.values.toList() } - } else if (sortedMap.size > _currentMedia.value.size && it.active) { - _currentMedia.value = sortedMap.values.toList() } else { - // When loading an update for an existing media control. + var isNewToCurrentMedia = true val currentList = mutableListOf<MediaCommonModel>().apply { addAll(_currentMedia.value) } currentList.forEachIndexed { index, mediaCommonModel -> if ( mediaCommonModel is MediaCommonModel.MediaControl && mediaCommonModel.mediaLoadedModel.instanceId == - mediaDataLoadingModel.instanceId && - mediaCommonModel != newCommonModel + mediaDataLoadingModel.instanceId ) { - // Update media model if changed. - currentList[index] = newCommonModel + // When loading an update for an existing media control. + isNewToCurrentMedia = false + if (mediaCommonModel != newCommonModel) { + // Update media model if changed. + currentList[index] = newCommonModel + } } } - _currentMedia.value = currentList + if (isNewToCurrentMedia && it.active) { + _currentMedia.value = sortedMap.values.toList() + } else { + _currentMedia.value = currentList + } + } + + sortedMedia = sortedMap + + if (!isUpdate) { + val rank = sortedMedia.values.indexOf(newCommonModel) + if (isSmartspaceLoggingEnabled(newCommonModel, rank)) { + smartspaceLogger.logSmartspaceCardReceived( + it.smartspaceId, + it.appUid, + cardinality = _currentMedia.value.size, + isSsReactivated = mediaDataLoadingModel.isSsReactivated, + rank = rank, + ) + } + } else if (mediaDataLoadingModel.receivedSmartspaceCardLatency != 0) { + logSmartspaceAllMediaCards(mediaDataLoadingModel.receivedSmartspaceCardLatency) } } } - sortedMedia = sortedMap - // On removal we want to keep the order being shown to user. if (mediaDataLoadingModel is MediaDataLoadingModel.Removed) { _currentMedia.value = @@ -249,6 +278,7 @@ constructor( commonModel !is MediaCommonModel.MediaControl || mediaDataLoadingModel.instanceId != commonModel.mediaLoadedModel.instanceId } + sortedMedia = sortedMap } } @@ -271,21 +301,45 @@ constructor( isPlaying = false, active = _smartspaceMediaData.value.isActive, ) + val newCommonModel = MediaCommonModel.MediaRecommendations(smartspaceMediaLoadingModel) when (smartspaceMediaLoadingModel) { - is SmartspaceMediaLoadingModel.Loaded -> - sortedMap[sortKey] = - MediaCommonModel.MediaRecommendations(smartspaceMediaLoadingModel) - is SmartspaceMediaLoadingModel.Removed -> + is SmartspaceMediaLoadingModel.Loaded -> { + sortedMap[sortKey] = newCommonModel + _currentMedia.value = sortedMap.values.toList() + sortedMedia = sortedMap + + if (isRecommendationActive()) { + val hasActivatedExistedResumeMedia = + !hasActiveMedia() && + hasAnyMedia() && + smartspaceMediaLoadingModel.isPrioritized + if (hasActivatedExistedResumeMedia) { + // Log resume card received if resumable media card is reactivated and + // recommendation card is valid and ranked first + logSmartspaceAllMediaCards( + (systemClock.currentTimeMillis() - + _smartspaceMediaData.value.headphoneConnectionTimeMillis) + .toInt() + ) + } + + smartspaceLogger.logSmartspaceCardReceived( + SmallHash.hash(_smartspaceMediaData.value.targetId), + _smartspaceMediaData.value.getUid(applicationContext), + cardinality = _currentMedia.value.size, + isRecommendationCard = true, + rank = _currentMedia.value.indexOf(newCommonModel), + ) + } + } + is SmartspaceMediaLoadingModel.Removed -> { _currentMedia.value = _currentMedia.value.filter { commonModel -> commonModel !is MediaCommonModel.MediaRecommendations } + sortedMedia = sortedMap + } } - - if (sortedMap.size > sortedMedia.size) { - _currentMedia.value = sortedMap.values.toList() - } - sortedMedia = sortedMap } fun setOrderedMedia() { @@ -315,4 +369,35 @@ constructor( private fun isMediaFromRec(data: MediaData): Boolean { return data.isPlaying == true && mediaFromRecPackageName == data.packageName } + + /** Log all media cards if smartspace logging is enabled for each. */ + private fun logSmartspaceAllMediaCards(receivedSmartspaceCardLatency: Int) { + sortedMedia.values.forEachIndexed { index, mediaCommonModel -> + if (mediaCommonModel is MediaCommonModel.MediaControl) { + _selectedUserEntries.value[mediaCommonModel.mediaLoadedModel.instanceId]?.let { + it.smartspaceId = + SmallHash.hash(it.appUid + systemClock.currentTimeMillis().toInt()) + it.isImpressed = false + + if (isSmartspaceLoggingEnabled(mediaCommonModel, index)) { + smartspaceLogger.logSmartspaceCardReceived( + it.smartspaceId, + it.appUid, + cardinality = _currentMedia.value.size, + isSsReactivated = mediaCommonModel.mediaLoadedModel.isSsReactivated, + rank = index, + receivedLatencyMillis = receivedSmartspaceCardLatency, + ) + } + } + } + } + } + + private fun isSmartspaceLoggingEnabled(commonModel: MediaCommonModel, index: Int): Boolean { + return sortedMedia.size > index && + (_smartspaceMediaData.value.expiryTimeMs != 0L || + isRecommendationActive() || + commonModel is MediaCommonModel.MediaRecommendations) + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt index f78a0f959f3c..31bd4fb78ffa 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImpl.kt @@ -180,7 +180,13 @@ constructor( mediaData.instanceId ) mediaFilterRepository.addMediaDataLoadingState( - MediaDataLoadingModel.Loaded(lastActiveId) + MediaDataLoadingModel.Loaded( + lastActiveId, + receivedSmartspaceCardLatency = + (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis) + .toInt(), + isSsReactivated = true + ) ) mediaLoadingLogger.logMediaLoaded( mediaData.instanceId, diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt index 37dffd1955d6..adcfba75f498 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt @@ -86,6 +86,7 @@ import com.android.systemui.media.controls.util.MediaControllerFactory import com.android.systemui.media.controls.util.MediaDataUtils import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger +import com.android.systemui.media.controls.util.SmallHash import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.res.R @@ -721,6 +722,7 @@ class MediaDataProcessor( appUid = appUid, isExplicit = isExplicit, resumeProgress = progress, + smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()), ) ) } @@ -902,6 +904,7 @@ class MediaDataProcessor( instanceId = instanceId, appUid = appUid, isExplicit = isExplicit, + smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()), ) ) } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt index 11a562911a85..40b34779151d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt @@ -99,6 +99,12 @@ data class MediaData( /** Track progress (0 - 1) to display for players where [resumption] is true */ val resumeProgress: Double? = null, + + /** Smartspace Id, used for logging. */ + var smartspaceId: Int = -1, + + /** If media card was visible to user, used for logging. */ + var isImpressed: Boolean = false, ) { companion object { /** Media is playing on the local device */ diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt index 170f1f78a5a6..c8a02faea58a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaDataLoadingModel.kt @@ -27,6 +27,8 @@ sealed class MediaDataLoadingModel { data class Loaded( override val instanceId: InstanceId, val immediatelyUpdateUi: Boolean = true, + val receivedSmartspaceCardLatency: Int = 0, + val isSsReactivated: Boolean = false, ) : MediaDataLoadingModel() /** Media data has been removed. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaData.kt index 9e15dbbb64b8..96c3fa8fbc89 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/SmartspaceMediaData.kt @@ -48,6 +48,8 @@ data class SmartspaceMediaData( val instanceId: InstanceId? = null, /** The timestamp in milliseconds indicating when the card should be removed */ val expiryTimeMs: Long = 0L, + /** If recommendation card was visible to user, used for logging. */ + var isImpressed: Boolean = false, ) { /** * Indicates if all the data is valid. diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaSmartspaceLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaSmartspaceLogger.kt new file mode 100644 index 000000000000..01fbf4af7626 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaSmartspaceLogger.kt @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.controls.util + +import android.util.Log +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.shared.system.SysUiStatsLog +import javax.inject.Inject + +/** Logger class for Smartspace logging events. */ +@SysUISingleton +class MediaSmartspaceLogger @Inject constructor() { + /** + * Log Smartspace card received event + * + * @param instanceId id to uniquely identify a card. + * @param uid uid for the application that media comes from. + * @param cardinality number of card in carousel. + * @param isRecommendationCard whether media card being logged is a recommendations card. + * @param isSsReactivated indicates resume media card is reactivated by Smartspace + * recommendation signal + * @param rank the rank for media card in the media carousel, starting from 0 + * @param receivedLatencyMillis latency in milliseconds for card received events. + */ + fun logSmartspaceCardReceived( + instanceId: Int, + uid: Int, + cardinality: Int, + isRecommendationCard: Boolean = false, + isSsReactivated: Boolean = false, + rank: Int = 0, + receivedLatencyMillis: Int = 0, + ) { + logSmartspaceCardReported( + SMARTSPACE_CARD_RECEIVED_EVENT, + instanceId, + uid, + surfaces = + intArrayOf( + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN, + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__DREAM_OVERLAY, + ), + cardinality, + isRecommendationCard, + isSsReactivated, + rank = rank, + receivedLatencyMillis = receivedLatencyMillis, + ) + } + + /** + * Log Smartspace card UI event + * + * @param eventId id of the event. eg: dismiss, click, or seen. + * @param instanceId id to uniquely identify a card. + * @param uid uid for the application that media comes from. + * @param location location of media carousel holding media card. + * @param cardinality number of card in carousel. + * @param isRecommendationCard whether media card being logged is a recommendations card. + * @param isSsReactivated indicates resume media card is reactivated by Smartspace + * recommendation signal + * @param rank the rank for media card in the media carousel, starting from 0 + * @param isSwipeToDismiss whether is to log swipe-to-dismiss event + */ + fun logSmartspaceCardUIEvent( + eventId: Int, + instanceId: Int, + uid: Int, + location: Int, + cardinality: Int, + isRecommendationCard: Boolean = false, + isSsReactivated: Boolean = false, + rank: Int = 0, + isSwipeToDismiss: Boolean = false, + ) { + logSmartspaceCardReported( + eventId, + instanceId, + uid, + surfaces = intArrayOf(location), + cardinality, + isRecommendationCard, + isSsReactivated, + rank = rank, + isSwipeToDismiss = isSwipeToDismiss, + ) + } + + /** + * Log Smartspace events + * + * @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN) + * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new + * instanceId + * @param uid uid for the application that media comes from + * @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when + * the event happened + * @param cardinality number of card in carousel. + * @param isRecommendationCard whether media card being logged is a recommendations card. + * @param isSsReactivated indicates resume media card is reactivated by Smartspace + * recommendation signal + * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1 + * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc. + * @param interactedSubcardCardinality how many media items were shown to the user when there is + * user interaction + * @param rank the rank for media card in the media carousel, starting from 0 + * @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency + * between headphone connection to sysUI displays media recommendation card + * @param isSwipeToDismiss whether is to log swipe-to-dismiss event + */ + private fun logSmartspaceCardReported( + eventId: Int, + instanceId: Int, + uid: Int, + surfaces: IntArray, + cardinality: Int, + isRecommendationCard: Boolean, + isSsReactivated: Boolean, + interactedSubcardRank: Int = 0, + interactedSubcardCardinality: Int = 0, + rank: Int = 0, + receivedLatencyMillis: Int = 0, + isSwipeToDismiss: Boolean = false, + ) { + surfaces.forEach { surface -> + SysUiStatsLog.write( + SysUiStatsLog.SMARTSPACE_CARD_REPORTED, + eventId, + instanceId, + // Deprecated, replaced with AiAi feature type so we don't need to create logging + // card type for each new feature. + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD, + surface, + // Use -1 as rank value to indicate user swipe to dismiss the card + if (isSwipeToDismiss) -1 else rank, + cardinality, + if (isRecommendationCard) { + 15 // MEDIA_RECOMMENDATION + } else if (isSsReactivated) { + 43 // MEDIA_RESUME_SS_ACTIVATED + } else { + 31 // MEDIA_RESUME + }, + uid, + interactedSubcardRank, + interactedSubcardCardinality, + receivedLatencyMillis, + null, // Media cards cannot have subcards. + null // Media cards don't have dimensions today. + ) + + if (DEBUG) { + Log.d( + TAG, + "Log Smartspace card event id: $eventId instance id: $instanceId" + + " surface: $surface rank: $rank cardinality: $cardinality " + + "isRecommendationCard: $isRecommendationCard " + + "isSsReactivated: $isSsReactivated" + + "uid: $uid " + + "interactedSubcardRank: $interactedSubcardRank " + + "interactedSubcardCardinality: $interactedSubcardCardinality " + + "received_latency_millis: $receivedLatencyMillis" + ) + } + } + } + + companion object { + private const val TAG = "MediaSmartspaceLogger" + private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) + private const val SMARTSPACE_CARD_RECEIVED_EVENT = 759 + const val SMARTSPACE_CARD_CLICK_EVENT = 760 + const val SMARTSPACE_CARD_DISMISS_EVENT = 761 + const val SMARTSPACE_CARD_SEEN_EVENT = 800 + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt index ee8169423de2..47e069102035 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt @@ -98,7 +98,7 @@ constructor( createAndShow( packageName = null, aboveStatusBar = false, - dialogTransitionAnimatorController = null, + dialogTransitionAnimatorController = controller, includePlaybackAndAppMetadata = false, userHandle = null, ) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsController.kt index 2ffb7835f400..5f1688650cb2 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsController.kt @@ -18,6 +18,7 @@ package com.android.systemui.screenshot import android.app.assist.AssistContent import com.android.systemui.screenshot.ui.viewmodel.ActionButtonAppearance +import com.android.systemui.screenshot.ui.viewmodel.PreviewAction import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -84,9 +85,9 @@ constructor( } inner class ActionsCallback(private val screenshotId: UUID) { - fun providePreviewAction(onClick: () -> Unit) { + fun providePreviewAction(previewAction: PreviewAction) { if (screenshotId == currentScreenshotId) { - viewModel.setPreviewAction(onClick) + viewModel.setPreviewAction(previewAction) } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt index b8029c8b1cc3..c216f1da2dc1 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt @@ -29,6 +29,7 @@ import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_EDIT_TAPPED import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SHARE_TAPPED import com.android.systemui.screenshot.ui.viewmodel.ActionButtonAppearance +import com.android.systemui.screenshot.ui.viewmodel.PreviewAction import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -40,7 +41,9 @@ import java.util.UUID */ interface ScreenshotActionsProvider { fun onScrollChipReady(onClick: Runnable) + fun onScrollChipInvalidated() + fun setCompletedScreenshot(result: ScreenshotSavedResult) /** @@ -75,17 +78,19 @@ constructor( private var result: ScreenshotSavedResult? = null init { - actionsCallback.providePreviewAction { - debugLog(LogConfig.DEBUG_ACTIONS) { "Preview tapped" } - uiEventLogger.log(SCREENSHOT_PREVIEW_TAPPED, 0, request.packageNameString) - onDeferrableActionTapped { result -> - actionExecutor.startSharedTransition( - createEdit(result.uri, context), - result.user, - true - ) + actionsCallback.providePreviewAction( + PreviewAction(context.resources.getString(R.string.screenshot_edit_description)) { + debugLog(LogConfig.DEBUG_ACTIONS) { "Preview tapped" } + uiEventLogger.log(SCREENSHOT_PREVIEW_TAPPED, 0, request.packageNameString) + onDeferrableActionTapped { result -> + actionExecutor.startSharedTransition( + createEdit(result.uri, context), + result.user, + true + ) + } } - } + ) actionsCallback.provideActionButton( ActionButtonAppearance( diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java index d87d85b93b9d..59b47dc8d0ab 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java @@ -16,16 +16,20 @@ package com.android.systemui.screenshot.appclips; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; + import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_NAME; +import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_TASK_ID; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.PERMISSION_SELF; import android.app.Activity; import android.content.BroadcastReceiver; +import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -43,6 +47,7 @@ import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; +import android.widget.TextView; import androidx.activity.ComponentActivity; import androidx.annotation.Nullable; @@ -51,10 +56,13 @@ import androidx.lifecycle.ViewModelProvider; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger.UiEventEnum; import com.android.settingslib.Utils; +import com.android.systemui.Flags; import com.android.systemui.res.R; import com.android.systemui.screenshot.scroll.CropView; import com.android.systemui.settings.UserTracker; +import java.util.Set; + import javax.inject.Inject; /** @@ -73,8 +81,6 @@ import javax.inject.Inject; * * <p>This {@link Activity} runs in its own separate process to isolate memory intensive image * editing from SysUI process. - * - * TODO(b/267309532): Polish UI and animations. */ public class AppClipsActivity extends ComponentActivity { @@ -94,6 +100,7 @@ public class AppClipsActivity extends ComponentActivity { private CropView mCropView; private Button mSave; private Button mCancel; + private TextView mBacklinksData; private AppClipsViewModel mViewModel; private ResultReceiver mResultReceiver; @@ -153,11 +160,10 @@ public class AppClipsActivity extends ComponentActivity { mCancel = mLayout.findViewById(R.id.cancel); mSave.setOnClickListener(this::onClick); mCancel.setOnClickListener(this::onClick); - - mCropView = mLayout.findViewById(R.id.crop_view); - + mBacklinksData = mLayout.findViewById(R.id.backlinks_data); mPreview = mLayout.findViewById(R.id.preview); + mPreview.addOnLayoutChangeListener( (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> updateImageDimensions()); @@ -166,9 +172,19 @@ public class AppClipsActivity extends ComponentActivity { mViewModel.getScreenshot().observe(this, this::setScreenshot); mViewModel.getResultLiveData().observe(this, this::setResultThenFinish); mViewModel.getErrorLiveData().observe(this, this::setErrorThenFinish); + mViewModel.getBacklinksLiveData().observe(this, this::setBacklinksData); if (savedInstanceState == null) { - mViewModel.performScreenshot(); + int displayId = getDisplayId(); + mViewModel.performScreenshot(displayId); + + if (Flags.appClipsBacklinks()) { + int appClipsTaskId = getTaskId(); + int callingPackageTaskId = intent.getIntExtra(EXTRA_CALLING_PACKAGE_TASK_ID, + INVALID_TASK_ID); + Set<Integer> taskIdsToIgnore = Set.of(appClipsTaskId, callingPackageTaskId); + mViewModel.triggerBacklinks(taskIdsToIgnore, displayId); + } } } @@ -281,6 +297,15 @@ public class AppClipsActivity extends ComponentActivity { finish(); } + private void setBacklinksData(ClipData clipData) { + if (mBacklinksData.getVisibility() == View.GONE) { + mBacklinksData.setVisibility(View.VISIBLE); + } + + mBacklinksData.setText(String.format(getString(R.string.backlinks_string), + clipData.getDescription().getLabel())); + } + private void setError(int errorCode) { if (mResultReceiver == null) { return; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java index 7de22b1a9c77..aaa5dfc01ba3 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.os.UserHandle; +import android.util.Log; import androidx.annotation.Nullable; @@ -27,19 +28,18 @@ import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ServiceConnector; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Application; -import com.android.systemui.settings.DisplayTracker; import javax.inject.Inject; /** An intermediary singleton object to help communicating with the cross process service. */ @SysUISingleton class AppClipsCrossProcessHelper { + private static final String TAG = AppClipsCrossProcessHelper.class.getSimpleName(); private final ServiceConnector<IAppClipsScreenshotHelperService> mProxyConnector; - private final DisplayTracker mDisplayTracker; @Inject - AppClipsCrossProcessHelper(@Application Context context, DisplayTracker displayTracker) { + AppClipsCrossProcessHelper(@Application Context context) { // Start a service as main user so that even if the app clips activity is running as work // profile user the service is able to use correct instance of Bubbles to grab a screenshot // excluding the bubble layer. @@ -48,7 +48,6 @@ class AppClipsCrossProcessHelper { Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY | Context.BIND_NOT_VISIBLE, UserHandle.USER_SYSTEM, IAppClipsScreenshotHelperService.Stub::asInterface); - mDisplayTracker = displayTracker; } /** @@ -58,15 +57,16 @@ class AppClipsCrossProcessHelper { * pass around but not a {@link Bitmap}. */ @Nullable - Bitmap takeScreenshot() { + Bitmap takeScreenshot(int displayId) { try { AndroidFuture<ScreenshotHardwareBufferInternal> future = mProxyConnector.postForResult( - service -> - // Take a screenshot of the default display of the user. - service.takeScreenshot(mDisplayTracker.getDefaultDisplayId())); + service -> service.takeScreenshot(displayId)); return future.get().createBitmapThenCloseBuffer(); } catch (Exception e) { + Log.e(TAG, + String.format("Error while capturing a screenshot of displayId %d", displayId), + e); return null; } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java index 48449b393903..3c4469d052b1 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java @@ -85,6 +85,7 @@ public class AppClipsTrampolineActivity extends Activity { static final String ACTION_FINISH_FROM_TRAMPOLINE = TAG + "FINISH_FROM_TRAMPOLINE"; static final String EXTRA_RESULT_RECEIVER = TAG + "RESULT_RECEIVER"; static final String EXTRA_CALLING_PACKAGE_NAME = TAG + "CALLING_PACKAGE_NAME"; + static final String EXTRA_CALLING_PACKAGE_TASK_ID = TAG + "CALLING_PACKAGE_TASK_ID"; private static final ApplicationInfoFlags APPLICATION_INFO_FLAGS = ApplicationInfoFlags.of(0); private final NoteTaskController mNoteTaskController; @@ -193,12 +194,14 @@ public class AppClipsTrampolineActivity extends Activity { ComponentName componentName = ComponentName.unflattenFromString( getString(R.string.config_screenshotAppClipsActivityComponent)); String callingPackageName = getCallingPackage(); + int callingPackageTaskId = getTaskId(); Intent intent = new Intent() .setComponent(componentName) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .putExtra(EXTRA_RESULT_RECEIVER, mResultReceiver) - .putExtra(EXTRA_CALLING_PACKAGE_NAME, callingPackageName); + .putExtra(EXTRA_CALLING_PACKAGE_NAME, callingPackageName) + .putExtra(EXTRA_CALLING_PACKAGE_TASK_ID, callingPackageTaskId); try { startActivity(intent); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java index 630d3380f4d7..9bb7bbfbe4c3 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java @@ -16,9 +16,23 @@ package com.android.systemui.screenshot.appclips; +import static android.content.Intent.ACTION_MAIN; +import static android.content.Intent.ACTION_VIEW; import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED; +import static android.content.Intent.CATEGORY_LAUNCHER; +import static com.google.common.util.concurrent.Futures.withTimeout; + +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; + +import android.app.ActivityTaskManager.RootTaskInfo; +import android.app.IActivityTaskManager; +import android.app.WindowConfiguration; +import android.app.assist.AssistContent; +import android.content.ClipData; +import android.content.ComponentName; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.HardwareRenderer; import android.graphics.RecordingCanvas; @@ -26,10 +40,13 @@ import android.graphics.Rect; import android.graphics.RenderNode; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.RemoteException; import android.os.UserHandle; +import android.util.Log; import android.view.Display; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; @@ -37,22 +54,36 @@ import androidx.lifecycle.ViewModelProvider; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.screenshot.AssistContentRequester; import com.android.systemui.screenshot.ImageExporter; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; +import java.util.Collections; +import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; /** A {@link ViewModel} to help with the App Clips screenshot flow. */ final class AppClipsViewModel extends ViewModel { + private static final String TAG = AppClipsViewModel.class.getSimpleName(); + private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; private final ImageExporter mImageExporter; + private final IActivityTaskManager mAtmService; + private final AssistContentRequester mAssistContentRequester; + private final PackageManager mPackageManager; + @Main private final Executor mMainExecutor; @Background @@ -61,24 +92,34 @@ final class AppClipsViewModel extends ViewModel { private final MutableLiveData<Bitmap> mScreenshotLiveData; private final MutableLiveData<Uri> mResultLiveData; private final MutableLiveData<Integer> mErrorLiveData; + private final MutableLiveData<ClipData> mBacklinksLiveData; - AppClipsViewModel(AppClipsCrossProcessHelper appClipsCrossProcessHelper, - ImageExporter imageExporter, @Main Executor mainExecutor, - @Background Executor bgExecutor) { + private AppClipsViewModel(AppClipsCrossProcessHelper appClipsCrossProcessHelper, + ImageExporter imageExporter, IActivityTaskManager atmService, + AssistContentRequester assistContentRequester, PackageManager packageManager, + @Main Executor mainExecutor, @Background Executor bgExecutor) { mAppClipsCrossProcessHelper = appClipsCrossProcessHelper; mImageExporter = imageExporter; + mAtmService = atmService; + mAssistContentRequester = assistContentRequester; + mPackageManager = packageManager; mMainExecutor = mainExecutor; mBgExecutor = bgExecutor; mScreenshotLiveData = new MutableLiveData<>(); mResultLiveData = new MutableLiveData<>(); mErrorLiveData = new MutableLiveData<>(); + mBacklinksLiveData = new MutableLiveData<>(); } - /** Grabs a screenshot and updates the {@link Bitmap} set in screenshot {@link LiveData}. */ - void performScreenshot() { + /** + * Grabs a screenshot and updates the {@link Bitmap} set in screenshot {@link #getScreenshot()}. + * + * @param displayId id of the {@link Display} to capture screenshot. + */ + void performScreenshot(int displayId) { mBgExecutor.execute(() -> { - Bitmap screenshot = mAppClipsCrossProcessHelper.takeScreenshot(); + Bitmap screenshot = mAppClipsCrossProcessHelper.takeScreenshot(displayId); mMainExecutor.execute(() -> { if (screenshot == null) { mErrorLiveData.setValue(CAPTURE_CONTENT_FOR_NOTE_FAILED); @@ -89,6 +130,38 @@ final class AppClipsViewModel extends ViewModel { }); } + /** + * Triggers the Backlinks flow which: + * <ul> + * <li>Evaluates the task to query. + * <li>Requests {@link AssistContent} from that task. + * <li>Transforms the {@link AssistContent} into {@link ClipData} for Backlinks. + * <li>The {@link ClipData} is reported to activity via {@link #getBacklinksLiveData()}. + * </ul> + * + * @param taskIdsToIgnore id of the tasks to ignore when querying for {@link AssistContent} + * @param displayId id of the display to query tasks for Backlinks data + */ + void triggerBacklinks(Set<Integer> taskIdsToIgnore, int displayId) { + mBgExecutor.execute(() -> { + ListenableFuture<ClipData> backlinksData = getBacklinksData(taskIdsToIgnore, displayId); + Futures.addCallback(backlinksData, new FutureCallback<>() { + @Override + public void onSuccess(@Nullable ClipData result) { + if (result != null) { + mBacklinksLiveData.setValue(result); + } + } + + @Override + public void onFailure(Throwable t) { + Log.e(TAG, "Error querying for Backlinks data", t); + } + }, mMainExecutor); + + }); + } + /** Returns a {@link LiveData} that holds the captured screenshot. */ LiveData<Bitmap> getScreenshot() { return mScreenshotLiveData; @@ -107,6 +180,11 @@ final class AppClipsViewModel extends ViewModel { return mErrorLiveData; } + /** Returns a {@link LiveData} that holds the Backlinks data in {@link ClipData}. */ + LiveData<ClipData> getBacklinksLiveData() { + return mBacklinksLiveData; + } + /** * Saves the provided {@link Drawable} to storage then informs the result {@link Uri} to * {@link LiveData}. @@ -148,21 +226,144 @@ final class AppClipsViewModel extends ViewModel { return HardwareRenderer.createHardwareBitmap(output, bounds.width(), bounds.height()); } + private ListenableFuture<ClipData> getBacklinksData(Set<Integer> taskIdsToIgnore, + int displayId) { + return getAllRootTaskInfosOnDisplay(displayId) + .stream() + .filter(taskInfo -> shouldIncludeTask(taskInfo, taskIdsToIgnore)) + .findFirst() + .map(this::getBacklinksDataForTaskId) + .orElse(Futures.immediateFuture(null)); + } + + private List<RootTaskInfo> getAllRootTaskInfosOnDisplay(int displayId) { + try { + return mAtmService.getAllRootTaskInfosOnDisplay(displayId); + } catch (RemoteException e) { + Log.e(TAG, String.format("Error while querying for tasks on display %d", displayId), e); + return Collections.emptyList(); + } + } + + private boolean shouldIncludeTask(RootTaskInfo taskInfo, Set<Integer> taskIdsToIgnore) { + // Only consider tasks that shouldn't be ignored, are visible, running, and have a launcher + // icon. Furthermore, types such as launcher/home/dock/assistant are ignored. + return !taskIdsToIgnore.contains(taskInfo.taskId) + && taskInfo.isVisible + && taskInfo.isRunning + && taskInfo.numActivities > 0 + && taskInfo.topActivity != null + && taskInfo.topActivityInfo != null + && taskInfo.childTaskIds.length > 0 + && taskInfo.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_STANDARD + && canAppStartThroughLauncher(taskInfo.topActivity.getPackageName()); + } + + private boolean canAppStartThroughLauncher(String packageName) { + return getMainLauncherIntentForPackage(packageName).resolveActivity(mPackageManager) + != null; + } + + private ListenableFuture<ClipData> getBacklinksDataForTaskId(RootTaskInfo taskInfo) { + SettableFuture<ClipData> backlinksData = SettableFuture.create(); + int taskId = taskInfo.taskId; + mAssistContentRequester.requestAssistContent(taskId, assistContent -> + backlinksData.set(getBacklinksDataFromAssistContent(taskInfo, assistContent))); + return withTimeout(backlinksData, 5L, TimeUnit.SECONDS, newSingleThreadScheduledExecutor()); + } + + /** + * A utility method to get {@link ClipData} to use for Backlinks functionality from + * {@link AssistContent} received from the app whose screenshot is taken. + * + * <p>There are multiple ways an app can provide deep-linkable data via {@link AssistContent} + * but Backlinks restricts to using only one way. The following is the ordered list based on + * preference: + * <ul> + * <li>{@link AssistContent#getWebUri()} is the most preferred way. + * <li>Second preference is given to {@link AssistContent#getIntent()} when the app provides + * the intent, see {@link AssistContent#isAppProvidedIntent()}. + * <li>The last preference is given to an {@link Intent} that is built using + * {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER}. + * </ul> + * + * @param taskInfo {@link RootTaskInfo} of the task which provided the {@link AssistContent}. + * @param content the {@link AssistContent} to map into Backlinks {@link ClipData}. + * @return {@link ClipData} that represents the Backlinks data. + */ + private ClipData getBacklinksDataFromAssistContent(RootTaskInfo taskInfo, + @Nullable AssistContent content) { + String appName = getAppNameOfTask(taskInfo); + String packageName = taskInfo.topActivity.getPackageName(); + ClipData fallback = ClipData.newIntent(appName, + getMainLauncherIntentForPackage(packageName)); + if (content == null) { + return fallback; + } + + // First preference is given to app provided uri. + if (content.isAppProvidedWebUri()) { + Uri uri = content.getWebUri(); + Intent backlinksIntent = new Intent(ACTION_VIEW).setData(uri); + if (doesIntentResolveToSamePackage(backlinksIntent, packageName)) { + return ClipData.newRawUri(appName, uri); + } + } + + // Second preference is given to app provided, hopefully deep-linking, intent. + if (content.isAppProvidedIntent()) { + Intent backlinksIntent = content.getIntent(); + if (doesIntentResolveToSamePackage(backlinksIntent, packageName)) { + return ClipData.newIntent(appName, backlinksIntent); + } + } + + return fallback; + } + + private boolean doesIntentResolveToSamePackage(Intent intentToResolve, + String requiredPackageName) { + ComponentName resolvedComponent = intentToResolve.resolveActivity(mPackageManager); + if (resolvedComponent == null) { + return false; + } + + return resolvedComponent.getPackageName().equals(requiredPackageName); + } + + private String getAppNameOfTask(RootTaskInfo taskInfo) { + return taskInfo.topActivityInfo.loadLabel(mPackageManager).toString(); + } + + private Intent getMainLauncherIntentForPackage(String packageName) { + return new Intent(ACTION_MAIN) + .addCategory(CATEGORY_LAUNCHER) + .setPackage(packageName); + } + /** Helper factory to help with injecting {@link AppClipsViewModel}. */ static final class Factory implements ViewModelProvider.Factory { private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; private final ImageExporter mImageExporter; + private final IActivityTaskManager mAtmService; + private final AssistContentRequester mAssistContentRequester; + private final PackageManager mPackageManager; @Main private final Executor mMainExecutor; @Background private final Executor mBgExecutor; @Inject - Factory(AppClipsCrossProcessHelper appClipsCrossProcessHelper, ImageExporter imageExporter, - @Main Executor mainExecutor, @Background Executor bgExecutor) { + Factory(AppClipsCrossProcessHelper appClipsCrossProcessHelper, ImageExporter imageExporter, + IActivityTaskManager atmService, AssistContentRequester assistContentRequester, + PackageManager packageManager, @Main Executor mainExecutor, + @Background Executor bgExecutor) { mAppClipsCrossProcessHelper = appClipsCrossProcessHelper; mImageExporter = imageExporter; + mAtmService = atmService; + mAssistContentRequester = assistContentRequester; + mPackageManager = packageManager; mMainExecutor = mainExecutor; mBgExecutor = bgExecutor; } @@ -176,7 +377,8 @@ final class AppClipsViewModel extends ViewModel { //noinspection unchecked return (T) new AppClipsViewModel(mAppClipsCrossProcessHelper, mImageExporter, - mMainExecutor, mBgExecutor); + mAtmService, mAssistContentRequester, mPackageManager, mMainExecutor, + mBgExecutor); } } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt index 442b3873be4d..0fefa0b7757a 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt @@ -128,8 +128,9 @@ constructor(private val buttonViewBinder: ActionButtonViewBinder) { } } launch { - viewModel.previewAction.collect { onClick -> - previewView.setOnClickListener { onClick?.invoke() } + viewModel.previewAction.collect { action -> + previewView.setOnClickListener { action?.onClick?.invoke() } + previewView.contentDescription = action?.contentDescription } } launch { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt index 3f99bc4597cb..25420d44dc79 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModel.kt @@ -31,8 +31,8 @@ class ScreenshotViewModel(private val accessibilityManager: AccessibilityManager val scrollingScrim: StateFlow<Bitmap?> = _scrollingScrim private val _badge = MutableStateFlow<Drawable?>(null) val badge: StateFlow<Drawable?> = _badge - private val _previewAction = MutableStateFlow<(() -> Unit)?>(null) - val previewAction: StateFlow<(() -> Unit)?> = _previewAction + private val _previewAction = MutableStateFlow<PreviewAction?>(null) + val previewAction: StateFlow<PreviewAction?> = _previewAction private val _actions = MutableStateFlow(emptyList<ActionButtonViewModel>()) val actions: StateFlow<List<ActionButtonViewModel>> = _actions private val _animationState = MutableStateFlow(AnimationState.NOT_STARTED) @@ -57,8 +57,8 @@ class ScreenshotViewModel(private val accessibilityManager: AccessibilityManager _badge.value = badge } - fun setPreviewAction(onClick: () -> Unit) { - _previewAction.value = onClick + fun setPreviewAction(previewAction: PreviewAction) { + _previewAction.value = previewAction } fun addAction( @@ -149,6 +149,11 @@ class ScreenshotViewModel(private val accessibilityManager: AccessibilityManager } } +data class PreviewAction( + val contentDescription: CharSequence, + val onClick: () -> Unit, +) + enum class AnimationState { NOT_STARTED, ENTRANCE_STARTED, // The first 200ms of the entrance animation diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 71fe3712aaa4..1d43ec277222 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -1044,6 +1044,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump mView.setTranslationY(0f); }) .start(); + } else { + mView.postDelayed(() -> { + instantCollapse(); + }, unlockAnimationStartDelay); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 95cabfb53e72..1a7871a21016 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -386,6 +386,11 @@ public class KeyguardIndicationController { mStatusBarStateListener.onDozingChanged(mStatusBarStateController.isDozing()); } + @Nullable + public ViewGroup getIndicationArea() { + return mIndicationArea; + } + public void setIndicationArea(ViewGroup indicationArea) { mIndicationArea = indicationArea; mTopIndicationView = indicationArea.findViewById(R.id.keyguard_indication_text); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 190a2cd269ae..4ba673d632cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -2011,6 +2011,21 @@ public class ExpandableNotificationRow extends ActivatableNotificationView }; } + /** + * Retrieves an OnClickListener for the close button of a notification, which when invoked, + * dismisses the notificationc represented by the given ExpandableNotificationRow. + * + * @param row The ExpandableNotificationRow representing the notification to be dismissed. + * @return An OnClickListener instance that dismisses the notification(s) when invoked. + */ + public View.OnClickListener getCloseButtonOnClickListener(ExpandableNotificationRow row) { + return v -> { + if (row != null) { + row.performDismiss(false); + } + }; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Trace.beginSection(appendTraceStyleTag("ExpNotRow#onMeasure")); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java index 939424945038..f3521234e67a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java @@ -36,6 +36,7 @@ import androidx.annotation.Nullable; import com.android.app.animation.Interpolators; import com.android.internal.widget.CachingIconView; +import com.android.internal.widget.NotificationCloseButton; import com.android.internal.widget.NotificationExpandButton; import com.android.systemui.res.R; import com.android.systemui.statusbar.TransformableView; @@ -60,6 +61,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple = new PathInterpolator(0.4f, 0f, 0.7f, 1f); protected final ViewTransformationHelper mTransformationHelper; private CachingIconView mIcon; + private NotificationCloseButton mCloseButton; private NotificationExpandButton mExpandButton; private View mAltExpandTarget; private View mIconContainer; @@ -112,6 +114,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple TRANSFORMING_VIEW_TITLE); resolveHeaderViews(); addFeedbackOnClickListener(row); + addCloseButtonOnClickListener(row); } @Override @@ -150,6 +153,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple mNotificationTopLine = mView.findViewById(com.android.internal.R.id.notification_top_line); mAudiblyAlertedIcon = mView.findViewById(com.android.internal.R.id.alerted_icon); mFeedbackIcon = mView.findViewById(com.android.internal.R.id.feedback); + mCloseButton = mView.findViewById(com.android.internal.R.id.close_button); } private void addFeedbackOnClickListener(ExpandableNotificationRow row) { @@ -179,6 +183,13 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple } } + private void addCloseButtonOnClickListener(ExpandableNotificationRow row) { + View.OnClickListener listener = row.getCloseButtonOnClickListener(row); + if (mCloseButton != null && listener != null) { + mCloseButton.setOnClickListener(listener); + } + } + @Override public void onContentUpdated(ExpandableNotificationRow row) { super.onContentUpdated(row); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index 456c321a0c14..2cbb6aea53a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -64,6 +64,7 @@ public class AmbientState implements Dumpable { * Used to read bouncer states. */ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + private float mStackTop; private float mStackCutoff; private int mScrollY; private float mOverScrollTopAmount; @@ -186,6 +187,7 @@ public class AmbientState implements Dumpable { * @param stackY Distance of top of notifications panel from top of screen. */ public void setStackY(float stackY) { + SceneContainerFlag.assertInLegacyMode(); mStackY = stackY; } @@ -193,6 +195,7 @@ public class AmbientState implements Dumpable { * @return Distance of top of notifications panel from top of screen. */ public float getStackY() { + SceneContainerFlag.assertInLegacyMode(); return mStackY; } @@ -348,6 +351,18 @@ public class AmbientState implements Dumpable { return mZDistanceBetweenElements; } + /** Y coordinate in view pixels of the top of the notification stack */ + public float getStackTop() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return 0f; + return mStackTop; + } + + /** @see #getStackTop() */ + public void setStackTop(float mStackTop) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; + this.mStackTop = mStackTop; + } + /** * Y coordinate in view pixels above which the bottom of the notification stack / shelf / footer * must be. @@ -769,6 +784,8 @@ public class AmbientState implements Dumpable { @Override public void dump(PrintWriter pw, String[] args) { + pw.println("mStackTop=" + mStackTop); + pw.println("mStackCutoff" + mStackCutoff); pw.println("mTopPadding=" + mTopPadding); pw.println("mStackTopMargin=" + mStackTopMargin); pw.println("mStackTranslation=" + mStackTranslation); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 0e77ed44293a..1eee466f0d56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -834,7 +834,7 @@ public class NotificationStackScrollLayout drawDebugInfo(canvas, y, Color.RED, /* label= */ "y = " + y); if (SceneContainerFlag.isEnabled()) { - y = (int) mScrollViewFields.getStackTop(); + y = (int) mAmbientState.getStackTop(); drawDebugInfo(canvas, y, Color.RED, /* label= */ "getStackTop() = " + y); y = (int) mAmbientState.getStackCutoff(); @@ -1181,9 +1181,11 @@ public class NotificationStackScrollLayout updateAlgorithmLayoutMinHeight(); updateOwnTranslationZ(); - // Give The Algorithm information regarding the QS height so it can layout notifications - // properly. Needed for some devices that grows notifications down-to-top - mStackScrollAlgorithm.updateQSFrameTop(mQsHeader == null ? 0 : mQsHeader.getHeight()); + if (!SceneContainerFlag.isEnabled()) { + // Give The Algorithm information regarding the QS height so it can layout notifications + // properly. Needed for some devices that grows notifications down-to-top + mStackScrollAlgorithm.updateQSFrameTop(mQsHeader == null ? 0 : mQsHeader.getHeight()); + } // Once the layout has finished, we don't need to animate any scrolling clampings anymore. mAnimateStackYForContentHeightChange = false; @@ -1214,7 +1216,7 @@ public class NotificationStackScrollLayout @Override public void setStackTop(float stackTop) { - mScrollViewFields.setStackTop(stackTop); + mAmbientState.setStackTop(stackTop); // TODO(b/332574413): replace the following with using stackTop updateTopPadding(stackTop, isAddOrRemoveAnimationPending()); } @@ -1424,11 +1426,7 @@ public class NotificationStackScrollLayout if (mAmbientState.isBouncerInTransit() && mQsExpansionFraction > 0f) { fraction = BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(fraction); } - // TODO(b/322228881): Clean up scene container vs legacy behavior in NSSL - if (SceneContainerFlag.isEnabled()) { - // stackY should be driven by scene container, not NSSL - mAmbientState.setStackY(getTopPadding()); - } else { + if (!SceneContainerFlag.isEnabled()) { final float stackY = MathUtils.lerp(0, endTopPosition, fraction); mAmbientState.setStackY(stackY); } @@ -1811,6 +1809,7 @@ public class NotificationStackScrollLayout } public void setQsHeader(ViewGroup qsHeader) { + SceneContainerFlag.assertInLegacyMode(); mQsHeader = qsHeader; } @@ -2662,6 +2661,7 @@ public class NotificationStackScrollLayout } public void setMaxTopPadding(int maxTopPadding) { + SceneContainerFlag.assertInLegacyMode(); mMaxTopPadding = maxTopPadding; } @@ -2682,6 +2682,7 @@ public class NotificationStackScrollLayout } public float getTopPaddingOverflow() { + SceneContainerFlag.assertInLegacyMode(); return mTopPaddingOverflow; } @@ -3721,7 +3722,7 @@ public class NotificationStackScrollLayout protected boolean isInsideQsHeader(MotionEvent ev) { if (SceneContainerFlag.isEnabled()) { - return ev.getY() < mScrollViewFields.getStackTop(); + return ev.getY() < mAmbientState.getStackTop(); } mQsHeader.getBoundsOnScreen(mQsHeaderBound); @@ -4641,6 +4642,7 @@ public class NotificationStackScrollLayout } public boolean isEmptyShadeViewVisible() { + SceneContainerFlag.assertInLegacyMode(); return mEmptyShadeView.isVisible(); } @@ -4919,6 +4921,7 @@ public class NotificationStackScrollLayout } public void setQsFullScreen(boolean qsFullScreen) { + SceneContainerFlag.assertInLegacyMode(); if (FooterViewRefactor.isEnabled()) { if (qsFullScreen == mQsFullScreen) { return; // no change @@ -5095,6 +5098,7 @@ public class NotificationStackScrollLayout } public void setExpandingVelocity(float expandingVelocity) { + SceneContainerFlag.assertInLegacyMode(); mAmbientState.setExpandingVelocity(expandingVelocity); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt index 2e86ad97a5f4..97ec39192cc8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt @@ -32,8 +32,6 @@ import java.util.function.Consumer class ScrollViewFields { /** Used to produce the clipping path */ var scrimClippingShape: ShadeScrimShape? = null - /** Y coordinate in view pixels of the top of the notification stack */ - var stackTop: Float = 0f /** Y coordinate in view pixels of the top of the HUN */ var headsUpTop: Float = 0f /** Whether the notifications are scrolled all the way to the top (i.e. when freshly opened) */ @@ -76,7 +74,6 @@ class ScrollViewFields { fun dump(pw: IndentingPrintWriter) { pw.printSection("StackViewStates") { pw.println("scrimClippingShape", scrimClippingShape) - pw.println("stackTop", stackTop) pw.println("headsUpTop", headsUpTop) pw.println("isScrolledToTop", isScrolledToTop) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index f9efc07c67fb..ca74c0e6f9e1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -29,6 +29,7 @@ import com.android.internal.policy.SystemBarUtils; import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.res.R; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.shade.transition.LargeScreenShadeInterpolator; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.NotificationShelf; @@ -332,8 +333,10 @@ public class StackScrollAlgorithm { private void updateClipping(StackScrollAlgorithmState algorithmState, AmbientState ambientState) { - float drawStart = ambientState.isOnKeyguard() ? 0 + float stackTop = SceneContainerFlag.isEnabled() ? ambientState.getStackTop() : ambientState.getStackY() - ambientState.getScrollY(); + float drawStart = ambientState.isOnKeyguard() ? 0 + : stackTop; float clipStart = 0; int childCount = algorithmState.visibleChildren.size(); boolean firstHeadsUp = true; @@ -641,7 +644,10 @@ public class StackScrollAlgorithm { // Incoming views have yTranslation=0 by default. viewState.setYTranslation(algorithmState.mCurrentYPosition); - float viewEnd = viewState.getYTranslation() + viewState.height + ambientState.getStackY(); + float stackTop = SceneContainerFlag.isEnabled() + ? ambientState.getStackTop() + : ambientState.getStackY(); + float viewEnd = stackTop + viewState.getYTranslation() + viewState.height; maybeUpdateHeadsUpIsVisible(viewState, ambientState.isShadeExpanded(), view.mustStayOnScreen(), /* topVisible= */ viewState.getYTranslation() >= mNotificationScrimPadding, @@ -681,7 +687,9 @@ public class StackScrollAlgorithm { } } else { if (view instanceof EmptyShadeView) { - float fullHeight = ambientState.getLayoutMaxHeight() + mMarginBottom + float fullHeight = SceneContainerFlag.isEnabled() + ? ambientState.getStackCutoff() - ambientState.getStackTop() + : ambientState.getLayoutMaxHeight() + mMarginBottom - ambientState.getStackY(); viewState.setYTranslation((fullHeight - getMaxAllowedChildHeight(view)) / 2f); } else if (view != ambientState.getTrackedHeadsUpRow()) { @@ -726,7 +734,7 @@ public class StackScrollAlgorithm { + mPaddingBetweenElements; setLocation(view.getViewState(), algorithmState.mCurrentYPosition, i); - viewState.setYTranslation(viewState.getYTranslation() + ambientState.getStackY()); + viewState.setYTranslation(viewState.getYTranslation() + stackTop); } @VisibleForTesting @@ -1002,8 +1010,11 @@ public class StackScrollAlgorithm { // Animate pinned HUN bottom corners to and from original roundness. final float originalCornerRadius = row.isLastInSection() ? 1f : (mSmallCornerRadius / mLargeCornerRadius); + final float stackTop = SceneContainerFlag.isEnabled() + ? ambientState.getStackTop() + : ambientState.getStackY(); final float bottomValue = computeCornerRoundnessForPinnedHun(mHostView.getHeight(), - ambientState.getStackY(), getMaxAllowedChildHeight(row), originalCornerRadius); + stackTop, getMaxAllowedChildHeight(row), originalCornerRadius); row.requestBottomRoundness(bottomValue, STACK_SCROLL_ALGO); row.addOnDetachResetRoundness(STACK_SCROLL_ALGO); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt index 7f1faeeb381d..cfcd6b14010d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt @@ -16,15 +16,23 @@ package com.android.systemui.volume.panel.component.spatial.domain.interactor +import android.bluetooth.BluetoothProfile import android.media.AudioDeviceAttributes import android.media.AudioDeviceInfo +import android.media.AudioManager +import com.android.settingslib.bluetooth.CachedBluetoothDevice +import com.android.settingslib.bluetooth.LocalBluetoothProfile +import com.android.settingslib.flags.Flags import com.android.settingslib.media.domain.interactor.SpatializerInteractor +import com.android.settingslib.volume.data.repository.AudioRepository +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.volume.domain.interactor.AudioOutputInteractor import com.android.systemui.volume.domain.model.AudioOutputDevice import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioAvailabilityModel import com.android.systemui.volume.panel.component.spatial.domain.model.SpatialAudioEnabledModel import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import javax.inject.Inject +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted @@ -33,6 +41,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.withContext /** * Provides an ability to access and update spatial audio and head tracking state. @@ -46,6 +55,8 @@ class SpatialAudioComponentInteractor constructor( audioOutputInteractor: AudioOutputInteractor, private val spatializerInteractor: SpatializerInteractor, + private val audioRepository: AudioRepository, + @Background private val backgroundCoroutineContext: CoroutineContext, @VolumePanelScope private val coroutineScope: CoroutineScope, ) { @@ -138,42 +149,85 @@ constructor( } private suspend fun AudioOutputDevice.getAudioDeviceAttributes(): AudioDeviceAttributes? { - when (this) { - is AudioOutputDevice.BuiltIn -> return builtinSpeaker + return when (this) { + is AudioOutputDevice.BuiltIn -> builtinSpeaker is AudioOutputDevice.Bluetooth -> { - return listOf( - AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_HEADSET, - cachedBluetoothDevice.address, - ), - AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_SPEAKER, - cachedBluetoothDevice.address, - ), - AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_BROADCAST, - cachedBluetoothDevice.address, - ), - AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, - cachedBluetoothDevice.address, - ), - AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_HEARING_AID, - cachedBluetoothDevice.address, + if (Flags.enableDeterminingSpatialAudioAttributesByProfile()) { + getAudioDeviceAttributesByBluetoothProfile(cachedBluetoothDevice) + } else { + listOf( + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_HEADSET, + cachedBluetoothDevice.address, + ), + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_SPEAKER, + cachedBluetoothDevice.address, + ), + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLE_BROADCAST, + cachedBluetoothDevice.address, + ), + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, + cachedBluetoothDevice.address, + ), + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + AudioDeviceInfo.TYPE_HEARING_AID, + cachedBluetoothDevice.address, + ) ) - ) - .firstOrNull { spatializerInteractor.isSpatialAudioAvailable(it) } + .firstOrNull { spatializerInteractor.isSpatialAudioAvailable(it) } + } } - else -> return null + else -> null } } + private suspend fun getAudioDeviceAttributesByBluetoothProfile( + cachedBluetoothDevice: CachedBluetoothDevice + ): AudioDeviceAttributes? = + withContext(backgroundCoroutineContext) { + cachedBluetoothDevice.profiles + .firstOrNull { + it.profileId in audioProfiles && it.isEnabled(cachedBluetoothDevice.device) + } + ?.let { profile: LocalBluetoothProfile -> + when (profile.profileId) { + BluetoothProfile.A2DP -> { + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP + } + BluetoothProfile.LE_AUDIO -> { + when ( + audioRepository.getBluetoothAudioDeviceCategory( + cachedBluetoothDevice.address + ) + ) { + AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER -> + AudioDeviceInfo.TYPE_BLE_SPEAKER + else -> AudioDeviceInfo.TYPE_BLE_HEADSET + } + } + BluetoothProfile.HEARING_AID -> { + AudioDeviceInfo.TYPE_HEARING_AID + } + else -> null + } + } + ?.let { + AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + it, + cachedBluetoothDevice.address, + ) + } + } + private companion object { val builtinSpeaker = AudioDeviceAttributes( @@ -181,5 +235,7 @@ constructor( AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "" ) + val audioProfiles = + setOf(BluetoothProfile.A2DP, BluetoothProfile.LE_AUDIO, BluetoothProfile.HEARING_AID) } } diff --git a/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleIsolationTest.kt b/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleIsolationTest.kt index 2d84fbafcf6c..5b3f08f7bcac 100644 --- a/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleIsolationTest.kt +++ b/packages/SystemUI/tests/src/androidx/core/animation/AnimatorTestRuleIsolationTest.kt @@ -15,8 +15,8 @@ */ package androidx.core.animation -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.doOnEnd @@ -29,7 +29,7 @@ import org.junit.runner.RunWith * This test class validates that two tests' animators are isolated from each other when using the * same animator test rule. This is a test to prevent future instances of b/275602127. */ -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @RunWithLooper class AnimatorTestRuleIsolationTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java index 52af8fb62943..6ee8ffd91ab0 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java @@ -18,10 +18,10 @@ package com.android.keyguard; import static com.google.common.truth.Truth.assertThat; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -32,7 +32,7 @@ import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @RunWithLooper public class AuthKeyguardMessageAreaTest extends SysuiTestCase { private KeyguardMessageArea mKeyguardMessageArea; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/BouncerKeyguardMessageAreaTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/BouncerKeyguardMessageAreaTest.kt index ba46a874c260..049d77a7a454 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/BouncerKeyguardMessageAreaTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/BouncerKeyguardMessageAreaTest.kt @@ -17,9 +17,9 @@ package com.android.keyguard import android.content.Context -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.util.AttributeSet +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -31,7 +31,7 @@ import org.mockito.Mockito.times import org.mockito.Mockito.verify @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper class BouncerKeyguardMessageAreaTest : SysuiTestCase() { class FakeBouncerKeyguardMessageArea(context: Context, attrs: AttributeSet?) : diff --git a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt index 6512e70c51e1..bb2340aafbb5 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt @@ -16,15 +16,15 @@ package com.android.keyguard +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import android.testing.AndroidTestingRunner import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class BouncerPanelExpansionCalculatorTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java index 0a3225eecbe4..a8ab922a90b9 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java @@ -50,9 +50,9 @@ import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.testing.AndroidTestingRunner; import android.text.TextUtils; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.keyguard.logging.CarrierTextManagerLogger; @@ -84,7 +84,7 @@ import java.util.HashMap; import java.util.List; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class CarrierTextManagerTest extends SysuiTestCase { private static final CharSequence SEPARATOR = " \u2014 "; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt index 69a6f2aed4c4..79933ee3b018 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt @@ -16,10 +16,10 @@ package com.android.keyguard import android.content.BroadcastReceiver -import android.testing.AndroidTestingRunner import android.view.View import android.view.ViewTreeObserver import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher @@ -76,7 +76,7 @@ import org.mockito.junit.MockitoJUnit import com.android.systemui.Flags as AConfigFlags import org.mockito.Mockito.`when` as whenever -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class ClockEventControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt index 9a95b17fc7d1..347605de6616 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt @@ -21,8 +21,8 @@ import android.content.pm.PackageManager import android.os.PowerManager import android.telecom.TelecomManager import android.telephony.TelephonyManager -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger import com.android.internal.widget.LockPatternUtils @@ -45,7 +45,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class EmergencyButtonControllerTest : SysuiTestCase() { @Mock lateinit var emergencyButton: EmergencyButton diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java index f9fe5e7e2b62..e724c60bfc54 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java @@ -28,10 +28,10 @@ import static org.mockito.Mockito.when; import android.os.SystemClock; import android.platform.test.annotations.EnableFlags; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.KeyEvent; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.util.LatencyTracker; @@ -54,7 +54,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @RunWithLooper public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt index 634dac16d1ec..d170e4840842 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt @@ -17,7 +17,7 @@ package com.android.keyguard import android.hardware.biometrics.BiometricSourceType -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.UiEventLogger @@ -38,7 +38,7 @@ import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class KeyguardBiometricLockoutLoggerTest : SysuiTestCase() { @Mock diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index cfa74f0ef432..1d7816848cd0 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -30,9 +30,9 @@ import static org.mockito.Mockito.when; import android.database.ContentObserver; import android.os.UserHandle; import android.provider.Settings; -import android.testing.AndroidTestingRunner; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.Flags; @@ -47,7 +47,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.verification.VerificationMode; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class KeyguardClockSwitchControllerTest extends KeyguardClockSwitchControllerBaseTest { @Test public void testInit_viewAlreadyAttached() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt index 9a1a4e294e05..c2c0f5713d9b 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt @@ -16,8 +16,8 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED import kotlinx.coroutines.Dispatchers @@ -26,7 +26,7 @@ import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class KeyguardClockSwitchControllerWithCoroutinesTest : KeyguardClockSwitchControllerBaseTest() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java index e2063d2f8a04..83443bee744e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java @@ -30,7 +30,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.content.Context; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -39,6 +38,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.TextView; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.Flags; @@ -55,7 +55,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) // Need to run on the main thread because KeyguardSliceView$Row init checks for // the main thread before acquiring a wake lock. This class is constructed when // the keyguard_clock_switch layout is inflated. diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java index cc36cfa6a30a..dd58ea7db2bc 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardDisplayManagerTest.java @@ -28,11 +28,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.display.DisplayManagerGlobal; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Display; import android.view.DisplayInfo; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -49,7 +49,7 @@ import org.mockito.MockitoAnnotations; import java.util.concurrent.Executor; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper public class KeyguardDisplayManagerTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java index 6228ff837340..bd811814eb24 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java @@ -27,11 +27,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.biometrics.BiometricSourceType; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.text.Editable; import android.text.TextWatcher; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -47,7 +47,7 @@ import org.mockito.MockitoAnnotations; @SmallTest @TestableLooper.RunWithLooper -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class KeyguardMessageAreaControllerTest extends SysuiTestCase { @Mock private ConfigurationController mConfigurationController; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java index c566826fdf19..8b5372a1f035 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java @@ -23,11 +23,11 @@ import static org.mockito.Mockito.when; import android.content.pm.PackageManager; import android.os.Handler; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -47,7 +47,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @RunWithLooper(setAsMainLooper = true) public class KeyguardSliceViewControllerTest extends SysuiTestCase { @Mock diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java index a0e80653792d..d96518abc007 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java @@ -17,7 +17,6 @@ package com.android.keyguard; import android.graphics.Color; import android.net.Uri; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; @@ -26,6 +25,7 @@ import androidx.slice.SliceProvider; import androidx.slice.SliceSpecs; import androidx.slice.builders.ListBuilder; import androidx.slice.widget.RowContent; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -44,7 +44,7 @@ import java.util.concurrent.atomic.AtomicBoolean; @SmallTest @RunWithLooper(setAsMainLooper = true) -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class KeyguardSliceViewTest extends SysuiTestCase { private KeyguardSliceView mKeyguardSliceView; private Uri mSliceUri; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt index ed61ee12849f..64e499674d9f 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt @@ -1,7 +1,7 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Assert.assertEquals @@ -10,7 +10,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) class KeyguardStatusAreaViewTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt index 3b57d8f85d83..c29439d89753 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt @@ -16,8 +16,8 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.power.shared.model.ScreenPowerState import kotlinx.coroutines.cancelChildren @@ -29,7 +29,7 @@ import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest class KeyguardStatusViewControllerWithCoroutinesTest : KeyguardStatusViewControllerBaseTest() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt index afd2034424ff..16d2f0205c84 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt @@ -1,7 +1,7 @@ package com.android.keyguard +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.LayoutInflater import android.view.View @@ -15,7 +15,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) class KeyguardStatusViewTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt index 336183d71ff1..2e41246a62a1 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt @@ -16,8 +16,9 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.view.View +import android.view.ViewGroup +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.ui.view.KeyguardRootView @@ -43,7 +44,7 @@ import org.mockito.kotlin.whenever * the set of ids, which also dictact which direction to move and when, via a filter fn. */ @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class KeyguardUnfoldTransitionTest : SysuiTestCase() { private val kosmos = Kosmos() diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index ee0cefb1949f..075d8ae0adac 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -108,10 +108,10 @@ import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.text.TextUtils; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.dx.mockito.inline.extended.ExtendedMockito; @@ -176,7 +176,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper public class KeyguardUpdateMonitorTest extends SysuiTestCase { private static final String PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY = diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt index c6740535d903..e7b4262419ce 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt @@ -15,8 +15,8 @@ */ package com.android.keyguard -import android.testing.AndroidTestingRunner import androidx.core.view.accessibility.AccessibilityNodeInfoCompat +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -25,7 +25,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class KeyguardUserSwitcherAnchorTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java index 255c7d909194..c1ba39e89cf9 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerTest.java @@ -32,12 +32,12 @@ import static org.mockito.Mockito.when; import android.graphics.Point; import android.hardware.biometrics.BiometricSourceType; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.Pair; import android.view.HapticFeedbackConstants; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.biometrics.UdfpsController; @@ -50,7 +50,7 @@ import org.junit.Test; import org.junit.runner.RunWith; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper public class LegacyLockIconViewControllerTest extends LegacyLockIconViewControllerBaseTest { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerWithCoroutinesTest.kt index 958013908e44..2fd3cb0f0592 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/LegacyLockIconViewControllerWithCoroutinesTest.kt @@ -16,8 +16,8 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.LockIconView.ICON_LOCK import com.android.systemui.doze.util.getBurnInOffset @@ -33,7 +33,7 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.reset import org.mockito.Mockito.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class LegacyLockIconViewControllerWithCoroutinesTest : LegacyLockIconViewControllerBaseTest() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/NumPadAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/NumPadAnimatorTest.kt index 7c2550f465f6..18976e135e9c 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/NumPadAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/NumPadAnimatorTest.kt @@ -17,8 +17,8 @@ package com.android.keyguard import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Before @@ -32,7 +32,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class NumPadAnimatorTest : SysuiTestCase() { @Mock lateinit var background: GradientDrawable diff --git a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt index 835c9ff51381..d8f2b1016657 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt @@ -16,9 +16,9 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.LayoutInflater +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -28,7 +28,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class PinShapeHintingViewTest : SysuiTestCase() { lateinit var underTest: PinShapeHintingView diff --git a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt index d431731b710e..447cf65ba293 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt @@ -16,9 +16,9 @@ package com.android.keyguard -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.LayoutInflater +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -28,7 +28,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class PinShapeNonHintingViewTest : SysuiTestCase() { lateinit var underTest: PinShapeNonHintingView diff --git a/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt index 9f9b9a478561..c7d11ef16100 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt @@ -16,10 +16,10 @@ package com.android.keyguard import android.animation.Animator -import android.testing.AndroidTestingRunner import android.transition.TransitionValues import android.view.View import android.view.ViewGroup +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardStatusViewController.SplitShadeTransitionAdapter import com.android.systemui.SysuiTestCase @@ -32,7 +32,7 @@ import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class SplitShadeTransitionAdapterTest : SysuiTestCase() { @Mock private lateinit var KeyguardClockSwitchController: KeyguardClockSwitchController diff --git a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt index fb649c8f3891..5247a89896d1 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt @@ -19,7 +19,7 @@ package com.android.keyguard.mediator import android.os.Looper import android.platform.test.flag.junit.SetFlagsRule import android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags import com.android.systemui.SysuiTestCase @@ -43,7 +43,7 @@ import org.mockito.MockitoAnnotations import java.util.Optional @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class ScreenOnCoordinatorTest : SysuiTestCase() { @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt b/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt index 2551650c47d0..0a9ce6854ca8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt @@ -16,7 +16,7 @@ package com.android.systemui -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.dump.DumpManager import org.junit.Assert.assertFalse @@ -30,7 +30,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class BootCompleteCacheTest : SysuiTestCase() { @@ -116,4 +116,4 @@ class BootCompleteCacheTest : SysuiTestCase() { verify(bootCompleteListener, never()).onBootComplete() } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt index f776a63c54ae..a23e82918845 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt @@ -4,8 +4,8 @@ import android.graphics.Path import android.graphics.Rect import android.graphics.RectF import android.hardware.camera2.CameraManager -import android.testing.AndroidTestingRunner import android.util.PathParser +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.util.mockito.any @@ -19,7 +19,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class CameraAvailabilityListenerTest : SysuiTestCase() { companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java index 2e040077c227..006864489170 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java @@ -18,14 +18,17 @@ import static org.junit.Assert.assertEquals; import android.os.Looper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Test; +import org.junit.runner.RunWith; import java.util.concurrent.ExecutionException; @SmallTest +@RunWith(AndroidJUnit4.class) public class DependencyTest extends SysuiTestCase { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt index 588620646b73..091072f30ecd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt @@ -23,11 +23,11 @@ import android.graphics.Path import android.graphics.Rect import android.graphics.RectF import android.graphics.Region -import android.testing.AndroidTestingRunner import android.view.Display import android.view.DisplayCutout import android.view.DisplayInfo import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.never import com.android.internal.R @@ -42,7 +42,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class DisplayCutoutBaseViewTest : SysuiTestCase() { @@ -183,4 +183,4 @@ class DisplayCutoutBaseViewTest : SysuiTestCase() { return@then true } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt index 46936d6223a1..bc12aaaa52d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt @@ -16,11 +16,11 @@ package com.android.systemui import android.graphics.Point import android.hardware.display.DisplayManagerGlobal -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.Display import android.view.DisplayAdjustments import android.view.DisplayInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.R import com.android.keyguard.KeyguardUpdateMonitor @@ -42,7 +42,7 @@ import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations @RunWithLooper -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class FaceScanningProviderFactoryTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt index d500b5aebcbf..fb60ba381c40 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt @@ -22,11 +22,11 @@ import android.graphics.PixelFormat import android.graphics.Rect import android.graphics.RectF import android.hardware.graphics.common.DisplayDecorationSupport -import android.testing.AndroidTestingRunner import android.view.Display import android.view.DisplayCutout import android.view.DisplayInfo import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.R import com.android.systemui.util.mockito.eq @@ -39,7 +39,7 @@ import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class ScreenDecorHwcLayerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 54a14a292ba1..997f8a844d69 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -61,7 +61,6 @@ import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.hardware.graphics.common.DisplayDecorationSupport; import android.os.Handler; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.PathParser; @@ -78,6 +77,7 @@ import android.view.WindowMetrics; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; @@ -121,7 +121,7 @@ import java.util.ArrayList; import java.util.List; @RunWithLooper -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @SmallTest public class ScreenDecorationsTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java index f46b2f905f5b..53b98d52e9d1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java @@ -26,10 +26,14 @@ import static org.mockito.Mockito.when; import android.hardware.input.InputManager; import android.os.RemoteException; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.testing.TestableLooper; import android.view.KeyEvent; +import android.view.accessibility.Flags; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -44,6 +48,7 @@ import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -77,6 +82,9 @@ public class SystemActionsTest extends SysuiTestCase { private SystemActions mSystemActions; + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); @@ -131,4 +139,40 @@ public class SystemActionsTest extends SysuiTestCase { verify(mTelecomManager).endCall(); } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_GLOBAL_ACTION_MENU) + public void handleMenu_injectsKeyEvents() { + final List<KeyEvent> keyEvents = new ArrayList<>(); + doAnswer(invocation -> { + keyEvents.add(new KeyEvent(invocation.getArgument(0))); + return null; + }).when(mInputManager).injectInputEvent(any(), anyInt()); + + mSystemActions.handleMenu(); + + assertThat(keyEvents.size()).isEqualTo(2); + assertThat(keyEvents.get(0).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_MENU); + assertThat(keyEvents.get(0).getAction()).isEqualTo(KeyEvent.ACTION_DOWN); + assertThat(keyEvents.get(1).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_MENU); + assertThat(keyEvents.get(1).getAction()).isEqualTo(KeyEvent.ACTION_UP); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_GLOBAL_ACTION_MEDIA_PLAY_PAUSE) + public void handleMediaPlayPause_injectsKeyEvents() { + final List<KeyEvent> keyEvents = new ArrayList<>(); + doAnswer(invocation -> { + keyEvents.add(new KeyEvent(invocation.getArgument(0))); + return null; + }).when(mInputManager).injectInputEvent(any(), anyInt()); + + mSystemActions.handleMediaPlayPause(); + + assertThat(keyEvents.size()).isEqualTo(2); + assertThat(keyEvents.get(0).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); + assertThat(keyEvents.get(0).getAction()).isEqualTo(KeyEvent.ACTION_DOWN); + assertThat(keyEvents.get(1).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); + assertThat(keyEvents.get(1).getAction()).isEqualTo(KeyEvent.ACTION_UP); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java index 38095c83367d..c30bedde557d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java @@ -258,8 +258,9 @@ public class MenuViewLayerTest extends SysuiTestCase { setupEnabledAccessibilityServiceList(); mMenuViewLayer.mDismissMenuAction.run(); - final String value = Settings.Secure.getString(mSpyContext.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + final String value = Settings.Secure.getStringForUser(mSpyContext.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mSecureSettings.getRealUserHandle(UserHandle.USER_CURRENT)); assertThat(value).isEqualTo(""); } @@ -274,8 +275,9 @@ public class MenuViewLayerTest extends SysuiTestCase { ShortcutConstants.UserShortcutType.HARDWARE)).thenReturn(stubShortcutTargets); mMenuViewLayer.mDismissMenuAction.run(); - final String value = Settings.Secure.getString(mSpyContext.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + final String value = Settings.Secure.getStringForUser(mSpyContext.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + mSecureSettings.getRealUserHandle(UserHandle.USER_CURRENT)); assertThat(value).isEqualTo(TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString()); } @@ -445,9 +447,11 @@ public class MenuViewLayerTest extends SysuiTestCase { } private void setupEnabledAccessibilityServiceList() { - Settings.Secure.putString(mSpyContext.getContentResolver(), + Settings.Secure.putStringForUser(mSpyContext.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, - TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString()); + TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString(), + mSecureSettings.getRealUserHandle(UserHandle.USER_CURRENT) + ); final ResolveInfo resolveInfo = new ResolveInfo(); final ServiceInfo serviceInfo = new ServiceInfo(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java index 51f6cdb2cb89..7320bbff843e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java @@ -22,9 +22,9 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.settingslib.bluetooth.CachedBluetoothDevice; @@ -44,7 +44,7 @@ import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest public class HearingDevicesCheckerTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt index 982f033d05e5..99d36003dfef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/battery/AccessorizedBatteryDrawableTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.battery +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT @@ -24,8 +25,10 @@ import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class AccessorizedBatteryDrawableTest : SysuiTestCase() { @Test fun intrinsicSize_shieldFalse_isBatterySize() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java index 14eff2f2ef86..d940fc938c4b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java @@ -31,6 +31,7 @@ import android.content.ContentResolver; import android.os.Handler; import android.provider.Settings; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -44,10 +45,12 @@ import com.android.systemui.tuner.TunerService; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest +@RunWith(AndroidJUnit4.class) public class BatteryMeterViewControllerTest extends SysuiTestCase { @Mock private BatteryMeterView mBatteryMeterView; diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt index 39cb0476e429..cac0b664ab79 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatterySpecsTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.battery +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT @@ -24,8 +25,10 @@ import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class BatterySpecsTest : SysuiTestCase() { @Test fun getFullBatteryHeight_shieldFalse_returnsMainHeight() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardImageLoaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardImageLoaderTest.kt index 21516d4917b5..791f1f2e1f26 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardImageLoaderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardImageLoaderTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.clipboardoverlay import android.content.ContentResolver import android.content.Context import android.net.Uri +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.whenever @@ -29,6 +30,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Assert.assertNull import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.eq import org.mockito.Mock @@ -37,6 +39,7 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class ClipboardImageLoaderTest : SysuiTestCase() { @Mock private lateinit var mockContext: Context diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt index ac1f90cc6dda..b3f458821cba 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/TemperatureControlBehaviorTest.kt @@ -10,6 +10,7 @@ import android.service.controls.templates.TemperatureControlTemplate import android.service.controls.templates.ThumbnailTemplate import android.view.LayoutInflater import android.view.ViewGroup +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -20,10 +21,12 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class TemperatureControlBehaviorTest : SysuiTestCase() { @Mock lateinit var controlsMetricsLogger: ControlsMetricsLogger diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt index ef89752dd3d1..82ad30ecfbdd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/shared/FaceAuthReasonTest.kt @@ -16,13 +16,16 @@ package com.android.systemui.deviceentry.shared +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import junit.framework.Assert import kotlin.reflect.full.declaredMembers import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class FaceAuthReasonTest : SysuiTestCase() { @Test fun testApiReasonToUiEvent_forAllReasons_isNotNull() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt index dd741b4167e9..d79db5cc32eb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayMetricsRepositoryTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.display.data.repository import android.content.Context import android.util.DisplayMetrics import android.view.Display +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.LogBuffer @@ -33,9 +34,11 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class DisplayMetricsRepositoryTest : SysuiTestCase() { private lateinit var underTest: DisplayMetricsRepository diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt index 01868ae3e5da..1c327aff9a3d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt @@ -126,6 +126,7 @@ class DisplayRepositoryTest : SysuiTestCase() { // All subscribers are done, unregister should have been called. verify(displayManager).unregisterDisplayListener(any()) } + @Test fun onDisplayAdded_propagated() = testScope.runTest { @@ -457,6 +458,16 @@ class DisplayRepositoryTest : SysuiTestCase() { assertThat(defaultDisplayOff).isFalse() } + @Test + fun displayFlow_startsWithDefaultDisplayBeforeAnyEvent() = + testScope.runTest { + setDisplays(Display.DEFAULT_DISPLAY) + + val value by latestDisplayFlowValue() + + assertThat(value?.ids()).containsExactly(Display.DEFAULT_DISPLAY) + } + private fun Iterable<Display>.ids(): List<Int> = map { it.displayId } // Wrapper to capture the displayListener. diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java index a7d7b93c4044..419f7eda9d1f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import android.view.Display; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -33,10 +34,12 @@ import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import java.util.concurrent.Executor; @SmallTest +@RunWith(AndroidJUnit4.class) public class DozeScreenStatePreventingAdapterTest extends SysuiTestCase { private Executor mExecutor; diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java index 240d2d7bd35c..5a89710f6cf6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import android.view.Display; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -33,10 +34,12 @@ import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import java.util.concurrent.Executor; @SmallTest +@RunWith(AndroidJUnit4.class) public class DozeSuspendScreenStatePreventingAdapterTest extends SysuiTestCase { private Executor mExecutor; diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt index 840eb468b8c2..597629219634 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.dump +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.CoreStartable import com.android.systemui.Dumpable @@ -28,6 +29,7 @@ import com.android.systemui.util.mockito.eq import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.anyInt import org.mockito.Mockito.never @@ -39,6 +41,7 @@ import java.io.StringWriter import javax.inject.Provider @SmallTest +@RunWith(AndroidJUnit4::class) class DumpHandlerTest : SysuiTestCase() { private lateinit var dumpHandler: DumpHandler diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt index 6d5226f35e97..f331060db43e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.dump +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Dumpable import com.android.systemui.SysuiTestCase @@ -25,10 +26,12 @@ import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertThrows import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class DumpManagerTest : SysuiTestCase() { @Mock private lateinit var dumpable1: Dumpable diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt index 1d2afe4047c3..d09928b25084 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.dump +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase @@ -24,11 +25,13 @@ import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import java.io.PrintWriter import java.io.StringWriter @SmallTest +@RunWith(AndroidJUnit4::class) class DumpsysTableLoggerTest : SysuiTestCase() { private val logger = DumpsysTableLogger( TEST_SECTION_NAME, @@ -143,4 +146,4 @@ val TEST_DATA_VALID = List(TEST_DATA_LENGTH) { row -> List(TEST_COLUMNS.size) { col -> "data$col$row" } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt index 3b4888fc5b58..0cd2b9f03475 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.dump import android.content.BroadcastReceiver import android.content.IntentFilter import android.os.UserHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher @@ -30,6 +31,7 @@ import com.android.systemui.util.mockito.nullable import com.android.systemui.util.time.FakeSystemClock import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock @@ -40,6 +42,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class LogBufferFreezerTest : SysuiTestCase() { lateinit var freezer: LogBufferFreezer diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt index 3ff72028d5ca..ae6b337a3fa0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.dump +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpHandler.Companion.dump @@ -40,6 +41,7 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito @@ -48,6 +50,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class LogEulogizerTest : SysuiTestCase() { lateinit var eulogizer: LogBufferEulogizer diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt index 52c6e22cfcbb..9f238e64ce7e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.flags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any @@ -26,6 +27,7 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.verify @@ -35,6 +37,7 @@ import org.mockito.MockitoAnnotations * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()! */ @SmallTest +@RunWith(AndroidJUnit4::class) class ConditionalRestarterTest : SysuiTestCase() { private lateinit var restarter: ConditionalRestarter diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt index dbe59e66b955..a1fe0f082b56 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt @@ -23,6 +23,7 @@ import android.content.res.Resources import android.content.res.Resources.NotFoundException import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_SYSUI_TEAMFOOD import com.android.systemui.SysuiTestCase @@ -39,6 +40,7 @@ import java.util.function.Consumer import org.junit.Assert import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyString @@ -55,6 +57,7 @@ import org.mockito.MockitoAnnotations * the default. */ @SmallTest +@RunWith(AndroidJUnit4::class) class FeatureFlagsClassicDebugTest : SysuiTestCase() { private lateinit var mFeatureFlagsClassicDebug: FeatureFlagsClassicDebug diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt index 943e2124f6b4..ad8bedb22d3b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicReleaseTest.kt @@ -17,12 +17,14 @@ package com.android.systemui.flags import android.content.pm.PackageManager.NameNotFoundException import android.content.res.Resources +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertThrows import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.never @@ -34,6 +36,7 @@ import org.mockito.MockitoAnnotations * overriding, and should never return any value other than the one provided as the default. */ @SmallTest +@RunWith(AndroidJUnit4::class) class FeatureFlagsClassicReleaseTest : SysuiTestCase() { private lateinit var mFeatureFlagsClassicRelease: FeatureFlagsClassicRelease diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt index d500dd260267..dd56fa6be2d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagCommandTest.kt @@ -16,18 +16,21 @@ package com.android.systemui.flags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any import java.io.PrintWriter import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class FlagCommandTest : SysuiTestCase() { @Mock private lateinit var featureFlags: FeatureFlagsClassicDebug diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt index 5e87a6fd3fa3..593de37e0d6d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt @@ -19,6 +19,7 @@ import android.content.Context import android.database.ContentObserver import android.net.Uri import android.os.Handler +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any @@ -30,6 +31,7 @@ import java.util.function.Consumer import org.junit.Assert.assertThrows import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.times import org.mockito.Mockito.verify @@ -42,6 +44,7 @@ import org.mockito.MockitoAnnotations * overriding, and should never return any value other than the one provided as the default. */ @SmallTest +@RunWith(AndroidJUnit4::class) class FlagManagerTest : SysuiTestCase() { private lateinit var mFlagManager: FlagManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt index 755cc4615cc2..46b4c4b80481 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/NotOccludedConditionTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.flags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -30,6 +31,7 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @@ -39,6 +41,7 @@ import org.mockito.MockitoAnnotations */ @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class NotOccludedConditionTest : SysuiTestCase() { private lateinit var condition: NotOccludedCondition diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt index 0fdda082b9c6..0f727cb8505c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.flags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -26,6 +27,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.verify @@ -36,6 +38,7 @@ import org.mockito.MockitoAnnotations * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()! */ @SmallTest +@RunWith(AndroidJUnit4::class) class PluggedInConditionTest : SysuiTestCase() { private lateinit var condition: PluggedInCondition diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt index 3c965ce61aa2..1ab945adb54f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.flags import android.os.PowerManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.statusbar.StatusBarStateController @@ -27,6 +28,7 @@ import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString @@ -37,6 +39,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class RestartDozeListenerTest : SysuiTestCase() { lateinit var restartDozeListener: RestartDozeListener diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt index 0116e5326e47..df03882b649c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.flags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -27,6 +28,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @@ -35,6 +37,7 @@ import org.mockito.MockitoAnnotations * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()! */ @SmallTest +@RunWith(AndroidJUnit4::class) class ScreenIdleConditionTest : SysuiTestCase() { private lateinit var condition: ScreenIdleCondition diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt index 8a29217c33c5..008c68d0631a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt @@ -2,6 +2,7 @@ package com.android.systemui.fragments import android.app.Fragment import android.os.Looper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -9,8 +10,10 @@ import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class FragmentServiceTest : SysuiTestCase() { private val fragmentHostManagerFactory: FragmentHostManager.Factory = mock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java index 7f55d388c34f..dc019b6bb12f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java @@ -37,6 +37,7 @@ import android.widget.EditText; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.FlakyTest; import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -48,6 +49,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -55,6 +57,7 @@ import java.util.function.BooleanSupplier; @LargeTest @FlakyTest(bugId = 176891566) +@RunWith(AndroidJUnit4.class) public class GlobalActionsImeTest extends SysuiTestCase { @Rule diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt index 3a868685f4d9..2735d2f03e6a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/docking/ui/viewmodel/KeyboardDockingIndicationViewModelTest.kt @@ -20,6 +20,7 @@ import android.graphics.Rect import android.view.WindowInsets import android.view.WindowManager import android.view.WindowMetrics +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository @@ -33,14 +34,13 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.Mockito.spy import org.mockito.MockitoAnnotations import org.mockito.kotlin.doReturn import org.mockito.kotlin.whenever @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class KeyboardDockingIndicationViewModelTest : SysuiTestCase() { private val testScope = TestScope(StandardTestDispatcher()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt new file mode 100644 index 000000000000..c4eabd84e031 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.binder + +import android.platform.test.annotations.EnableFlags +import android.testing.TestableLooper +import android.view.View +import android.view.layoutInflater +import android.view.mockedLayoutInflater +import android.view.windowManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR +import com.android.systemui.SysuiTestCase +import com.android.systemui.bouncer.domain.interactor.givenCanShowAlternateBouncer +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.kosmos.testScope +import com.android.systemui.res.R +import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.whenever +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Mockito.any +import org.mockito.Mockito.anyBoolean +import org.mockito.Mockito.atLeastOnce +import org.mockito.Mockito.never +import org.mockito.Mockito.spy +import org.mockito.Mockito.verify +import org.mockito.kotlin.isNull + +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class AlternateBouncerViewBinderTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + + private val mockedAltBouncerView = + spy(kosmos.layoutInflater.inflate(R.layout.alternate_bouncer, null, false)) + + @Before + fun setup() { + whenever( + kosmos.mockedLayoutInflater.inflate( + eq(R.layout.alternate_bouncer), + isNull(), + anyBoolean() + ) + ) + .thenReturn(mockedAltBouncerView) + kosmos.alternateBouncerViewBinder.start() + } + + @Test + @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) + fun addViewToWindowManager() { + testScope.runTest { + kosmos.givenCanShowAlternateBouncer() + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + testScope, + ) + verify(kosmos.windowManager).addView(any(), any()) + } + } + + @Test + @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) + fun viewRemovedImmediatelyIfAlreadyAttachedToWindow() { + testScope.runTest { + kosmos.givenCanShowAlternateBouncer() + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + testScope, + ) + verify(kosmos.windowManager).addView(any(), any()) + whenever(mockedAltBouncerView.isAttachedToWindow).thenReturn(true) + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.LOCKSCREEN, + testScope, + ) + verify(kosmos.windowManager).removeView(any()) + } + } + + @Test + @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) + fun viewNotRemovedUntilAttachedToWindow() { + testScope.runTest { + kosmos.givenCanShowAlternateBouncer() + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.ALTERNATE_BOUNCER, + testScope, + ) + verify(kosmos.windowManager).addView(any(), any()) + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.ALTERNATE_BOUNCER, + to = KeyguardState.LOCKSCREEN, + testScope, + ) + + verify(kosmos.windowManager, never()).removeView(any()) + givenAltBouncerViewAttachedToWindow() + verify(kosmos.windowManager).removeView(any()) + } + } + + private fun givenAltBouncerViewAttachedToWindow() { + val attachStateChangeListenerCaptor = + ArgumentCaptor.forClass(View.OnAttachStateChangeListener::class.java) + verify(mockedAltBouncerView, atLeastOnce()) + .addOnAttachStateChangeListener(attachStateChangeListenerCaptor.capture()) + attachStateChangeListenerCaptor.allValues.onEach { + it.onViewAttachedToWindow(mockedAltBouncerView) + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt index 7787a7fa6af1..9055495b9f23 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.binder import android.testing.TestableLooper.RunWithLooper import android.view.RemoteAnimationTarget +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardViewController import com.android.systemui.SysuiTestCase @@ -34,6 +35,7 @@ import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.doAnswer @@ -42,6 +44,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWithLooper(setAsMainLooper = true) @kotlinx.coroutines.ExperimentalCoroutinesApi +@RunWith(AndroidJUnit4::class) class KeyguardSurfaceBehindParamsApplierTest : SysuiTestCase() { @get:Rule val animatorTestRule = AnimatorTestRule(this) @@ -155,4 +158,4 @@ class KeyguardSurfaceBehindParamsApplierTest : SysuiTestCase() { // Releasing the surface should immediately cancel animators. assertFalse(checkNotNull(isAnimatingSurface)) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt index 02c9debcbe1f..aa4a6d17123c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoSettingsFormatTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.log.echo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.core.LogLevel @@ -24,8 +25,10 @@ import com.android.systemui.log.echo.EchoOverrideType.BUFFER import com.android.systemui.log.echo.EchoOverrideType.TAG import kotlin.test.assertEquals import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class LogcatEchoSettingsFormatTest : SysuiTestCase() { private val format = LogcatEchoSettingFormat() diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt index 7967134eb150..a5f50af55a4b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/echo/LogcatEchoTrackerDebugTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.log.echo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.core.LogLevel.DEBUG @@ -39,11 +40,13 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class LogcatEchoTrackerDebugTest : SysuiTestCase() { private val dispatcher = StandardTestDispatcher() diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt index 1d182cfec49c..e55cb12bc0e8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.log.table +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX @@ -35,9 +36,11 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class LogDiffsForTableTest : SysuiTestCase() { private val testDispatcher = UnconfinedTestDispatcher() diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt index 43e430fd7fa2..8d608111744e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.log.table +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX @@ -23,8 +24,10 @@ import com.android.systemui.log.table.TableChange.Companion.MAX_STRING_LENGTH import com.google.common.truth.Truth.assertThat import junit.framework.Assert.assertTrue import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class TableChangeTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt index 8ba76437c725..8c62bc2e0207 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.log.table +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -26,9 +27,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import org.junit.Test +import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class TableLogBufferFactoryTest : SysuiTestCase() { private val dumpManager: DumpManager = mock() private val systemClock = FakeSystemClock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt index 5c9a0033cb72..ace562b93c2b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.log.table +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.LogcatEchoTracker @@ -35,9 +36,11 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class TableLogBufferTest : SysuiTestCase() { private lateinit var underTest: TableLogBuffer diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java index 544350c7e24d..1d4b0903b579 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataCombineLatestTest.java @@ -79,7 +79,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { USER_ID, true, APP, null, ARTIST, TITLE, null, new ArrayList<>(), new ArrayList<>(), null, PACKAGE, null, null, null, true, null, MediaData.PLAYBACK_LOCAL, false, KEY, false, false, false, 0L, 0L, - InstanceId.fakeInstanceId(-1), -1, false, null); + InstanceId.fakeInstanceId(-1), -1, false, null, -1, false); mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME, null, false); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt index 4da56b51e423..c974e0dde5e6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt @@ -740,11 +740,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) - val controlCommonModel = - MediaCommonModel.MediaControl( - MediaDataLoadingModel.Loaded(dataMain.instanceId), - true - ) + val mediaLoadingModel = MediaDataLoadingModel.Loaded(dataMain.instanceId) + var controlCommonModel = MediaCommonModel.MediaControl(mediaLoadingModel, true) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) repository.setOrderedMedia() assertThat(currentMedia).containsExactly(controlCommonModel) @@ -758,7 +755,15 @@ class MediaDataFilterImplTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should treat the media as active instead - val dataCurrentAndActive = dataCurrent.copy(active = true) + val dataCurrentAndActive = + dataMain.copy(active = true, lastActive = clock.elapsedRealtime()) + controlCommonModel = + controlCommonModel.copy( + mediaLoadingModel.copy( + receivedSmartspaceCardLatency = 100, + isSsReactivated = true + ) + ) assertThat(currentMedia).containsExactly(controlCommonModel) assertThat( hasActiveMediaOrRecommendation( @@ -800,11 +805,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { val currentMedia by collectLastValue(repository.currentMedia) // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) - val controlCommonModel = - MediaCommonModel.MediaControl( - MediaDataLoadingModel.Loaded(dataMain.instanceId), - true - ) + val mediaLoadingModel = MediaDataLoadingModel.Loaded(dataMain.instanceId) + var controlCommonModel = MediaCommonModel.MediaControl(mediaLoadingModel, true) val recsCommonModel = MediaCommonModel.MediaRecommendations( SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) @@ -824,7 +826,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should treat the media as active instead - val dataCurrentAndActive = dataCurrent.copy(active = true) + val dataCurrentAndActive = + dataMain.copy(active = true, lastActive = clock.elapsedRealtime()) verify(listener) .onMediaDataLoaded( eq(KEY), @@ -849,6 +852,13 @@ class MediaDataFilterImplTest : SysuiTestCase() { ) .isTrue() // Smartspace update should also be propagated but not prioritized. + controlCommonModel = + controlCommonModel.copy( + mediaLoadingModel.copy( + receivedSmartspaceCardLatency = 100, + isSsReactivated = true + ) + ) assertThat(currentMedia).containsExactly(controlCommonModel, recsCommonModel) verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) @@ -909,7 +919,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { runCurrent() mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - val dataCurrentAndActive = dataCurrent.copy(active = true) + val dataCurrentAndActive = + dataMain.copy(active = true, lastActive = clock.elapsedRealtime()) verify(listener) .onMediaDataLoaded( eq(KEY), @@ -1063,11 +1074,8 @@ class MediaDataFilterImplTest : SysuiTestCase() { MediaCommonModel.MediaRecommendations( SmartspaceMediaLoadingModel.Loaded(SMARTSPACE_KEY) ) - val controlCommonModel = - MediaCommonModel.MediaControl( - MediaDataLoadingModel.Loaded(dataMain.instanceId), - true - ) + val mediaLoadingModel = MediaDataLoadingModel.Loaded(dataMain.instanceId) + var controlCommonModel = MediaCommonModel.MediaControl(mediaLoadingModel, true) // WHEN we have media that was recently played, but not currently active val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) @@ -1086,7 +1094,15 @@ class MediaDataFilterImplTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should treat the media as active instead - val dataCurrentAndActive = dataCurrent.copy(active = true) + val dataCurrentAndActive = + dataMain.copy(active = true, lastActive = clock.elapsedRealtime()) + controlCommonModel = + controlCommonModel.copy( + mediaLoadingModel.copy( + receivedSmartspaceCardLatency = 100, + isSsReactivated = true + ) + ) verify(listener) .onMediaDataLoaded( eq(KEY), diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt index 473dc4712c25..868145d1403a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/shared/SmartspaceMediaDataTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.media.controls.shared import android.app.smartspace.SmartspaceAction import android.graphics.drawable.Icon +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase @@ -26,8 +27,10 @@ import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.res.R import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class SmartspaceMediaDataTest : SysuiTestCase() { private val icon: Icon = Icon.createWithResource(context, R.drawable.ic_media_play) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt index 2a8967edf13d..64acc5965d45 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt @@ -24,6 +24,7 @@ import android.media.AudioDeviceAttributes import android.media.AudioDeviceInfo import android.media.AudioManager import android.media.AudioManager.MuteAwaitConnectionCallback.EVENT_CONNECTION +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.media.DeviceIconUtil import com.android.settingslib.media.LocalMediaManager @@ -35,6 +36,7 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.never @@ -45,6 +47,7 @@ import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { private lateinit var muteAwaitConnectionManager: MediaMuteAwaitConnectionManager @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt index d9453d67848f..b9aa02967acc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt @@ -2,6 +2,7 @@ package com.android.systemui.media.nearby import android.media.INearbyMediaDevicesProvider import android.media.INearbyMediaDevicesUpdateCallback +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import android.media.NearbyDevice @@ -10,6 +11,7 @@ import com.android.systemui.statusbar.CommandQueue import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.anyInt @@ -20,6 +22,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class NearbyMediaDevicesManagerTest : SysuiTestCase() { private lateinit var manager: NearbyMediaDevicesManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt index d82819397f08..77807bf7915b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.media.taptotransfer import android.app.StatusBarManager import android.content.Context import android.media.MediaRoute2Info +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.media.taptotransfer.receiver.ChipStateReceiver @@ -35,6 +36,7 @@ import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -43,6 +45,7 @@ import java.io.StringWriter import java.util.concurrent.Executor @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttCommandLineHelperTest : SysuiTestCase() { private val inlineExecutor = Executor { command -> command.run() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt index b322bb7d6b46..ab5c893644b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.media.taptotransfer.common +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -27,9 +28,11 @@ import java.io.PrintWriter import java.io.StringWriter import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.mock @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttLoggerUtilsTest : SysuiTestCase() { private lateinit var buffer: LogBuffer diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt index 5c6d9131e1f0..02123ba3ba02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.media.taptotransfer.common import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.graphics.drawable.Drawable +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -30,12 +31,14 @@ import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttUtilsTest : SysuiTestCase() { private lateinit var appIconFromPackageName: Drawable diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt index 64f3fd304ca6..cee71b5266a0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.media.taptotransfer.receiver +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -27,9 +28,11 @@ import java.io.PrintWriter import java.io.StringWriter import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.mock @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttReceiverLoggerTest : SysuiTestCase() { private lateinit var buffer: LogBuffer diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt index f55771362cb2..352443a99acc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverUiEventLoggerTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.media.taptotransfer.receiver +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.testing.UiEventLoggerFake @@ -7,8 +8,10 @@ import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttReceiverUiEventLoggerTest : SysuiTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: MediaTttReceiverUiEventLogger diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt index ee3704c1e9e9..af8b3edf38c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.media.taptotransfer.sender +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase @@ -28,9 +29,11 @@ import java.io.PrintWriter import java.io.StringWriter import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.mock @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttSenderLoggerTest : SysuiTestCase() { private lateinit var buffer: LogBuffer diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt index bf26a2f53b4c..30b578a77e96 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.media.taptotransfer.sender +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.testing.UiEventLoggerFake @@ -7,8 +8,10 @@ import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class MediaTttSenderUiEventLoggerTest : SysuiTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: MediaTttSenderUiEventLogger diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt index f4c5ccfc8388..b337ccfda772 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewControllerTest.kt @@ -22,6 +22,7 @@ import android.graphics.Rect import android.os.Bundle import android.view.View import android.view.ViewGroup +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_RECENTS_SPLIT_SCREEN @@ -36,6 +37,7 @@ import com.google.common.truth.Truth.assertThat import java.util.Optional import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito.any @@ -43,6 +45,7 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.verify @SmallTest +@RunWith(AndroidJUnit4::class) class MediaProjectionRecentsViewControllerTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt index 9630ee32d456..55e52b780488 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProviderTest.kt @@ -27,6 +27,7 @@ import android.view.WindowManager import android.view.WindowMetrics import androidx.core.view.WindowInsetsCompat.Type import androidx.lifecycle.LifecycleOwner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener @@ -38,8 +39,10 @@ import com.google.common.truth.Truth.assertThat import kotlin.math.min import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class TaskPreviewSizeProviderTest : SysuiTestCase() { private val lifecycleOwner = mock<LifecycleOwner>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt index fe18454ec06c..cc722aa40a1e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProviderImplTest.kt @@ -5,14 +5,17 @@ import android.graphics.Rect import android.view.WindowManager import android.view.WindowMetrics import androidx.core.view.WindowInsetsCompat +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class WindowMetricsProviderImplTest : SysuiTestCase() { private val windowManager = mock<WindowManager>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt index bba275e993fd..5ed8a11e862f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt @@ -1,6 +1,7 @@ package com.android.systemui.navigationbar import android.app.ActivityManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -19,6 +20,7 @@ import com.android.wm.shell.pip.Pip import java.util.Optional import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers import org.mockito.Mock import org.mockito.Mockito.any @@ -30,6 +32,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class TaskbarDelegateTest : SysuiTestCase() { val DISPLAY_ID = 0; val MODE_GESTURE = 0; @@ -108,4 +111,4 @@ class TaskbarDelegateTest : SysuiTestCase() { ArgumentMatchers.eq(true) ) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDisableFlagsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDisableFlagsLoggerTest.kt index 9e5d3bdb179c..cc3e27c71564 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDisableFlagsLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDisableFlagsLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.qs +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -26,9 +27,11 @@ import com.google.common.truth.Truth.assertThat import java.io.PrintWriter import java.io.StringWriter import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.mock @SmallTest +@RunWith(AndroidJUnit4::class) class QSDisableFlagsLoggerTest : SysuiTestCase() { private val buffer = diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/data/QSPreferencesRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/data/QSPreferencesRepositoryTest.kt index b0aa6ddf44ce..7c95dfe61a54 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/data/QSPreferencesRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/data/QSPreferencesRepositoryTest.kt @@ -19,7 +19,7 @@ package com.android.systemui.qs.panels.data import android.content.Context import android.content.SharedPreferences import android.content.pm.UserInfo -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -36,7 +36,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class QSPreferencesRepositoryTest : SysuiTestCase() { private val kosmos = testKosmos() private val underTest = with(kosmos) { qsPreferencesRepository } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorTest.kt index 9b08432e290f..7ad904e9b436 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/domain/interactor/IconLabelVisibilityInteractorTest.kt @@ -17,7 +17,7 @@ package com.android.systemui.qs.panels.domain.interactor import android.content.pm.UserInfo -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -34,7 +34,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class IconLabelVisibilityInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val underTest = with(kosmos) { iconLabelVisibilityInteractor } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt index 06833213671d..79cb51ab3e10 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt @@ -20,6 +20,7 @@ import android.os.Handler import android.service.quicksettings.Tile import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger import com.android.systemui.res.R @@ -54,12 +55,14 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWithLooper(setAsMainLooper = true) +@RunWith(AndroidJUnit4::class) class InternetTileNewImplTest : SysuiTestCase() { lateinit var underTest: InternetTileNewImpl diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java index 0d7a9e4d2430..f866f740345e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java @@ -35,8 +35,8 @@ import android.content.Intent; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; @@ -60,7 +60,7 @@ import org.mockito.MockitoAnnotations; import java.io.IOException; import java.util.concurrent.Executor; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @SmallTest public class RecordingServiceTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt index 943245150e64..db607fd56643 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegateTest.kt @@ -18,10 +18,10 @@ package com.android.systemui.screenrecord import android.content.Intent import android.os.UserHandle -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View import android.widget.Spinner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Dependency import com.android.systemui.SysuiTestCase @@ -55,7 +55,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class ScreenRecordPermissionDialogDelegateTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt index 61ea437f10dd..aceea909e595 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.screenrecord.data.repository +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -28,6 +29,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.mock import org.mockito.kotlin.verify @@ -35,6 +37,7 @@ import org.mockito.kotlin.whenever @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class ScreenRecordRepositoryTest : SysuiTestCase() { private val kosmos = Kosmos() private val testScope = kosmos.testScope diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentCreatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentCreatorTest.kt index 36639d4b7ca4..67eaf7b9d19e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentCreatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentCreatorTest.kt @@ -20,6 +20,7 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.truth.content.IntentSubject.assertThat as assertThatIntent import androidx.test.filters.SmallTest import com.android.systemui.res.R @@ -29,9 +30,11 @@ import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.`when` as whenever @SmallTest +@RunWith(AndroidJUnit4::class) class ActionIntentCreatorTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt index 5cd3f66d2cbf..612d646bb7d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionIntentExecutorTest.kt @@ -17,9 +17,9 @@ package com.android.systemui.screenshot import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 import android.os.Process.myUserHandle import android.platform.test.annotations.EnableFlags -import android.testing.AndroidTestingRunner import android.testing.TestableContext import com.android.systemui.Flags import com.android.systemui.SysuiTestCase @@ -36,7 +36,7 @@ import org.junit.runner.RunWith import org.mockito.kotlin.mock import org.mockito.kotlin.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class ActionIntentExecutorTest : SysuiTestCase() { private val scheduler = TestCoroutineScheduler() diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt index 6f5c56eb9148..148a2e56f2a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt @@ -24,6 +24,7 @@ import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase +import com.android.systemui.screenshot.ui.viewmodel.PreviewAction import com.google.common.truth.Truth.assertThat import java.util.UUID import kotlin.test.Test @@ -60,9 +61,9 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() { fun previewActionAccessed_beforeScreenshotCompleted_doesNothing() { actionsProvider = createActionsProvider() - val previewActionCaptor = argumentCaptor<() -> Unit>() + val previewActionCaptor = argumentCaptor<PreviewAction>() verify(actionsCallback).providePreviewAction(previewActionCaptor.capture()) - previewActionCaptor.firstValue.invoke() + previewActionCaptor.firstValue.onClick.invoke() verifyNoMoreInteractions(actionExecutor) } @@ -102,14 +103,14 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() { fun actionAccessed_whilePending_launchesMostRecentAction() = runTest { actionsProvider = createActionsProvider() - val previewActionCaptor = argumentCaptor<() -> Unit>() + val previewActionCaptor = argumentCaptor<PreviewAction>() verify(actionsCallback).providePreviewAction(previewActionCaptor.capture()) val actionButtonCaptor = argumentCaptor<() -> Unit>() verify(actionsCallback, times(2)) .provideActionButton(any(), any(), actionButtonCaptor.capture()) actionButtonCaptor.firstValue.invoke() - previewActionCaptor.firstValue.invoke() + previewActionCaptor.firstValue.onClick.invoke() actionButtonCaptor.secondValue.invoke() actionsProvider.setCompletedScreenshot(validResult) diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java index c6ce51a28dd3..ba330f7b6ec0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DraggableConstraintLayoutTest.java @@ -20,10 +20,10 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.MotionEvent; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -35,7 +35,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) public class DraggableConstraintLayoutTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt index 924b872546c7..b31d21e7f8b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt @@ -4,12 +4,12 @@ import android.graphics.drawable.Drawable import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags -import android.testing.AndroidTestingRunner import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.Guideline +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.screenshot.message.LabeledIcon @@ -31,7 +31,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class MessageContainerControllerTest : SysuiTestCase() { lateinit var messageContainer: MessageContainerController diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt index 2a3c31aee6e7..29e7a8a4ca85 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotActionsControllerTest.kt @@ -16,9 +16,10 @@ package com.android.systemui.screenshot -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.screenshot.ui.viewmodel.PreviewAction import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel import java.util.UUID import kotlin.test.Test @@ -29,13 +30,13 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class ScreenshotActionsControllerTest : SysuiTestCase() { private val screenshotData = mock<ScreenshotData>() private val actionExecutor = mock<ActionExecutor>() private val viewModel = mock<ScreenshotViewModel>() - private val onClick = mock<() -> Unit>() + private val previewAction = PreviewAction("description", onClick = {}) private lateinit var actionsController: ScreenshotActionsController private lateinit var fakeActionsProvider1: FakeActionsProvider @@ -43,6 +44,7 @@ class ScreenshotActionsControllerTest : SysuiTestCase() { private val actionsProviderFactory = object : ScreenshotActionsProvider.Factory { var isFirstCall = true + override fun create( requestId: UUID, request: ScreenshotData, @@ -69,16 +71,16 @@ class ScreenshotActionsControllerTest : SysuiTestCase() { @Test fun setPreview_onCurrentScreenshot_updatesViewModel() { actionsController.setCurrentScreenshot(screenshotData) - fakeActionsProvider1.callPreview(onClick) + fakeActionsProvider1.callPreview(previewAction) - verify(viewModel).setPreviewAction(onClick) + verify(viewModel).setPreviewAction(previewAction) } @Test fun setPreview_onNonCurrentScreenshot_doesNotUpdateViewModel() { actionsController.setCurrentScreenshot(screenshotData) actionsController.setCurrentScreenshot(screenshotData) - fakeActionsProvider1.callPreview(onClick) + fakeActionsProvider1.callPreview(previewAction) verify(viewModel, never()).setPreviewAction(any()) } @@ -87,8 +89,8 @@ class ScreenshotActionsControllerTest : SysuiTestCase() { private val actionsCallback: ScreenshotActionsController.ActionsCallback ) : ScreenshotActionsProvider { - fun callPreview(onClick: () -> Unit) { - actionsCallback.providePreviewAction(onClick) + fun callPreview(previewAction: PreviewAction) { + actionsCallback.providePreviewAction(previewAction) } override fun onScrollChipReady(onClick: Runnable) {} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt index f8a8a6830669..3ed09770b189 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.screenshot import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 import android.graphics.Insets import android.graphics.Rect import android.os.UserHandle @@ -25,7 +26,9 @@ import android.view.WindowManager import com.android.internal.util.ScreenshotRequest import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith +@RunWith(AndroidJUnit4::class) class ScreenshotDataTest { private val type = WindowManager.TAKE_SCREENSHOT_FULLSCREEN private val source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java index 2a9aca7f5a35..89c13b0468f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java @@ -34,8 +34,8 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Handler; import android.os.UserHandle; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -50,7 +50,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) /** * Tests for exception handling and bitmap configuration in adding smart actions to Screenshot * Notification. diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt index 92c240404b24..5987e74e02ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotSoundControllerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.screenshot import android.media.MediaPlayer +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.mock @@ -29,11 +30,13 @@ import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.never import org.mockito.Mockito.verify @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class ScreenshotSoundControllerTest : SysuiTestCase() { private val soundProvider = mock<ScreenshotSoundProvider>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java index 83c949793447..471fdc0b8fde 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java @@ -28,8 +28,8 @@ import static org.mockito.Mockito.when; import android.app.PendingIntent; import android.content.Intent; import android.os.Bundle; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -40,7 +40,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @SmallTest public class SmartActionsReceiverTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt index dd6ba909d579..ec5589e9a57b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt @@ -14,6 +14,7 @@ import android.view.Display.TYPE_VIRTUAL import android.view.Display.TYPE_WIFI import android.view.WindowManager import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake import com.android.internal.util.ScreenshotRequest @@ -42,7 +43,7 @@ import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class TakeScreenshotExecutorTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java index ebdc49f75558..7d2d7c452426 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java @@ -30,12 +30,12 @@ import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.os.UserManager; -import android.testing.AndroidTestingRunner; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -54,7 +54,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class WorkProfileMessageControllerTest extends SysuiTestCase { private static final String FILES_APP_COMPONENT = "com.android.test/.FilesComponent"; private static final String FILES_APP_LABEL = "Custom Files App"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java index 68a689321219..2981590a3037 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java @@ -17,6 +17,7 @@ package com.android.systemui.screenshot.appclips; import static android.app.Activity.RESULT_OK; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED; @@ -25,30 +26,45 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityTaskManager.RootTaskInfo; +import android.app.IActivityTaskManager; +import android.app.assist.AssistContent; +import android.content.ComponentName; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.ApplicationInfoFlags; +import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Process; +import android.os.RemoteException; import android.os.ResultReceiver; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.testing.AndroidTestingRunner; import android.view.Display; +import android.view.View; import android.widget.ImageView; +import android.widget.TextView; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.intercepting.SingleActivityFactory; import com.android.internal.logging.UiEventLogger; +import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.res.R; +import com.android.systemui.screenshot.AssistContentRequester; import com.android.systemui.screenshot.ImageExporter; import com.android.systemui.settings.UserTracker; @@ -60,9 +76,11 @@ import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.List; import java.util.UUID; import java.util.concurrent.Executor; import java.util.function.BiConsumer; @@ -75,14 +93,27 @@ public final class AppClipsActivityTest extends SysuiTestCase { private static final Bitmap TEST_BITMAP = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); private static final String TEST_URI_STRING = "www.test-uri.com"; private static final Uri TEST_URI = Uri.parse(TEST_URI_STRING); - private static final BiConsumer<Integer, Bundle> FAKE_CONSUMER = (unUsed1, unUsed2) -> {}; + private static final BiConsumer<Integer, Bundle> FAKE_CONSUMER = (unUsed1, unUsed2) -> { + }; private static final String TEST_CALLING_PACKAGE = "test-calling-package"; + private static final int BACKLINKS_TASK_ID = 42; + private static final String BACKLINKS_TASK_APP_NAME = "Backlinks app"; + private static final String BACKLINKS_TASK_PACKAGE_NAME = "backlinksTaskPackageName"; + private static final RootTaskInfo TASK_THAT_SUPPORTS_BACKLINKS = + createTaskInfoForBacklinksTask(); + + private static final AssistContent ASSIST_CONTENT_FOR_BACKLINKS_TASK = + createAssistContentForBacklinksTask(); @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; @Mock private ImageExporter mImageExporter; @Mock + private IActivityTaskManager mAtmService; + @Mock + private AssistContentRequester mAssistContentRequester; + @Mock private PackageManager mPackageManager; @Mock private UserTracker mUserTracker; @@ -98,9 +129,10 @@ public final class AppClipsActivityTest extends SysuiTestCase { protected AppClipsActivityTestable create(Intent unUsed) { return new AppClipsActivityTestable( new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper, - mImageExporter, getContext().getMainExecutor(), - directExecutor()), mPackageManager, mUserTracker, - mUiEventLogger); + mImageExporter, mAtmService, mAssistContentRequester, + mPackageManager, getContext().getMainExecutor(), + directExecutor()), + mPackageManager, mUserTracker, mUiEventLogger); } }; @@ -118,7 +150,7 @@ public final class AppClipsActivityTest extends SysuiTestCase { when(mPackageManager.getApplicationInfoAsUser(eq(TEST_CALLING_PACKAGE), any(ApplicationInfoFlags.class), eq(TEST_USER_ID))).thenReturn(applicationInfo); - when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(TEST_BITMAP); + when(mAppClipsCrossProcessHelper.takeScreenshot(anyInt())).thenReturn(TEST_BITMAP); ImageExporter.Result result = new ImageExporter.Result(); result.uri = TEST_URI; when(mImageExporter.export(any(Executor.class), any(UUID.class), any(Bitmap.class), @@ -132,10 +164,13 @@ public final class AppClipsActivityTest extends SysuiTestCase { } @Test + @DisableFlags(Flags.FLAG_APP_CLIPS_BACKLINKS) public void appClipsLaunched_screenshotDisplayed() { launchActivity(); assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull(); + assertThat(mActivity.findViewById(R.id.backlinks_data).getVisibility()) + .isEqualTo(View.GONE); } @Test @@ -176,6 +211,32 @@ public final class AppClipsActivityTest extends SysuiTestCase { verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_CANCELLED, TEST_UID, TEST_CALLING_PACKAGE); } + @Test + @EnableFlags(Flags.FLAG_APP_CLIPS_BACKLINKS) + public void appClipsLaunched_backlinks_displayed() throws RemoteException { + // Set up mocking to verify backlinks view is displayed on screen. + ArgumentCaptor<Integer> displayIdCaptor = ArgumentCaptor.forClass(Integer.class); + when(mAtmService.getAllRootTaskInfosOnDisplay(displayIdCaptor.capture())) + .thenReturn(List.of(TASK_THAT_SUPPORTS_BACKLINKS)); + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(ASSIST_CONTENT_FOR_BACKLINKS_TASK); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + when(mPackageManager + .resolveActivity(any(Intent.class), anyInt())) + .thenReturn(createBacklinksTaskResolveInfo()); + + launchActivity(); + waitForIdleSync(); + + assertThat(displayIdCaptor.getValue()).isEqualTo(mActivity.getDisplayId()); + TextView backlinksData = mActivity.findViewById(R.id.backlinks_data); + assertThat(backlinksData.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(backlinksData.getText().toString()).isEqualTo( + mActivity.getString(R.string.backlinks_string, BACKLINKS_TASK_APP_NAME)); + } + private void launchActivity() { launchActivity(createResultReceiver(FAKE_CONSUMER)); } @@ -203,7 +264,7 @@ public final class AppClipsActivityTest extends SysuiTestCase { testReceiver.writeToParcel(parcel, 0); parcel.setDataPosition(0); - testReceiver = ResultReceiver.CREATOR.createFromParcel(parcel); + testReceiver = ResultReceiver.CREATOR.createFromParcel(parcel); parcel.recycle(); return testReceiver; } @@ -212,6 +273,37 @@ public final class AppClipsActivityTest extends SysuiTestCase { mContext.getMainExecutor().execute(runnable); } + private static ResolveInfo createBacklinksTaskResolveInfo() { + ActivityInfo activityInfo = new ActivityInfo(); + activityInfo.applicationInfo = new ApplicationInfo(); + activityInfo.name = BACKLINKS_TASK_APP_NAME; + activityInfo.packageName = BACKLINKS_TASK_PACKAGE_NAME; + activityInfo.applicationInfo.packageName = BACKLINKS_TASK_PACKAGE_NAME; + ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = activityInfo; + return resolveInfo; + } + + private static RootTaskInfo createTaskInfoForBacklinksTask() { + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.taskId = BACKLINKS_TASK_ID; + taskInfo.isVisible = true; + taskInfo.isRunning = true; + taskInfo.numActivities = 1; + taskInfo.topActivity = new ComponentName(BACKLINKS_TASK_PACKAGE_NAME, "backlinksClass"); + taskInfo.topActivityInfo = createBacklinksTaskResolveInfo().activityInfo; + taskInfo.baseIntent = new Intent().setComponent(taskInfo.topActivity); + taskInfo.childTaskIds = new int[]{BACKLINKS_TASK_ID + 1}; + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); + return taskInfo; + } + + private static AssistContent createAssistContentForBacklinksTask() { + AssistContent content = new AssistContent(); + content.setWebUri(Uri.parse("https://developers.android.com")); + return content; + } + public static class AppClipsActivityTestable extends AppClipsActivity { public AppClipsActivityTestable(AppClipsViewModel.Factory viewModelFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java index ad0797c88f62..dcb75d1e187b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java @@ -16,28 +16,51 @@ package com.android.systemui.screenshot.appclips; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.content.ClipDescription.MIMETYPE_TEXT_INTENT; +import static android.content.ClipDescription.MIMETYPE_TEXT_URILIST; +import static android.content.Intent.ACTION_MAIN; +import static android.content.Intent.ACTION_VIEW; import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED; +import static android.content.Intent.CATEGORY_LAUNCHER; +import static android.view.Display.DEFAULT_DISPLAY; import static com.google.common.truth.Truth.assertThat; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityTaskManager.RootTaskInfo; +import android.app.IActivityTaskManager; +import android.app.assist.AssistContent; +import android.content.ClipData; +import android.content.ClipDescription; +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.net.Uri; import android.os.Process; +import android.os.RemoteException; import android.os.UserHandle; -import android.view.Display; import androidx.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; +import com.android.systemui.screenshot.AssistContentRequester; import com.android.systemui.screenshot.ImageExporter; import com.google.common.util.concurrent.Futures; @@ -45,9 +68,13 @@ import com.google.common.util.concurrent.Futures; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Collections; +import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -60,27 +87,44 @@ public final class AppClipsViewModelTest extends SysuiTestCase { private static final Rect FAKE_RECT = new Rect(); private static final Uri FAKE_URI = Uri.parse("www.test-uri.com"); private static final UserHandle USER_HANDLE = Process.myUserHandle(); + private static final int BACKLINKS_TASK_ID = 42; + private static final String BACKLINKS_TASK_APP_NAME = "Ultimate question app"; + private static final String BACKLINKS_TASK_PACKAGE_NAME = "backlinksTaskPackageName"; + private static final AssistContent EMPTY_ASSIST_CONTENT = new AssistContent(); @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; @Mock private ImageExporter mImageExporter; + @Mock private IActivityTaskManager mAtmService; + @Mock private AssistContentRequester mAssistContentRequester; + @Mock + private PackageManager mPackageManager; + private ArgumentCaptor<Intent> mPackageManagerIntentCaptor; private AppClipsViewModel mViewModel; @Before - public void setUp() { + public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); + mPackageManagerIntentCaptor = ArgumentCaptor.forClass(Intent.class); + + // Set up mocking for backlinks. + when(mAtmService.getAllRootTaskInfosOnDisplay(DEFAULT_DISPLAY)) + .thenReturn(List.of(createTaskInfoForBacklinksTask())); + when(mPackageManager.resolveActivity(mPackageManagerIntentCaptor.capture(), anyInt())) + .thenReturn(createBacklinksTaskResolveInfo()); mViewModel = new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper, mImageExporter, + mAtmService, mAssistContentRequester, mPackageManager, getContext().getMainExecutor(), directExecutor()).create(AppClipsViewModel.class); } @Test public void performScreenshot_fails_shouldUpdateErrorWithFailed() { - when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(null); + when(mAppClipsCrossProcessHelper.takeScreenshot(anyInt())).thenReturn(null); - mViewModel.performScreenshot(); + mViewModel.performScreenshot(DEFAULT_DISPLAY); waitForIdleSync(); - verify(mAppClipsCrossProcessHelper).takeScreenshot(); + verify(mAppClipsCrossProcessHelper).takeScreenshot(DEFAULT_DISPLAY); assertThat(mViewModel.getErrorLiveData().getValue()) .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED); assertThat(mViewModel.getResultLiveData().getValue()).isNull(); @@ -88,12 +132,12 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void performScreenshot_succeeds_shouldUpdateScreenshotWithBitmap() { - when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(FAKE_BITMAP); + when(mAppClipsCrossProcessHelper.takeScreenshot(DEFAULT_DISPLAY)).thenReturn(FAKE_BITMAP); - mViewModel.performScreenshot(); + mViewModel.performScreenshot(DEFAULT_DISPLAY); waitForIdleSync(); - verify(mAppClipsCrossProcessHelper).takeScreenshot(); + verify(mAppClipsCrossProcessHelper).takeScreenshot(DEFAULT_DISPLAY); assertThat(mViewModel.getErrorLiveData().getValue()).isNull(); assertThat(mViewModel.getScreenshot().getValue()).isEqualTo(FAKE_BITMAP); } @@ -101,7 +145,7 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void saveScreenshot_throwsError_shouldUpdateErrorWithFailed() { when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), eq(USER_HANDLE), - eq(Display.DEFAULT_DISPLAY))).thenReturn( + eq(DEFAULT_DISPLAY))).thenReturn( Futures.immediateFailedFuture(new ExecutionException(new Throwable()))); mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT, USER_HANDLE); @@ -115,7 +159,7 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void saveScreenshot_failsSilently_shouldUpdateErrorWithFailed() { when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), eq(USER_HANDLE), - eq(Display.DEFAULT_DISPLAY))).thenReturn( + eq(DEFAULT_DISPLAY))).thenReturn( Futures.immediateFuture(new ImageExporter.Result())); mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT, USER_HANDLE); @@ -131,7 +175,7 @@ public final class AppClipsViewModelTest extends SysuiTestCase { ImageExporter.Result result = new ImageExporter.Result(); result.uri = FAKE_URI; when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), eq(USER_HANDLE), - eq(Display.DEFAULT_DISPLAY))).thenReturn(Futures.immediateFuture(result)); + eq(DEFAULT_DISPLAY))).thenReturn(Futures.immediateFuture(result)); mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT, USER_HANDLE); waitForIdleSync(); @@ -139,4 +183,198 @@ public final class AppClipsViewModelTest extends SysuiTestCase { assertThat(mViewModel.getErrorLiveData().getValue()).isNull(); assertThat(mViewModel.getResultLiveData().getValue()).isEqualTo(FAKE_URI); } + + @Test + public void triggerBacklinks_shouldUpdateBacklinks_withUri() { + Uri expectedUri = Uri.parse("https://developers.android.com"); + AssistContent contentWithUri = new AssistContent(); + contentWithUri.setWebUri(expectedUri); + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(contentWithUri); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + Intent queriedIntent = mPackageManagerIntentCaptor.getValue(); + assertThat(queriedIntent.getData()).isEqualTo(expectedUri); + assertThat(queriedIntent.getAction()).isEqualTo(ACTION_VIEW); + + ClipData result = mViewModel.getBacklinksLiveData().getValue(); + ClipDescription resultDescription = result.getDescription(); + assertThat(resultDescription.getLabel().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME); + assertThat(resultDescription.getMimeType(0)).isEqualTo(MIMETYPE_TEXT_URILIST); + assertThat(result.getItemCount()).isEqualTo(1); + assertThat(result.getItemAt(0).getUri()).isEqualTo(expectedUri); + } + + @Test + public void triggerBacklinks_withNonResolvableUri_usesMainLauncherIntent() { + Uri expectedUri = Uri.parse("https://developers.android.com"); + AssistContent contentWithUri = new AssistContent(); + contentWithUri.setWebUri(expectedUri); + resetPackageManagerMockingForUsingFallbackBacklinks(); + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(contentWithUri); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + verifyMainLauncherBacklinksIntent(); + } + + @Test + public void triggerBacklinks_shouldUpdateBacklinks_withAppProvidedIntent() { + Intent expectedIntent = new Intent().setPackage(BACKLINKS_TASK_PACKAGE_NAME); + AssistContent contentWithAppProvidedIntent = new AssistContent(); + contentWithAppProvidedIntent.setIntent(expectedIntent); + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(contentWithAppProvidedIntent); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + Intent queriedIntent = mPackageManagerIntentCaptor.getValue(); + assertThat(queriedIntent.getPackage()).isEqualTo(expectedIntent.getPackage()); + + ClipData result = mViewModel.getBacklinksLiveData().getValue(); + ClipDescription resultDescription = result.getDescription(); + assertThat(resultDescription.getLabel().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME); + assertThat(resultDescription.getMimeType(0)).isEqualTo(MIMETYPE_TEXT_INTENT); + assertThat(result.getItemCount()).isEqualTo(1); + assertThat(result.getItemAt(0).getIntent()).isEqualTo(expectedIntent); + } + + @Test + public void triggerBacklinks_withNonResolvableAppProvidedIntent_usesMainLauncherIntent() { + Intent expectedIntent = new Intent().setPackage(BACKLINKS_TASK_PACKAGE_NAME); + AssistContent contentWithAppProvidedIntent = new AssistContent(); + contentWithAppProvidedIntent.setIntent(expectedIntent); + resetPackageManagerMockingForUsingFallbackBacklinks(); + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(contentWithAppProvidedIntent); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + verifyMainLauncherBacklinksIntent(); + } + + @Test + public void triggerBacklinks_shouldUpdateBacklinks_withMainLauncherIntent() { + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(EMPTY_ASSIST_CONTENT); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + Intent queriedIntent = mPackageManagerIntentCaptor.getValue(); + assertThat(queriedIntent.getPackage()).isEqualTo(BACKLINKS_TASK_PACKAGE_NAME); + assertThat(queriedIntent.getAction()).isEqualTo(ACTION_MAIN); + assertThat(queriedIntent.getCategories()).containsExactly(CATEGORY_LAUNCHER); + + verifyMainLauncherBacklinksIntent(); + } + + @Test + public void triggerBacklinks_withNonResolvableMainLauncherIntent_noBacklinksAvailable() { + reset(mPackageManager); + doAnswer(invocation -> { + AssistContentRequester.Callback callback = invocation.getArgument(1); + callback.onAssistContentAvailable(EMPTY_ASSIST_CONTENT); + return null; + }).when(mAssistContentRequester).requestAssistContent(eq(BACKLINKS_TASK_ID), any()); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + assertThat(mViewModel.getBacklinksLiveData().getValue()).isNull(); + } + + @Test + public void triggerBacklinks_nonStandardActivityIgnored_noBacklinkAvailable() + throws RemoteException { + reset(mAtmService); + RootTaskInfo taskInfo = createTaskInfoForBacklinksTask(); + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME); + when(mAtmService.getAllRootTaskInfosOnDisplay(DEFAULT_DISPLAY)) + .thenReturn(List.of(taskInfo)); + + mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); + waitForIdleSync(); + + assertThat(mViewModel.getBacklinksLiveData().getValue()).isNull(); + } + + @Test + public void triggerBacklinks_taskIdsToIgnoreConsidered_noBacklinkAvailable() { + mViewModel.triggerBacklinks(Set.of(BACKLINKS_TASK_ID), DEFAULT_DISPLAY); + waitForIdleSync(); + + assertThat(mViewModel.getBacklinksLiveData().getValue()).isNull(); + } + + private void resetPackageManagerMockingForUsingFallbackBacklinks() { + reset(mPackageManager); + when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) + // First the logic queries whether a package has a launcher activity, this should + // resolve otherwise the logic filters out the task. + .thenReturn(createBacklinksTaskResolveInfo()) + // Then logic queries with the backlinks intent, this should not resolve for the + // logic to use the fallback intent. + .thenReturn(null); + } + + private void verifyMainLauncherBacklinksIntent() { + ClipData result = mViewModel.getBacklinksLiveData().getValue(); + assertThat(result.getItemCount()).isEqualTo(1); + + ClipDescription resultDescription = result.getDescription(); + assertThat(resultDescription.getLabel().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME); + assertThat(resultDescription.getMimeType(0)).isEqualTo(MIMETYPE_TEXT_INTENT); + + Intent actualBacklinksIntent = result.getItemAt(0).getIntent(); + assertThat(actualBacklinksIntent.getPackage()).isEqualTo(BACKLINKS_TASK_PACKAGE_NAME); + assertThat(actualBacklinksIntent.getAction()).isEqualTo(ACTION_MAIN); + assertThat(actualBacklinksIntent.getCategories()).containsExactly(CATEGORY_LAUNCHER); + } + + private static ResolveInfo createBacklinksTaskResolveInfo() { + ActivityInfo activityInfo = new ActivityInfo(); + activityInfo.applicationInfo = new ApplicationInfo(); + activityInfo.name = BACKLINKS_TASK_APP_NAME; + activityInfo.packageName = BACKLINKS_TASK_PACKAGE_NAME; + activityInfo.applicationInfo.packageName = BACKLINKS_TASK_PACKAGE_NAME; + ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = activityInfo; + return resolveInfo; + } + + private static RootTaskInfo createTaskInfoForBacklinksTask() { + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.taskId = BACKLINKS_TASK_ID; + taskInfo.isVisible = true; + taskInfo.isRunning = true; + taskInfo.numActivities = 1; + taskInfo.topActivity = new ComponentName(BACKLINKS_TASK_PACKAGE_NAME, "backlinksClass"); + taskInfo.topActivityInfo = createBacklinksTaskResolveInfo().activityInfo; + taskInfo.baseIntent = new Intent().setComponent(taskInfo.topActivity); + taskInfo.childTaskIds = new int[]{BACKLINKS_TASK_ID + 1}; + taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); + return taskInfo; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt index ce2facd59482..6b9865fbbacc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/message/ProfileMessageControllerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.screenshot.message import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 import android.content.pm.PackageManager import android.graphics.Canvas import android.graphics.ColorFilter @@ -27,7 +28,9 @@ import com.android.systemui.screenshot.data.repository.ProfileTypeRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith +@RunWith(AndroidJUnit4::class) class ProfileMessageControllerTest { @Test fun personalScreenshot() = runTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt index 4945ace3b88c..3b0e194ce223 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.screenshot.policy import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 import android.graphics.Insets import android.graphics.Rect import android.os.UserHandle @@ -34,7 +35,9 @@ import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import org.junit.Test +import org.junit.runner.RunWith +@RunWith(AndroidJUnit4::class) class PolicyRequestProcessorTest { val imageCapture = object : ImageCapture { @@ -78,4 +81,4 @@ class PolicyRequestProcessorTest { assertWithMessage("The topComponent of the screenshot").that(result.topComponent) .isEqualTo(ComponentName.unflattenFromString(FILES)) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt index 9e3ae054d31b..6e57761aafa6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.screenshot.policy import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 import android.os.UserHandle import com.android.systemui.kosmos.Kosmos import com.android.systemui.screenshot.data.model.DisplayContentModel @@ -40,7 +41,9 @@ import com.android.systemui.screenshot.policy.TestUserIds.PRIVATE import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith +@RunWith(AndroidJUnit4::class) class PrivateProfilePolicyTest { private val kosmos = Kosmos() private val policy = PrivateProfilePolicy(kosmos.profileTypeRepository) diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt index 5d35528b0cf0..8d217fc3ad25 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.screenshot.policy import android.content.ComponentName +import androidx.test.ext.junit.runners.AndroidJUnit4 import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags @@ -50,7 +51,9 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith +@RunWith(AndroidJUnit4::class) class WorkProfilePolicyTest { @JvmField @Rule val setFlagsRule = SetFlagsRule() diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java index aad461392cf6..88cb00cda638 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/FakeSessionTest.java @@ -23,8 +23,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -39,7 +39,7 @@ import org.junit.runner.RunWith; * client/connection. */ @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class FakeSessionTest extends SysuiTestCase { @Test public void testNonEmptyResult_hasImage() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java index f39f5439d4ac..f8de714c6021 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/scroll/ScrollCaptureControllerTest.java @@ -29,9 +29,9 @@ import static org.mockito.Mockito.when; import static java.lang.Math.abs; import android.content.Context; -import android.testing.AndroidTestingRunner; import android.view.ScrollCaptureResponse; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.logging.testing.UiEventLoggerFake; @@ -46,7 +46,7 @@ import org.junit.runner.RunWith; * screenshots. */ @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class ScrollCaptureControllerTest extends SysuiTestCase { private static final ScrollCaptureResponse EMPTY_RESPONSE = diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt index e32086b79918..e39e0fbad6e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ui/viewmodel/ScreenshotViewModelTest.kt @@ -17,12 +17,15 @@ package com.android.systemui.screenshot.ui.viewmodel import android.view.accessibility.AccessibilityManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.mock @SmallTest +@RunWith(AndroidJUnit4::class) class ScreenshotViewModelTest { private val accessibilityManager: AccessibilityManager = mock(AccessibilityManager::class.java) private val appearance = ActionButtonAppearance(null, "Label", "Description") diff --git a/packages/SystemUI/tests/src/com/android/systemui/scrim/ScrimViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/scrim/ScrimViewTest.java index a345f7804ae9..ca8da635e0f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scrim/ScrimViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/scrim/ScrimViewTest.java @@ -22,12 +22,12 @@ import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.testing.ViewUtils; import android.view.View; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; @@ -38,7 +38,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @SmallTest public class ScrimViewTest extends LeakCheckedTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt index 333e6344c18f..1a4749c3196c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/sensorprivacy/SensorUseStartedActivityTest.kt @@ -1,8 +1,8 @@ package com.android.systemui.sensorprivacy -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.mock @@ -11,7 +11,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class SensorUseStartedActivityTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt index 2b7840533df2..98260d88f389 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt @@ -19,9 +19,9 @@ package com.android.systemui.settings.brightness import android.hardware.display.DisplayManager import android.os.Handler import android.service.vr.IVrManager -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.settings.DisplayTracker @@ -40,7 +40,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper class BrightnessControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt index 31acd86f52f4..a06784e257de 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt @@ -18,11 +18,11 @@ package com.android.systemui.settings.brightness import android.content.Intent import android.graphics.Rect -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View import android.view.ViewGroup import android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KEY +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.FlakyTest import androidx.test.filters.SmallTest import androidx.test.rule.ActivityTestRule @@ -55,7 +55,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class BrightnessDialogTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt index 2b3588aa6e3c..c7bea5911a15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt @@ -16,11 +16,11 @@ package com.android.systemui.shade -import android.testing.AndroidTestingRunner import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.START +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -33,7 +33,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class CombinedShadeHeaderConstraintsTest : SysuiTestCase() { private lateinit var qqsConstraint: ConstraintSet diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangeTest.kt index 9b2e085560a1..8c8083543823 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangeTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangeTest.kt @@ -15,8 +15,8 @@ */ package com.android.systemui.shade -import android.testing.AndroidTestingRunner import androidx.constraintlayout.widget.ConstraintSet +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.mock @@ -27,7 +27,7 @@ import org.mockito.Mockito.inOrder import org.mockito.Mockito.verify @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class ConstraintChangeTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangesTest.kt index 0abb08427478..05c17060b461 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ConstraintChangesTest.kt @@ -15,8 +15,8 @@ */ package com.android.systemui.shade -import android.testing.AndroidTestingRunner import androidx.constraintlayout.widget.ConstraintSet +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.mock @@ -26,7 +26,7 @@ import org.junit.runner.RunWith import org.mockito.Mockito.inOrder @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class ConstraintChangesTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt index b4f890b5315e..2ac0ed0efff4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt @@ -17,8 +17,8 @@ package com.android.systemui.shade import android.os.PowerManager -import android.testing.AndroidTestingRunner import android.view.MotionEvent +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor @@ -47,7 +47,7 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class LockscreenHostedDreamGestureListenerTest : SysuiTestCase() { @Mock private lateinit var falsingManager: FalsingManager @Mock private lateinit var falsingCollector: FalsingCollector diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt index bff408a7ddba..abc96ee3c5f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt @@ -16,9 +16,9 @@ package com.android.systemui.shade -import android.testing.AndroidTestingRunner import android.view.View import android.view.ViewGroup +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -46,7 +46,7 @@ import org.mockito.MockitoAnnotations * the set of ids, which also dictact which direction to move and when, via a filter fn. */ @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { @Mock private lateinit var progressProvider: NaturalRotationUnfoldProgressProvider diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java index 13d44de44ca1..90e8ea5f34c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java @@ -47,13 +47,14 @@ import android.animation.ValueAnimator; import android.graphics.Point; import android.os.PowerManager; import android.platform.test.annotations.DisableFlags; -import android.testing.AndroidTestingRunner; +import android.platform.test.annotations.EnableFlags; import android.testing.TestableLooper; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import androidx.constraintlayout.widget.ConstraintSet; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.DejankUtils; @@ -78,7 +79,7 @@ import org.mockito.InOrder; import java.util.List; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) public class NotificationPanelViewControllerTest extends NotificationPanelViewControllerBaseTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt index d47bd4775f12..e1d92e780c2a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt @@ -19,11 +19,11 @@ package com.android.systemui.shade import android.platform.test.annotations.EnableFlags -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.HapticFeedbackConstants import android.view.View import android.view.ViewStub +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.util.CollectionUtils import com.android.keyguard.KeyguardClockSwitch.LARGE @@ -55,7 +55,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest class NotificationPanelViewControllerWithCoroutinesTest : diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt index 31bd12f9a168..fec7424ac006 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt @@ -16,10 +16,10 @@ package com.android.systemui.shade import android.os.SystemClock -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.MotionEvent import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardSecurityContainerController import com.android.keyguard.LegacyLockIconViewController @@ -82,7 +82,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @ExperimentalCoroutinesApi -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) @SmallTest class NotificationShadeWindowViewTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt index 0c3af03da59e..97ce37c82c83 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt @@ -16,11 +16,11 @@ package com.android.systemui.shade -import android.testing.AndroidTestingRunner import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.constraintlayout.widget.ConstraintLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.qs.QSFragmentLegacy @@ -34,7 +34,7 @@ import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class NotificationsQuickSettingsContainerTest : SysuiTestCase() { @Mock private lateinit var qsFrame: View diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt index 3900defd4ed4..effd28edc68b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt @@ -20,9 +20,9 @@ import android.hardware.display.AmbientDisplayConfiguration import android.os.PowerManager import android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE import android.provider.Settings.Secure.DOZE_TAP_SCREEN_GESTURE -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.MotionEvent +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dock.DockManager @@ -49,7 +49,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) @SmallTest class PulsingGestureListenerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt index 2cd740d35c14..f38bf13d0bda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt @@ -3,8 +3,8 @@ package com.android.systemui.shade import android.content.Context import android.content.res.Resources import android.graphics.Rect -import android.testing.AndroidTestingRunner import android.view.DisplayCutout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -21,7 +21,7 @@ import org.mockito.Mock import org.mockito.junit.MockitoJUnit @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class QsBatteryModeControllerTest : SysuiTestCase() { private companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java index ad4b4fdc4eec..9a6423d96d4b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java @@ -36,10 +36,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.platform.test.annotations.EnableFlags; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.MotionEvent; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.plugins.qs.QS; @@ -53,7 +53,7 @@ import org.mockito.ArgumentCaptor; import java.util.List; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) public class QuickSettingsControllerImplTest extends QuickSettingsControllerImplBaseTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt index dfd7a715fcdf..46961d4db0f6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplWithCoroutinesTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.shade import android.app.StatusBarManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.google.common.truth.Truth.assertThat @@ -25,9 +26,11 @@ import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class QuickSettingsControllerImplWithCoroutinesTest : QuickSettingsControllerImplBaseTest() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt index 6bdd3ef5cebe..02172383485d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt @@ -16,10 +16,10 @@ package com.android.systemui.shade -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.Display import android.view.WindowManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.statusbar.IStatusBarService import com.android.systemui.SysuiTestCase @@ -59,7 +59,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) @SmallTest class ShadeControllerImplTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeExpansionStateManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeExpansionStateManagerTest.kt index 89ae42fd9f83..4734edee7626 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeExpansionStateManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeExpansionStateManagerTest.kt @@ -16,13 +16,16 @@ package com.android.systemui.shade +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class ShadeExpansionStateManagerTest : SysuiTestCase() { private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt index 7a9ef62278a4..c6699590e499 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/CellSignalStateTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.shade.carrier -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Assert.assertNotSame @@ -24,7 +24,7 @@ import org.junit.Assert.assertSame import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class CellSignalStateTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java index a42121a41e46..1a2531ac8c75 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java @@ -21,13 +21,13 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.content.Context; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.settingslib.mobile.TelephonyIcons; @@ -38,7 +38,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper @SmallTest public class ShadeCarrierTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt index 7c33648e08a3..10c017bdc525 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt @@ -1,6 +1,6 @@ package com.android.systemui.shade.transition -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository @@ -30,7 +30,7 @@ import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class ScrimShadeTransitionControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt index 4679a58645d9..89a3d5b5cf0b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt @@ -20,8 +20,8 @@ import android.content.Context import android.content.res.Resources import android.content.res.TypedArray import android.platform.test.annotations.PlatinumTest -import android.testing.AndroidTestingRunner import android.util.AttributeSet +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.shared.R @@ -39,7 +39,7 @@ import org.mockito.junit.MockitoRule @PlatinumTest(focusArea = "sysui") @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class DoubleShadowTextClockTest : SysuiTestCase() { @get:Rule val mockito: MockitoRule = MockitoJUnit.rule() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt index fc230e362735..5d8f868158e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListenerTest.kt @@ -17,9 +17,9 @@ package com.android.systemui.shared.animation import android.graphics.Paint -import android.testing.AndroidTestingRunner import android.widget.FrameLayout import android.widget.TextView +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -28,7 +28,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class DisableSubpixelTextTransitionListenerTest : SysuiTestCase() { private lateinit var disableSubpixelTextTransitionListener: diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt index 293dc048af1d..3a53a5aaedfa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt @@ -14,9 +14,9 @@ */ package com.android.systemui.shared.animation -import android.testing.AndroidTestingRunner import android.view.View import android.view.ViewGroup +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction @@ -34,7 +34,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() { private val progressProvider = FakeUnfoldTransitionProvider() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt index 3cb48d9b2462..fbaddfaf7216 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt @@ -15,8 +15,8 @@ package com.android.systemui.shared.animation import android.graphics.Point +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import android.testing.AndroidTestingRunner import android.view.Display import android.view.Surface.ROTATION_0 import android.view.Surface.ROTATION_90 @@ -36,7 +36,7 @@ import org.mockito.Mockito.spy import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt index 7b0cd19ca7f2..e076418f2630 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt @@ -16,8 +16,8 @@ package com.android.systemui.shared.clocks -import android.testing.AndroidTestingRunner import android.view.LayoutInflater +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.app.animation.Interpolators import com.android.systemui.customization.R @@ -34,7 +34,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.junit.MockitoJUnit -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class AnimatableClockViewTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt index 74d017375eb5..2f52248dab6f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt @@ -19,7 +19,7 @@ import android.content.ComponentName import android.content.ContentResolver import android.content.Context import android.graphics.drawable.Drawable -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.flags.FakeFeatureFlags @@ -55,7 +55,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class ClockRegistryTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt index e0e8d1f51884..2522ed7f9a3c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt @@ -19,10 +19,10 @@ package com.android.systemui.shared.clocks import android.content.res.Resources import android.graphics.Color import android.graphics.drawable.Drawable -import android.testing.AndroidTestingRunner import android.util.TypedValue import android.view.LayoutInflater import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.customization.R @@ -53,7 +53,7 @@ import org.mockito.junit.MockitoJUnit private fun DefaultClockProvider.createClock(id: ClockId): DefaultClockController = createClock(ClockSettings(id, null)) as DefaultClockController -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class DefaultClockProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt index 1a0e932d7e8a..8418598c256b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.shared.condition -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.shared.condition.Condition.START_EAGERLY @@ -32,7 +32,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class CombinedConditionTest : SysuiTestCase() { class FakeCondition diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt index 0a8210d6b319..83fb14aaf792 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt @@ -1,6 +1,6 @@ package com.android.systemui.shared.condition -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -19,7 +19,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class ConditionExtensionsTest : SysuiTestCase() { private lateinit var testScope: TestScope diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java index 65ca0a2400c1..267f22bb2569 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java @@ -27,8 +27,8 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -51,7 +51,7 @@ import java.util.Collections; import java.util.HashSet; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class ConditionMonitorTest extends SysuiTestCase { private FakeCondition mCondition1; private FakeCondition mCondition2; diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java index cec5d0a3b55f..a224843e592a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java @@ -25,8 +25,8 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -40,7 +40,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class ConditionTest extends SysuiTestCase { @Mock CoroutineScope mScope; diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt index 5fc09c7d5563..2a6754cbdd1a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt @@ -17,12 +17,12 @@ package com.android.systemui.shared.navigationbar import android.graphics.Rect -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.SurfaceControl import android.view.View import android.view.ViewRootImpl import androidx.concurrent.futures.DirectExecutor +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.concurrency.FakeExecutor @@ -43,7 +43,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @RunWithLooper class RegionSamplingHelperTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt index 0dd988d424b9..8bfb07bd08b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.shared.notifications.data.repository import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -28,10 +29,9 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class NotificationSettingsRepositoryTest : SysuiTestCase() { private lateinit var underTest: NotificationSettingsRepository diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java index 40c84d611198..c721ceb10f86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java @@ -28,9 +28,9 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; @@ -55,7 +55,7 @@ import java.util.Collections; import java.util.List; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @RunWithLooper public class PluginManagerTest extends SysuiTestCase { private static final String PRIVILEGED_PACKAGE = "com.android.systemui"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java index 711187be33fb..15fdc7c84060 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/VersionInfoTest.java @@ -17,6 +17,7 @@ package com.android.systemui.shared.plugins; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -29,8 +30,10 @@ import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; @SmallTest +@RunWith(AndroidJUnit4.class) public class VersionInfoTest extends SysuiTestCase { @Rule diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt index 1031621e2e7e..7fc845c17613 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplerTest.kt @@ -4,8 +4,8 @@ import android.app.WallpaperColors import android.app.WallpaperManager import android.graphics.Color import android.graphics.RectF -import android.testing.AndroidTestingRunner import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any @@ -28,7 +28,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class RegionSamplerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt index ee3d87089b6d..5a4ef055265c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt @@ -15,11 +15,11 @@ */ package com.android.systemui.shared.rotation -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.Display import android.view.WindowInsetsController import android.view.WindowManagerPolicyConstants +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -27,7 +27,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @RunWithLooper class RotationButtonControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt index b761647e24e3..d67ce303c451 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.shared.system +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -8,6 +9,7 @@ import org.junit.Assert.assertThrows import org.junit.Before import org.junit.Ignore import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.any import org.mockito.Mockito.only @@ -16,6 +18,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class UncaughtExceptionPreHandlerTest : SysuiTestCase() { private lateinit var preHandlerManager: UncaughtExceptionPreHandlerManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt index e9676c83c39e..d0ba629c4998 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt @@ -20,11 +20,13 @@ import android.content.res.Resources import android.view.CrossWindowBlurListeners import android.view.SurfaceControl import android.view.ViewRootImpl +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.any @@ -37,6 +39,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class BlurUtilsTest : SysuiTestCase() { @Mock lateinit var resources: Resources @@ -117,4 +120,4 @@ class BlurUtilsTest : SysuiTestCase() { return transaction } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index 5da3a569f91a..9df46e5047d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -42,6 +42,7 @@ import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; import android.view.accessibility.Flags; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.statusbar.LetterboxDetails; @@ -54,8 +55,10 @@ import com.android.systemui.statusbar.CommandQueue.Callbacks; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; @SmallTest +@RunWith(AndroidJUnit4.class) public class CommandQueueTest extends SysuiTestCase { private static final LetterboxDetails[] TEST_LETTERBOX_DETAILS = new LetterboxDetails[] { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java index 3b85dbacc699..5f9c9df7ab23 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java @@ -23,18 +23,21 @@ import android.app.RemoteInput; import android.content.Intent; import android.graphics.drawable.Icon; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.systemui.SysuiTestCase; import org.junit.Test; +import org.junit.runner.RunWith; import java.util.Arrays; import java.util.Collections; import java.util.List; @SmallTest +@RunWith(AndroidJUnit4.class) public class NotificationUiAdjustmentTest extends SysuiTestCase { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt index 9c59f9bf49d8..396d0171783b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt @@ -20,6 +20,7 @@ import android.telephony.ServiceState import android.telephony.SubscriptionInfo import android.telephony.TelephonyManager import android.telephony.telephonyManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.keyguardUpdateMonitor import com.android.systemui.SysuiTestCase @@ -44,11 +45,13 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class OperatorNameViewControllerTest : SysuiTestCase() { private lateinit var underTest: OperatorNameViewController private lateinit var airplaneModeInteractor: AirplaneModeInteractor diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt index 7d2b463afab7..5fbdfbf17df4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt @@ -16,10 +16,10 @@ package com.android.systemui.statusbar.chips.ui.view -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.LayoutInflater import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.res.R @@ -29,7 +29,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class ChipBackgroundContainerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt index b8d4e47544dd..6f7711759603 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt @@ -16,10 +16,10 @@ package com.android.systemui.statusbar.chips.ui.view -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.LayoutInflater import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.res.R @@ -36,7 +36,7 @@ private const val LARGE_TEXT = "00:000" private const val XL_TEXT = "00:0000" @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class ChipChronometerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt index a7b1411f2a45..912a10af7bd0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.chips.ui.viewmodel +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Icon @@ -38,8 +39,10 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class OngoingActivityChipsViewModelTest : SysuiTestCase() { private val kosmos = Kosmos().also { it.testCase = this } private val testScope = kosmos.testScope diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandParserTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandParserTest.kt index cfbe8e36537d..673cf59fc72b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandParserTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandParserTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.commandline +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -24,8 +25,10 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertThrows import org.junit.Assert.assertTrue import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class CommandParserTest : SysuiTestCase() { private val parser = CommandParser() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt index e391d6b11cd6..83811cd61581 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParametersTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.statusbar.commandline +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -7,8 +8,10 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertThrows import org.junit.Assert.assertTrue import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class ParametersTest : SysuiTestCase() { @Test fun singleArgOptional_returnsNullBeforeParse() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt index 86548d079003..1a7c8a336c81 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.commandline +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -24,10 +25,12 @@ import org.junit.Assert.assertThrows import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class ParseableCommandTest : SysuiTestCase() { @Mock private lateinit var pw: PrintWriter diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt index 759f0bcd6ea8..8cf7473345a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/ValueParserTest.kt @@ -1,13 +1,16 @@ package com.android.systemui.statusbar.commandline import android.graphics.Rect +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertTrue import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class ValueParserTest : SysuiTestCase() { @Test fun parseString() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt index 0fdda62e3b30..ca90f742db40 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.connectivity.ui import android.telephony.SubscriptionInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.demomode.DemoModeController @@ -28,12 +29,14 @@ import com.android.systemui.util.mockito.withArgCaptor import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class MobileContextProviderTest : SysuiTestCase() { @Mock private lateinit var networkController: NetworkController @Mock private lateinit var dumpManager: DumpManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt index b1c994c2374e..7c98037a5c41 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepositoryImplTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.data.repository +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.R import com.android.systemui.SysuiTestCase @@ -29,9 +30,11 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.verify @SmallTest +@RunWith(AndroidJUnit4::class) class KeyguardStatusBarRepositoryImplTest : SysuiTestCase() { private val testScope = TestScope() private val configurationController = mock<ConfigurationController>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt index 4b250b2848a4..7f981eec7ee1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt @@ -23,6 +23,7 @@ import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS import android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS import android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS import android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.statusbar.LetterboxDetails import com.android.internal.view.AppearanceRegion @@ -48,9 +49,11 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.verify @SmallTest +@RunWith(AndroidJUnit4::class) class StatusBarModeRepositoryImplTest : SysuiTestCase() { private val testScope = TestScope() private val commandQueue = mock<CommandQueue>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt index f1c7956a1bc7..fffcbb6ccd32 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt @@ -16,13 +16,16 @@ package com.android.systemui.statusbar.disableflags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertThrows import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class DisableFlagsLoggerTest : SysuiTestCase() { private val disable1Flags = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt index 215afb2143df..cf78c71fe047 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt @@ -24,17 +24,20 @@ import android.app.StatusBarManager.DISABLE_EXPAND import android.app.StatusBarManager.DISABLE_NAVIGATION import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS import android.app.StatusBarManager.DISABLE_NOTIFICATION_TICKER +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.CommandQueue import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class DisableStateTrackerTest : SysuiTestCase() { private lateinit var underTest: DisableStateTracker diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt index 31e1fef76383..d2dfc9257e7e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt @@ -21,6 +21,7 @@ import android.app.StatusBarManager.DISABLE_CLOCK import android.app.StatusBarManager.DISABLE_NONE import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS import android.content.res.Configuration +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R import com.android.systemui.SysuiTestCase @@ -42,10 +43,12 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.verify @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class DisableFlagsRepositoryTest : SysuiTestCase() { private lateinit var underTest: DisableFlagsRepository diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt index b944d7248173..7a8533ee6d69 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt @@ -35,6 +35,7 @@ import android.provider.Settings import android.testing.TestableLooper.RunWithLooper import android.view.View import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.SysuiTestCase @@ -69,6 +70,7 @@ import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.time.FakeSystemClock import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock @@ -86,6 +88,7 @@ import java.util.concurrent.Executor @SmallTest @RunWithLooper(setAsMainLooper = true) +@RunWith(AndroidJUnit4::class) class LockscreenSmartspaceControllerTest : SysuiTestCase() { companion object { const val SMARTSPACE_TIME_TOO_EARLY = 1000L diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt index b161f84c94ff..05057278f7ca 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt @@ -23,6 +23,7 @@ import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.service.notification.StatusBarNotification +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING @@ -54,11 +55,13 @@ import dagger.Component import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever @SmallTest +@RunWith(AndroidJUnit4::class) class SensitiveContentCoordinatorTest : SysuiTestCase() { val dynamicPrivacyController: DynamicPrivacyController = mock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt index 8272f5a0d5b9..ef2a2aa67a08 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.smartspace.SmartspaceTarget import android.content.ComponentName import android.os.UserHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener @@ -43,6 +44,7 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never @@ -51,6 +53,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class SmartspaceDedupingCoordinatorTest : SysuiTestCase() { @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt index 11996fef6255..99bd4fc549a8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.render +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.logcatLogBuffer @@ -37,10 +38,12 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito import org.mockito.Mockito.`when` as whenever @SmallTest +@RunWith(AndroidJUnit4::class) class NodeSpecBuilderTest : SysuiTestCase() { private val mediaContainerController: MediaContainerController = mock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt index 70d309b10338..ca75ca679c31 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.render +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.notification.collection.GroupEntry @@ -32,6 +33,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.withArgCaptor import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.inOrder import org.mockito.Mockito.never @@ -42,6 +44,7 @@ import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class RenderStageManagerTest : SysuiTestCase() { @Mock private lateinit var shadeListBuilder: ShadeListBuilder diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt index b7750795fe71..79ff4be253e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt @@ -15,6 +15,7 @@ package com.android.systemui.statusbar.notification.domain.interactor import android.app.StatusBarManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysUITestComponent import com.android.systemui.SysUITestModule @@ -26,8 +27,10 @@ import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class NotificationAlertsInteractorTest : SysuiTestCase() { @Component(modules = [SysUITestModule::class]) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt index a0faab563452..982b7b113a02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationLaunchAnimationInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.domain.interactor +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -23,8 +24,10 @@ import com.android.systemui.statusbar.notification.data.repository.NotificationL import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class NotificationLaunchAnimationInteractorTest : SysuiTestCase() { private val repository = NotificationLaunchAnimationRepository() private val underTest = NotificationLaunchAnimationInteractor(repository) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt index 3593f5b4963e..133a114fed9d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt @@ -13,6 +13,7 @@ */ package com.android.systemui.statusbar.notification.domain.interactor +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysUITestComponent import com.android.systemui.SysUITestModule @@ -25,8 +26,10 @@ import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class NotificationsKeyguardInteractorTest : SysuiTestCase() { @SysUISingleton diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt index 334776ca0bcc..277b8876f57f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.domain.interactor import android.service.notification.StatusBarNotification +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -31,8 +32,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class RenderNotificationsListInteractorTest : SysuiTestCase() { private val backgroundDispatcher = StandardTestDispatcher() private val testScope = TestScope(backgroundDispatcher) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 7304bd62293d..0766afc7cb15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -793,6 +793,73 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { } @Test + public void isExpanded_onKeyguard_allowOnKeyguardExpanded() throws Exception { + // GIVEN + final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + row.setOnKeyguard(true); + row.setUserExpanded(true); + + // THEN + assertThat(row.isExpanded(/*allowOnKeyguard =*/ true)).isTrue(); + } + @Test + public void isExpanded_onKeyguard_notAllowOnKeyguardNotExpanded() throws Exception { + // GIVEN + final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + row.setOnKeyguard(true); + row.setUserExpanded(true); + + // THEN + assertThat(row.isExpanded(/*allowOnKeyguard =*/ false)).isFalse(); + } + + @Test + public void isExpanded_systemExpanded_expanded() throws Exception { + // GIVEN + final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + row.setOnKeyguard(false); + row.setSystemExpanded(true); + + // THEN + assertThat(row.isExpanded()).isTrue(); + } + + @Test + public void isExpanded_systemChildExpanded_expanded() throws Exception { + // GIVEN + final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + row.setOnKeyguard(false); + row.setSystemChildExpanded(true); + + // THEN + assertThat(row.isExpanded()).isTrue(); + } + + @Test + public void isExpanded_userExpanded_expanded() throws Exception { + // GIVEN + final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + row.setOnKeyguard(false); + row.setSystemExpanded(true); + row.setUserExpanded(true); + + // THEN + assertThat(row.isExpanded()).isTrue(); + } + + @Test + public void isExpanded_userExpandedFalse_notExpanded() throws Exception { + // GIVEN + final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); + row.setOnKeyguard(false); + row.setSystemExpanded(true); + row.setUserExpanded(false); + + // THEN + assertThat(row.isExpanded()).isFalse(); + } + + @Test public void onDisappearAnimationFinished_shouldSetFalse_headsUpAnimatingAway() throws Exception { final ExpandableNotificationRow row = mNotificationTestHelper.createRow(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt index 1dfcb38b247b..578950fa88b5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/DisplaySwitchNotificationsHiderTrackerTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.statusbar.notification.stack +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.util.LatencyTracker import com.android.internal.util.LatencyTracker.ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE @@ -31,12 +32,14 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.verify @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class DisplaySwitchNotificationsHiderTrackerTest : SysuiTestCase() { private val testScope = TestScope() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 12f3ef3cf553..967f95eb0ef6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -214,6 +214,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + @DisableSceneContainer // TODO(b/332574413) cover stack bounds integration with tests public void testUpdateStackHeight_qsExpansionGreaterThanZero() { final float expansionFraction = 0.2f; final float overExpansion = 50f; @@ -891,6 +892,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + @DisableSceneContainer // NSSL has no more scroll logic when SceneContainer is on public void testNormalShade_hasNoTopOverscroll() { mTestableResources .addOverride(R.bool.config_use_split_notification_shade, /* value= */ false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index a6fb7187ff5f..8401a19f075d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -5,11 +5,14 @@ import android.content.pm.PackageManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ShadeInterpolation.getContentAlpha import com.android.systemui.dump.DumpManager +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.res.R @@ -37,6 +40,7 @@ import org.junit.Assume import org.junit.Before import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.any import org.mockito.Mockito.eq import org.mockito.Mockito.mock @@ -44,6 +48,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever @SmallTest +@RunWith(AndroidJUnit4::class) class StackScrollAlgorithmTest : SysuiTestCase() { @JvmField @Rule var expect: Expect = Expect.create() @@ -63,7 +68,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { EmptyShadeView(context, /* attrs= */ null).apply { layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100) } - private val footerView = FooterView(context, /*attrs=*/ null) + private val footerView = FooterView(context, /* attrs= */ null) @OptIn(ExperimentalCoroutinesApi::class) private val ambientState = AmbientState( @@ -123,6 +128,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } @Test + @DisableSceneContainer // TODO(b/332574413) cover hun bounds integration with tests fun resetViewStates_defaultHunWhenShadeIsOpening_yTranslationIsInset() { whenever(notificationRow.isPinned).thenReturn(true) whenever(notificationRow.isHeadsUp).thenReturn(true) @@ -165,6 +171,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } @Test + @DisableSceneContainer // TODO(b/332574413) cover hun bounds integration with tests @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME) fun resetViewStates_defaultHun_showingQS_newHeadsUpAnim_hunTranslatedToMax() { // Given: the shade is open and scrolled to the bottom to show the QuickSettings @@ -181,6 +188,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } @Test + @DisableSceneContainer // TODO(b/332574413) cover hun bounds integration with tests @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME) fun resetViewStates_hunAnimatingAway_showingQS_newHeadsUpAnim_hunTranslatedToBottomOfScreen() { // Given: the shade is open and scrolled to the bottom to show the QuickSettings @@ -269,6 +277,27 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } @Test + @EnableSceneContainer + fun resetViewStates_emptyShadeView_isCenteredVertically_withSceneContainer() { + stackScrollAlgorithm.initView(context) + hostView.removeAllViews() + hostView.addView(emptyShadeView) + ambientState.layoutMaxHeight = maxPanelHeight.toInt() + + val stackTop = 200f + val stackBottom = 2000f + val stackHeight = stackBottom - stackTop + ambientState.stackTop = stackTop + ambientState.stackCutoff = stackBottom + + stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) + + val centeredY = stackTop + stackHeight / 2f - emptyShadeView.height / 2f + assertThat(emptyShadeView.viewState.yTranslation).isEqualTo(centeredY) + } + + @Test + @DisableSceneContainer fun resetViewStates_emptyShadeView_isCenteredVertically() { stackScrollAlgorithm.initView(context) hostView.removeAllViews() @@ -1154,6 +1183,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() { assertFalse(stackScrollAlgorithm.shouldHunAppearFromBottom(ambientState, viewState)) } + // endregion private fun createHunViewMock( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt index c44c178db38a..2f810276d7b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImplTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone import android.content.pm.UserInfo import android.os.UserManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.settings.UserTracker @@ -29,12 +30,14 @@ import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class ManagedProfileControllerImplTest : SysuiTestCase() { private val mainExecutor: FakeExecutor = FakeExecutor(FakeSystemClock()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index ba38f871cf9d..25314f379e7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -27,6 +27,7 @@ import android.view.View import android.view.ViewTreeObserver import android.view.ViewTreeObserver.OnPreDrawListener import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.systemui.SysuiTestCase @@ -54,6 +55,7 @@ import java.util.Optional import javax.inject.Provider import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.mock @@ -64,6 +66,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Mock private lateinit var shadeViewController: ShadeViewController diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt index 5a0e13d02b92..2d9880a48f80 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone.domain.interactor +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -25,8 +26,10 @@ import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepositor import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class LightsOutInteractorTest : SysuiTestCase() { private val statusBarModeRepository = FakeStatusBarModeRepository() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt index e0f1e1a46d3b..219b16f1e0ef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone.fragment +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -26,9 +27,11 @@ import com.google.common.truth.Truth.assertThat import java.io.PrintWriter import java.io.StringWriter import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.mock @SmallTest +@RunWith(AndroidJUnit4::class) class CollapsedStatusBarFragmentLoggerTest : SysuiTestCase() { private val buffer = LogBufferFactory(DumpManager(), mock(LogcatEchoTracker::class.java)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt index 022b5d295256..9f6f51a28764 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/StatusBarVisibilityModelTest.kt @@ -19,14 +19,17 @@ import android.app.StatusBarManager.DISABLE_CLOCK import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS import android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP import android.app.StatusBarManager.DISABLE_SYSTEM_INFO +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.phone.fragment.StatusBarVisibilityModel.Companion.createDefaultModel import com.android.systemui.statusbar.phone.fragment.StatusBarVisibilityModel.Companion.createModelFromFlags import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class StatusBarVisibilityModelTest : SysuiTestCase() { @Test fun createDefaultModel_everythingEnabled() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt index 7273d9f55259..5174ec7189ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt @@ -25,11 +25,11 @@ import android.app.Person import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.service.notification.NotificationListenerService.REASON_USER_STOPPED -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.Flags.FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS @@ -80,7 +80,7 @@ private const val PROC_STATE_VISIBLE = ActivityManager.PROCESS_STATE_TOP private const val PROC_STATE_INVISIBLE = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper @OptIn(ExperimentalCoroutinesApi::class) class OngoingCallControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt index ecec124e83e2..5ce936d11a64 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt @@ -16,13 +16,16 @@ package com.android.systemui.statusbar.phone.ongoingcall +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class OngoingCallLoggerTest : SysuiTestCase() { private val uiEventLoggerFake = UiEventLoggerFake() private val ongoingCallLogger = OngoingCallLogger(uiEventLoggerFake) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt index d6624ca6c559..27c2366ebdb5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepositoryTest.kt @@ -16,13 +16,16 @@ package com.android.systemui.statusbar.phone.ongoingcall.data.repository +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class OngoingCallRepositoryTest : SysuiTestCase() { private val underTest = OngoingCallRepository() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt index 7e523fbd8747..19abbd58ad3a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone.ui import android.os.UserHandle +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.statusbar.StatusBarIcon import com.android.systemui.SysuiTestCase @@ -32,11 +33,13 @@ import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class StatusBarIconControllerImplTest : SysuiTestCase() { private lateinit var underTest: StatusBarIconControllerImpl diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java index 14bce9c54a20..891ff38764fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java @@ -25,11 +25,11 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.ViewGroup; import android.widget.LinearLayout; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.statusbar.StatusBarIcon; @@ -55,7 +55,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @RunWithLooper(setAsMainLooper = true) @SmallTest public class StatusBarIconControllerTest extends LeakCheckedTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt index 1c9f52366fe0..b823333978f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableLogBuffer @@ -33,12 +34,14 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") +@RunWith(AndroidJUnit4::class) class AirplaneModeViewModelImplTest : SysuiTestCase() { private lateinit var underTest: AirplaneModeViewModelImpl diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt index 6028712c29fc..f9ae5ff9bbc3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.ethernet.domain +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.AccessibilityContentDescriptions import com.android.systemui.res.R @@ -28,8 +29,10 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class EthernetInteractorTest : SysuiTestCase() { private val connectivityRepository = FakeConnectivityRepository() private val underTest = EthernetInteractor(connectivityRepository) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt index 3de50c97a258..4a2f6f281566 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt @@ -21,15 +21,18 @@ import android.telephony.CarrierConfigManager import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL import android.telephony.CarrierConfigManager.KEY_SHOW_5G_SLICE_ICON_BOOL import android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class SystemUiCarrierConfigTest : SysuiTestCase() { lateinit var underTest: SystemUiCarrierConfig diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt index 932c4a17cae2..320c148f497c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt @@ -20,6 +20,7 @@ import android.content.Intent import android.os.PersistableBundle import android.telephony.CarrierConfigManager import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.systemui.SysuiTestCase @@ -37,6 +38,7 @@ import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.MockitoAnnotations @@ -45,6 +47,7 @@ import org.mockito.quality.Strictness @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class CarrierConfigRepositoryTest : SysuiTestCase() { private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt index 6785de930849..db6f59276eb6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt @@ -43,11 +43,12 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.After +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters +import platform.test.runner.parameterized.Parameter import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.Parameterized -import org.junit.runners.Parameterized.Parameters /** * Parameterized test for all of the common values of [FakeNetworkEventModel]. This test simply @@ -56,7 +57,7 @@ import org.junit.runners.Parameterized.Parameters */ @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(Parameterized::class) +@RunWith(ParameterizedAndroidJunit4::class) internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt index a41bc0d87615..5e0d2fb05e59 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.SignalIcon import com.android.settingslib.mobile.TelephonyIcons.THREE_G @@ -49,9 +50,11 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { private val dumpManager: DumpManager = mock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt index 3c13906dbd43..fd4c3702a666 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt @@ -23,6 +23,7 @@ import android.telephony.SignalStrength import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET import android.telephony.TelephonyCallback import android.telephony.TelephonyManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -58,6 +59,7 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.never import org.mockito.Mockito.verify @@ -69,6 +71,7 @@ import org.mockito.Mockito.verify @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class FullMobileConnectionRepositoryTest : SysuiTestCase() { private lateinit var underTest: FullMobileConnectionRepository diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index 6d8bf55d489b..8fd0b31b82f3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -66,6 +66,7 @@ import android.telephony.TelephonyManager.EXTRA_SPN import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID import android.telephony.TelephonyManager.NETWORK_TYPE_LTE import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.mobile.MobileMappings import com.android.systemui.SysuiTestCase @@ -107,6 +108,7 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -114,6 +116,7 @@ import org.mockito.MockitoAnnotations @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class MobileConnectionRepositoryTest : SysuiTestCase() { private lateinit var underTest: MobileConnectionRepositoryImpl private lateinit var connectionsRepo: FakeMobileConnectionsRepository diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt index 14884182d656..30e96f10918d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt @@ -20,6 +20,7 @@ import android.platform.test.annotations.EnableFlags import android.telephony.CellSignalStrength import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.mobile.MobileIconCarrierIdOverrides import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl @@ -52,11 +53,13 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class MobileIconInteractorTest : SysuiTestCase() { private lateinit var underTest: MobileIconInteractor private val mobileMappingsProxy = FakeMobileMappingsProxy() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt index 58d9ee3935fd..cc0eae7e6fea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt @@ -21,6 +21,7 @@ import android.telephony.SubscriptionManager import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID import android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.mobile.MobileMappings import com.android.systemui.SysuiTestCase @@ -50,11 +51,13 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class MobileIconsInteractorTest : SysuiTestCase() { private lateinit var underTest: MobileIconsInteractor private lateinit var connectivityRepository: FakeConnectivityRepository diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt index 755aaa6541ff..4511be954692 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.pipeline.mobile.ui import android.widget.TextView +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -32,10 +33,12 @@ import java.io.PrintWriter import java.io.StringWriter import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class MobileViewLoggerTest : SysuiTestCase() { private val buffer = LogBufferFactory(DumpManager(), mock()).create("buffer", 10) private val stringWriter = StringWriter() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt index cdc4733715e5..fc1ea227f1bd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcherTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.satellite.data import android.telephony.TelephonyManager import android.telephony.satellite.SatelliteManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -41,9 +42,11 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito.verify @SmallTest +@RunWith(AndroidJUnit4::class) class DeviceBasedSatelliteRepositorySwitcherTest : SysuiTestCase() { private val testDispatcher = StandardTestDispatcher() private val testScope = TestScope(testDispatcher) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt index f77fd1999007..87693891a281 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/demo/DemoDeviceBasedSatelliteRepositoryTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.satellite.data.demo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -29,8 +30,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class DemoDeviceBasedSatelliteRepositoryTest : SysuiTestCase() { private val testDispatcher = StandardTestDispatcher() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt index f7ff568332ca..73ac6e3573d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt @@ -37,6 +37,7 @@ import android.telephony.satellite.SatelliteManager.SatelliteException import android.telephony.satellite.SatelliteModemStateCallback import android.telephony.satellite.SatelliteProvisionStateCallback import android.telephony.satellite.SatelliteSupportedStateCallback +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -61,6 +62,7 @@ import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.atLeastOnce @@ -73,6 +75,7 @@ import org.mockito.MockitoAnnotations @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { private lateinit var underTest: DeviceBasedSatelliteRepositoryImpl diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt index 2e5ebb3e3194..cd0390ecf9c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.satellite.domain.interactor import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.telephony.flags.Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG import com.android.systemui.SysuiTestCase @@ -38,8 +39,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class DeviceBasedSatelliteInteractorTest : SysuiTestCase() { private lateinit var underTest: DeviceBasedSatelliteInteractor diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt index c39e301155fe..64b07fcaa8c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Icon @@ -41,9 +42,11 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.runner.RunWith import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { private lateinit var underTest: DeviceBasedSatelliteViewModel private lateinit var interactor: DeviceBasedSatelliteInteractor diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt index c43778a4ae51..4c2bb7f8069d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt @@ -16,13 +16,16 @@ package com.android.systemui.statusbar.pipeline.shared.data.model +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.LogMessageImpl import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class DefaultConnectionModelTest : SysuiTestCase() { @Test fun messageInitializerAndPrinter_isValidatedFalse_hasCorrectInfo() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt index fa4e91b68a5e..f486787e9cc7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt @@ -25,6 +25,7 @@ import android.net.NetworkCapabilities.TRANSPORT_WIFI import android.net.vcn.VcnTransportInfo import android.net.wifi.WifiInfo import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -50,6 +51,7 @@ import kotlinx.coroutines.test.runTest import kotlinx.coroutines.yield import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever @@ -57,6 +59,7 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class ConnectivityRepositoryImplTest : SysuiTestCase() { private lateinit var underTest: ConnectivityRepositoryImpl diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt index 028a58c6e1b0..c3ad0f9d5148 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt @@ -17,8 +17,8 @@ package com.android.systemui.statusbar.pipeline.shared.ui.view import android.graphics.Rect -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT @@ -30,7 +30,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper(setAsMainLooper = true) class ModernStatusBarViewTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt index ca9df57e8798..a6cdfe23aa5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt @@ -17,8 +17,8 @@ package com.android.systemui.statusbar.pipeline.shared.ui.view import android.graphics.Rect -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.StatusBarIconView @@ -32,7 +32,7 @@ import org.junit.runner.RunWith * method. */ @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class SingleBindableStatusBarIconViewTest : SysuiTestCase() { private lateinit var binding: SingleBindableStatusBarIconViewBinding diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt index 92de8662928f..b4c6106150b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -60,9 +61,11 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class CollapsedStatusBarViewModelImplTest : SysuiTestCase() { private val kosmos = Kosmos().also { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt index 0cb3329dcb4d..2238bff8eb93 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.AccessibilityContentDescriptions.WIFI_OTHER_DEVICE_CONNECTION import com.android.systemui.SysuiTestCase @@ -55,8 +56,10 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class InternetTileViewModelTest : SysuiTestCase() { private lateinit var underTest: InternetTileViewModel private lateinit var mobileIconsInteractor: MobileIconsInteractor diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt index ba035bec340c..eb6b068ca8a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.wifi.shared.model import android.net.wifi.WifiManager.UNKNOWN_SSID import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableRowLogger @@ -25,8 +26,10 @@ import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkMode import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Companion.MIN_VALID_LEVEL import com.google.common.truth.Truth.assertThat import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class WifiNetworkModelTest : SysuiTestCase() { @Test fun active_levelsInValidRange_noException() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java index 9ab64d650e60..93071bd9305a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java @@ -43,6 +43,7 @@ import android.platform.test.flag.junit.FlagsParameterization; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.settingslib.bluetooth.BluetoothEventManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java index 6894e6c304d0..59b20c824739 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java @@ -13,9 +13,9 @@ import android.content.pm.PackageManager; import android.media.MediaRouter; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper public class CastControllerImplTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt index 22c72cc495b1..7549a7fa0499 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt @@ -16,12 +16,12 @@ package com.android.systemui.statusbar.policy -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View.MeasureSpec.UNSPECIFIED import android.view.View.MeasureSpec.makeMeasureSpec import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.LinearLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Before @@ -31,7 +31,7 @@ import com.google.common.truth.Truth.assertThat import org.junit.Test @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class ClockTest : SysuiTestCase() { private lateinit var clockView: Clock diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt index c606511456fe..f871d2748fc9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt @@ -18,9 +18,9 @@ package com.android.systemui.statusbar.policy import android.hardware.devicestate.DeviceState import android.hardware.devicestate.DeviceStateManager -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableResources +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED @@ -44,7 +44,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class DevicePostureControllerImplTest : SysuiTestCase() { private val useBaseStateDeviceState = SUPPORTED_POSTURES_SIZE diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt index 31bd57e777d1..649a4ab2b968 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt @@ -18,8 +18,8 @@ package com.android.systemui.statusbar.policy import android.os.Handler import android.provider.Settings -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -45,7 +45,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class DeviceProvisionedControllerImplTest : SysuiTestCase() { @@ -246,4 +246,4 @@ class DeviceProvisionedControllerImplTest : SysuiTestCase() { `when`(userTracker.userId).thenReturn(toUser) userTrackerCallbackCaptor.value.onUserChanged(toUser, mContext) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java index 683136d7af0f..f5efd6d5fdff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java @@ -23,10 +23,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.res.Configuration; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -51,7 +51,7 @@ import org.mockito.MockitoAnnotations; import java.util.Map; import java.util.function.Consumer; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @SmallTest public class ExtensionControllerImplTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java index 784fb71121d8..3721b0ed987a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java @@ -33,9 +33,9 @@ import android.net.TetheringManager; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.UserManager; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -57,7 +57,7 @@ import java.util.Collections; import java.util.concurrent.Executor; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper public class HotspotControllerImplTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt index 1250228e2d37..b7a35158fdf6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt @@ -16,12 +16,12 @@ package com.android.systemui.statusbar.policy -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.ViewUtils import android.view.LayoutInflater import android.view.View import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.res.R @@ -45,7 +45,7 @@ import org.mockito.MockitoAnnotations @SmallTest @TestableLooper.RunWithLooper -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { @Mock private lateinit var userSwitcherController: UserSwitcherController diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java index 3a086aec98ad..aed9af6df454 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java @@ -25,9 +25,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.biometrics.BiometricSourceType; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; @@ -54,7 +54,7 @@ import java.util.Random; @SmallTest @TestableLooper.RunWithLooper -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class KeyguardStateControllerTest extends SysuiTestCase { @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt index 635d63ed5eb2..750f0c68bf3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt @@ -15,8 +15,8 @@ package com.android.systemui.statusbar.policy import android.app.StatusBarManager import android.content.res.Configuration -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.res.R @@ -35,7 +35,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @RunWithLooper class RemoteInputQuickSettingsDisablerTest : SysuiTestCase() { @@ -134,4 +134,4 @@ class RemoteInputQuickSettingsDisablerTest : SysuiTestCase() { private fun shouldDisableQs(state: Int): Boolean { return state and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0 } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java index a9681e0a03f0..36e305244d18 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java @@ -22,10 +22,10 @@ import static junit.framework.Assert.assertTrue; import android.app.RemoteInput; import android.provider.DeviceConfig; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableResources; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; @@ -39,7 +39,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper @SmallTest public class SmartReplyConstantsTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java index ddd29c3f2803..637a0f16cd5d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java @@ -27,10 +27,10 @@ import android.app.NotificationManager; import android.os.Handler; import android.provider.Settings; import android.service.notification.ZenModeConfig; -import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -51,7 +51,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) @RunWithLooper public class ZenModeControllerImplTest extends SysuiTestCase { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt index 6f40f15ca00a..94f0d196fa21 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepositoryImplTest.kt @@ -15,6 +15,7 @@ package com.android.systemui.statusbar.policy.bluetooth import android.bluetooth.BluetoothProfile +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.LocalBluetoothAdapter @@ -30,11 +31,13 @@ import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.TestScope import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest +@RunWith(AndroidJUnit4::class) class BluetoothRepositoryImplTest : SysuiTestCase() { private lateinit var underTest: BluetoothRepositoryImpl diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt index dbb106264ecd..8981009c14a8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.policy.domain.interactor import android.app.NotificationManager.Policy import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysUITestComponent import com.android.systemui.SysUITestModule @@ -32,8 +33,10 @@ import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class ZenModeInteractorTest : SysuiTestCase() { @SysUISingleton @Component( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt index 8576d4f56906..03a25e3d9ce3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt @@ -21,18 +21,21 @@ import android.app.StatusBarManager.WINDOW_NAVIGATION_BAR import android.app.StatusBarManager.WINDOW_STATE_HIDDEN import android.app.StatusBarManager.WINDOW_STATE_SHOWING import android.app.StatusBarManager.WINDOW_STATUS_BAR +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.CommandQueue import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class StatusBarWindowStateControllerTest : SysuiTestCase() { private lateinit var controller: StatusBarWindowStateController private lateinit var callback: CommandQueue.Callbacks diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt index 16132ba7cff5..32ef501cd9e3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/glowboxeffect/GlowBoxEffectTest.kt @@ -18,8 +18,8 @@ package com.android.systemui.surfaceeffects.glowboxeffect import android.graphics.Color import android.graphics.Paint -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.AnimatorTestRule @@ -31,7 +31,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class GlowBoxEffectTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt index 41d7fd54902d..67a42196d2e2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt @@ -18,8 +18,8 @@ package com.android.systemui.surfaceeffects.loadingeffect import android.graphics.Paint import android.graphics.RenderEffect -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.AnimatorTestRule @@ -33,7 +33,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class LoadingEffectTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt index 0d19ab1db390..a5afe1e33169 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/MultiRippleControllerTest.kt @@ -17,7 +17,7 @@ package com.android.systemui.surfaceeffects.ripple import android.graphics.Color -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.surfaceeffects.ripple.MultiRippleController.Companion.MAX_RIPPLE_NUMBER @@ -29,7 +29,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class MultiRippleControllerTest : SysuiTestCase() { private lateinit var multiRippleController: MultiRippleController private lateinit var multiRippleView: MultiRippleView diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt index 74ed7fb2c699..8dafa824cb8c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt @@ -17,8 +17,8 @@ package com.android.systemui.surfaceeffects.ripple import android.graphics.Color -import android.testing.AndroidTestingRunner import androidx.core.graphics.ColorUtils +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.concurrency.FakeExecutor @@ -28,7 +28,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class RippleAnimationTest : SysuiTestCase() { private val fakeSystemClock = FakeSystemClock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt index 89cc18cc5d67..2fee2a4553b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt @@ -15,7 +15,7 @@ */ package com.android.systemui.surfaceeffects.ripple -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -24,7 +24,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class RippleShaderTest : SysuiTestCase() { private lateinit var rippleShader: RippleShader diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt index 1e5ab7e25599..18644ab67351 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleViewTest.kt @@ -15,7 +15,7 @@ */ package com.android.systemui.surfaceeffects.ripple -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Before @@ -23,7 +23,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class RippleViewTest : SysuiTestCase() { private lateinit var rippleView: RippleView diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt index f1fadf6f1a4a..fbd3eae59046 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SolidColorShaderTest.kt @@ -16,14 +16,14 @@ package com.android.systemui.surfaceeffects.shaders import android.graphics.Color -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class SolidColorShaderTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt index 64ea6a68a518..d32bffbdff1d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/shaders/SparkleShaderTest.kt @@ -16,14 +16,14 @@ package com.android.systemui.surfaceeffects.shaders import android.graphics.Color -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class SparkleShaderTest : SysuiTestCase() { private lateinit var sparkleShader: SparkleShader diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt index 08b49f026523..4ba64384a186 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt @@ -16,9 +16,9 @@ package com.android.systemui.surfaceeffects.turbulencenoise import android.graphics.Color -import android.testing.AndroidTestingRunner import android.view.View.INVISIBLE import android.view.View.VISIBLE +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.EASE_IN @@ -33,7 +33,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class TurbulenceNoiseControllerTest : SysuiTestCase() { private val fakeSystemClock = FakeSystemClock() // FakeExecutor is needed to run animator. diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt index e62ca645d772..286f01736497 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt @@ -15,7 +15,7 @@ */ package com.android.systemui.surfaceeffects.turbulencenoise -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE @@ -25,7 +25,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class TurbulenceNoiseShaderTest : SysuiTestCase() { private lateinit var turbulenceNoiseShader: TurbulenceNoiseShader diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt index 953071cb0a02..e09d4ea9bcc6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.surfaceeffects.turbulencenoise import android.graphics.Color -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE @@ -28,7 +28,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class TurbulenceNoiseViewTest : SysuiTestCase() { private val fakeSystemClock = FakeSystemClock() diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt index ae4dfbd6ab31..bb6ba46f1a0b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt @@ -23,6 +23,7 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.view.accessibility.AccessibilityManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.testing.UiEventLoggerFake @@ -44,6 +45,7 @@ import com.android.systemui.util.wakelock.WakeLockFake import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.reset @@ -53,6 +55,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class TemporaryViewDisplayControllerTest : SysuiTestCase() { private lateinit var underTest: TestController diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt index 38c1a785d1e9..1dfd9343d185 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.temporarydisplay +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase @@ -28,9 +29,11 @@ import java.io.PrintWriter import java.io.StringWriter import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.Mockito @SmallTest +@RunWith(AndroidJUnit4::class) class TemporaryViewLoggerTest : SysuiTestCase() { private lateinit var buffer: LogBuffer private lateinit var logger: TemporaryViewLogger<TemporaryViewInfo> diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewUiEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewUiEventLoggerTest.kt index f707a8dafeda..281ecfb473cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewUiEventLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewUiEventLoggerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.temporarydisplay +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.testing.UiEventLoggerFake @@ -23,8 +24,10 @@ import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class TemporaryViewUiEventLoggerTest : SysuiTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: TemporaryViewUiEventLogger diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt index 7586fe48b308..a230f0630d6e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TouchableRegionViewControllerTest.kt @@ -19,12 +19,14 @@ package com.android.systemui.temporarydisplay import android.graphics.Rect import android.view.View import android.view.ViewTreeObserver +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.verify @@ -32,6 +34,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest +@RunWith(AndroidJUnit4::class) class TouchableRegionViewControllerTest : SysuiTestCase() { @Mock private lateinit var view: View diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt index c539246d4902..75d031dcaf38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.temporarydisplay.chipbar import android.graphics.Rect import android.view.MotionEvent import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer import com.android.systemui.SysuiTestCase @@ -29,8 +30,10 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest +@RunWith(AndroidJUnit4::class) class SwipeChipbarAwayGestureHandlerTest : SysuiTestCase() { private lateinit var underTest: SwipeChipbarAwayGestureHandler diff --git a/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java b/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java index 683397e4190e..bb7b31b95f5e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/tuner/TunablePaddingTest.java @@ -26,14 +26,17 @@ import android.util.DisplayMetrics; import android.view.View; import android.view.WindowManager; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; @SmallTest +@RunWith(AndroidJUnit4.class) public class TunablePaddingTest extends LeakCheckedTest { private static final String KEY = "KEY"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt index 2cdc8d8ffc84..5d850d82d806 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt @@ -18,7 +18,7 @@ package com.android.systemui.unfold import android.content.Context import android.content.res.Resources -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.R import com.android.systemui.SysuiTestCase @@ -65,7 +65,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { private lateinit var displaySwitchLatencyTracker: DisplaySwitchLatencyTracker diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt index e1797c445a70..c29b86c1fa37 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt @@ -19,9 +19,9 @@ package com.android.systemui.unfold import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager.FoldStateListener import android.os.PowerManager -import android.testing.AndroidTestingRunner import android.view.ViewGroup import android.view.ViewTreeObserver +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.util.LatencyTracker import com.android.systemui.SysuiTestCase @@ -56,7 +56,7 @@ import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class FoldAodAnimationControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt index a56507af6575..266a60dfb6e9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldLightRevealOverlayAnimationTest.kt @@ -18,8 +18,8 @@ package com.android.systemui.unfold import android.os.PowerManager import android.os.SystemProperties -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.foldables.FoldLockSettingAvailabilityProvider import com.android.internal.jank.Cuj.CUJ_FOLD_ANIM @@ -58,7 +58,7 @@ import org.mockito.kotlin.whenever @SmallTest @TestableLooper.RunWithLooper(setAsMainLooper = true) -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @OptIn(ExperimentalCoroutinesApi::class) class FoldLightRevealOverlayAnimationTest : SysuiTestCase() { @get:Rule val animatorTestRule = AnimatorTestRule(this) diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt index 39e4e6446d02..459b3e0dd0fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.unfold -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.FoldStateLoggingProvider.FoldStateLoggingListener @@ -34,7 +34,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class FoldStateLoggingProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt index ab779a75518e..448b63e88b60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateRepositoryTest.kt @@ -15,7 +15,7 @@ */ package com.android.systemui.unfold -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -38,7 +38,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class FoldStateRepositoryTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt index 06f1a8848fad..208e39c7f255 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt @@ -18,7 +18,7 @@ package com.android.systemui.unfold import android.os.VibrationAttributes import android.os.VibrationEffect import android.os.vibrator -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.testKosmos @@ -30,7 +30,7 @@ import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class UnfoldHapticsPlayerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt index 2955384c0bbd..1e5929daf9c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt @@ -19,7 +19,7 @@ package com.android.systemui.unfold import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager.FoldStateListener import android.provider.Settings -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.util.LatencyTracker import com.android.systemui.SysuiTestCase @@ -39,7 +39,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class UnfoldLatencyTrackerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt index 0c452eb9d461..b5282eb7ab03 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt @@ -1,6 +1,6 @@ package com.android.systemui.unfold -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.WallpaperController @@ -13,7 +13,7 @@ import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class UnfoldTransitionWallpaperControllerTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt index 3c539979c527..b48a6da3eee7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt @@ -14,7 +14,7 @@ */ package com.android.systemui.unfold.config -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -28,7 +28,7 @@ import org.junit.runner.RunWith * Internal Android resource constants are not available in public APIs, * so we can't use them there directly. */ -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class ResourceUnfoldTransitionConfigTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt index e5f619b299a1..61f0abb0e476 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/MainThreadUnfoldTransitionProgressProviderTest.kt @@ -19,8 +19,8 @@ package com.android.systemui.unfold.progress import android.os.Handler import android.os.HandlerThread import android.os.Looper -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.FakeUnfoldTransitionProvider @@ -29,7 +29,7 @@ import kotlin.test.Test import kotlinx.coroutines.test.runTest import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @RunWithLooper(setAsMainLooper = true) class MainThreadUnfoldTransitionProgressProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt index 14fb054a1d9d..97688d55b778 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt @@ -17,7 +17,7 @@ package com.android.systemui.unfold.progress import android.os.Handler import android.os.HandlerThread -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.UnfoldTransitionProgressProvider @@ -33,7 +33,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/RemoteUnfoldTransitionReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/RemoteUnfoldTransitionReceiverTest.kt index 4989a21791fb..a7b67e21ca4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/RemoteUnfoldTransitionReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/RemoteUnfoldTransitionReceiverTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.unfold.progress -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.systemui.SysuiTestCase @@ -24,7 +24,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class RemoteUnfoldTransitionReceiverTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt index 70eadcee7607..b93c161a7039 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/UnfoldRemoteFilterTest.kt @@ -16,7 +16,7 @@ package com.android.systemui.unfold.progress -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.systemui.SysuiTestCase @@ -25,7 +25,7 @@ import kotlin.time.Duration.Companion.milliseconds import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class UnfoldRemoteFilterTest : SysuiTestCase() { private val listener = TestUnfoldProgressListener() diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt index 552b60cbeb21..21a45ecb5922 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt @@ -21,8 +21,8 @@ import android.content.res.Configuration import android.content.res.Resources import android.os.Handler import android.os.Looper -import android.testing.AndroidTestingRunner import androidx.core.util.Consumer +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig @@ -50,7 +50,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class DeviceFoldStateProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceStateRepositoryTest.kt index 4eb159103b49..4d9c80fe7295 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceStateRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceStateRepositoryTest.kt @@ -15,7 +15,7 @@ */ package com.android.systemui.unfold.updates -import android.testing.AndroidTestingRunner +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -32,7 +32,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.verify -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest class DeviceStateRepositoryTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt index eaef0073b6fb..f5bcc21056e8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt @@ -21,9 +21,9 @@ import android.hardware.display.DisplayManager import android.os.HandlerThread import android.os.Looper import android.os.Process -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.Display +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener @@ -41,7 +41,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @RunWithLooper class RotationChangeProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt index 70ec050afe1d..8d892ed8efbe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt @@ -15,9 +15,9 @@ */ package com.android.systemui.unfold.util -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.Surface +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.FakeUnfoldTransitionProvider @@ -36,7 +36,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class NaturalRotationUnfoldProgressProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt index 451bd24dd83f..39977c790080 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt @@ -18,8 +18,8 @@ package com.android.systemui.unfold.util import android.content.ContentResolver import android.database.ContentObserver import android.provider.Settings -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.FakeUnfoldTransitionProvider @@ -35,7 +35,7 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class ScaleAwareUnfoldProgressProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt index 4486402f43ec..6e0bff21e2df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProviderTest.kt @@ -19,8 +19,8 @@ package com.android.systemui.unfold.util import android.os.Handler import android.os.HandlerThread import android.os.Process -import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.FakeUnfoldTransitionProvider @@ -38,7 +38,7 @@ import org.junit.Assert.assertThrows import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @RunWithLooper class ScopedUnfoldTransitionProgressProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt index cd4d7b54916e..0cbe1bafbcb7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/UnfoldOnlyProgressProviderTest.kt @@ -15,8 +15,8 @@ */ package com.android.systemui.unfold.util -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.unfold.FakeUnfoldTransitionProvider @@ -26,7 +26,7 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class UnfoldOnlyProgressProviderTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt index b04eb01201fa..32c598612aa6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt @@ -20,9 +20,9 @@ import android.content.Intent import android.hardware.usb.IUsbSerialReader import android.hardware.usb.UsbAccessory import android.hardware.usb.UsbManager -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.rule.ActivityTestRule import com.android.systemui.SysuiTestCase @@ -40,7 +40,7 @@ import org.junit.runner.RunWith /** * UsbPermissionActivityTest */ -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class UsbPermissionActivityTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt index 6db35ae94a3f..84cd79d9c8dc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt @@ -1,9 +1,9 @@ package com.android.systemui.user import android.app.Dialog -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.any @@ -15,7 +15,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class CreateUserActivityTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt index 35f9c417abd3..a29114007895 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt @@ -3,8 +3,8 @@ package com.android.systemui.user import android.content.pm.UserInfo import android.graphics.Bitmap import android.os.UserManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase import com.android.systemui.util.concurrency.FakeExecutor @@ -22,7 +22,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class UserCreatorTest : SysuiTestCase() { companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt index 0669cb8b8ba5..37a73cf62929 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt @@ -21,6 +21,7 @@ import android.content.pm.UserInfo import android.os.UserHandle import android.os.UserManager import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.settings.FakeUserTracker @@ -41,7 +42,6 @@ import kotlinx.coroutines.test.TestCoroutineScope import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.Mock import org.mockito.Mockito.mock import org.mockito.Mockito.`when` as whenever @@ -49,7 +49,7 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class UserRepositoryImplTest : SysuiTestCase() { @Mock private lateinit var manager: UserManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt index 01795e92d141..20b273ae7f4e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt @@ -22,6 +22,7 @@ import android.content.Context import android.content.pm.UserInfo import android.os.UserHandle import android.os.UserManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.GuestResetOrExitSessionReceiver @@ -39,7 +40,6 @@ import kotlinx.coroutines.test.TestCoroutineScope import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito.never @@ -47,7 +47,7 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class GuestUserInteractorTest : SysuiTestCase() { @Mock private lateinit var manager: UserManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt index b30f77a663af..59ad38a87146 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/RefreshUsersSchedulerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.user.domain.interactor +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.user.data.repository.FakeUserRepository @@ -26,11 +27,10 @@ import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.MockitoAnnotations @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class RefreshUsersSchedulerTest : SysuiTestCase() { private lateinit var underTest: RefreshUsersScheduler diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt index 140e919d613f..78028f819fa0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt @@ -1,6 +1,7 @@ package com.android.systemui.user.domain.interactor import android.content.pm.UserInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER import com.android.systemui.SysuiTestCase @@ -10,10 +11,9 @@ import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class SelectedUserInteractorTest : SysuiTestCase() { private lateinit var underTest: SelectedUserInteractor diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt index 96c6eb8107df..ccbdffa03cbf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt @@ -28,6 +28,7 @@ import android.os.Process import android.os.UserHandle import android.os.UserManager import android.provider.Settings +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.keyguard.KeyguardUpdateMonitor @@ -75,7 +76,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyInt @@ -89,7 +89,7 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class UserSwitcherInteractorTest : SysuiTestCase() { @Mock private lateinit var activityStarter: ActivityStarter diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt index 661837bdb1e4..99cdf731a765 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt @@ -23,6 +23,7 @@ import android.content.pm.UserInfo import android.graphics.Bitmap import android.graphics.drawable.BitmapDrawable import android.os.UserManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.keyguard.KeyguardUpdateMonitor @@ -60,7 +61,6 @@ import kotlinx.coroutines.yield import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito.doAnswer @@ -68,7 +68,7 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class StatusBarUserChipViewModelTest : SysuiTestCase() { @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var activityManager: ActivityManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt index 5661e202d134..917df619467d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt @@ -21,6 +21,7 @@ import android.app.ActivityManager import android.app.admin.DevicePolicyManager import android.content.pm.UserInfo import android.os.UserManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.keyguard.KeyguardUpdateMonitor @@ -62,13 +63,12 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.Mock import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(JUnit4::class) +@RunWith(AndroidJUnit4::class) class UserSwitcherViewModelTest : SysuiTestCase() { @Mock private lateinit var activityStarter: ActivityStarter diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt index 8bfff9c209e2..b3f2113f86ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.util.kotlin import android.content.ComponentName import android.content.pm.ComponentInfo import android.content.pm.PackageManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.util.mockito.mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java index df08efaf16d2..c896fc0bfb8a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/AsyncSensorManagerTest.java @@ -23,8 +23,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import android.hardware.SensorEventListener; -import android.testing.AndroidTestingRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -39,7 +39,7 @@ import org.junit.Test; import org.junit.runner.RunWith; @SmallTest -@RunWith(AndroidTestingRunner.class) +@RunWith(AndroidJUnit4.class) public class AsyncSensorManagerTest extends SysuiTestCase { private AsyncSensorManager mAsyncSensorManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt index eb11e383d519..ef8d51a23dc2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/SettingsProxyTest.kt @@ -22,8 +22,8 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.provider.Settings.SettingNotFoundException -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat @@ -36,7 +36,7 @@ import org.mockito.Mockito.verify import org.mockito.kotlin.eq /** Tests for [SettingsProxy]. */ -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class SettingsProxyTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt index 38469ee7955d..c08ca7d1bdc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt @@ -23,8 +23,8 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.provider.Settings -import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.settings.FakeUserTracker @@ -39,7 +39,7 @@ import org.mockito.Mockito.verify import org.mockito.kotlin.eq /** Tests for [UserSettingsProxy]. */ -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) @SmallTest @TestableLooper.RunWithLooper class UserSettingsProxyTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt index 7d89a559f12f..bdecf2bdb53d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt @@ -20,6 +20,7 @@ import android.app.WallpaperInfo import android.app.WallpaperManager import android.content.Intent import android.content.pm.UserInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue @@ -37,9 +38,11 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.junit.runner.RunWith @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class WallpaperRepositoryImplTest : SysuiTestCase() { private val testDispatcher = StandardTestDispatcher() diff --git a/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt b/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt index 21dea6b1cbd0..2ee289bd026d 100644 --- a/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt +++ b/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt @@ -18,6 +18,8 @@ package android.view import android.content.applicationContext import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock var Kosmos.layoutInflater: LayoutInflater by Kosmos.Fixture { LayoutInflater.from(applicationContext) } +var Kosmos.mockedLayoutInflater: LayoutInflater by Kosmos.Fixture { mock<LayoutInflater>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt index f75cdd4d3bbc..9236bd2a2a8b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt @@ -20,6 +20,7 @@ import com.android.keyguard.keyguardUpdateMonitor import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor +import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.data.repository.biometricSettingsRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor @@ -28,6 +29,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.statusbar.policy.keyguardStateController +import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.systemClock val Kosmos.alternateBouncerInteractor: AlternateBouncerInteractor by @@ -47,3 +49,24 @@ val Kosmos.alternateBouncerInteractor: AlternateBouncerInteractor by sceneInteractor = { sceneInteractor }, ) } + +fun Kosmos.givenCanShowAlternateBouncer() { + this.givenAlternateBouncerSupported() + this.keyguardBouncerRepository.setPrimaryShow(false) + this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true) + this.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true) + whenever(this.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false) + whenever(this.keyguardStateController.isUnlocked).thenReturn(false) +} + +fun Kosmos.givenAlternateBouncerSupported() { + if (DeviceEntryUdfpsRefactor.isEnabled) { + this.fingerprintPropertyRepository.supportsUdfps() + } else { + this.keyguardBouncerRepository.setAlternateBouncerUIAvailable(true) + } +} + +fun Kosmos.givenCannotShowAlternateBouncer() { + this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalPrefsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalPrefsRepository.kt index d3ed58bf5be0..1da1fb2ee52f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalPrefsRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalPrefsRepository.kt @@ -17,16 +17,28 @@ package com.android.systemui.communal.data.repository +import android.content.pm.UserInfo import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.map /** Fake implementation of [CommunalPrefsRepository] */ class FakeCommunalPrefsRepository : CommunalPrefsRepository { - private val _isCtaDismissed = MutableStateFlow(false) - override val isCtaDismissed: Flow<Boolean> = _isCtaDismissed.asStateFlow() + private val _isCtaDismissed = MutableStateFlow<Set<UserInfo>>(emptySet()) + private val _isDisclaimerDismissed = MutableStateFlow<Set<UserInfo>>(emptySet()) - override suspend fun setCtaDismissedForCurrentUser() { - _isCtaDismissed.value = true + override fun isCtaDismissed(user: UserInfo): Flow<Boolean> = + _isCtaDismissed.map { it.contains(user) } + + override fun isDisclaimerDismissed(user: UserInfo): Flow<Boolean> = + _isDisclaimerDismissed.map { it.contains(user) } + + override suspend fun setCtaDismissed(user: UserInfo) { + _isCtaDismissed.value = _isCtaDismissed.value.toMutableSet().apply { add(user) } + } + + override suspend fun setDisclaimerDismissed(user: UserInfo) { + _isDisclaimerDismissed.value = + _isDisclaimerDismissed.value.toMutableSet().apply { add(user) } } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt index 1583d1c5d83f..b58861b1104e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt @@ -19,7 +19,6 @@ package com.android.systemui.communal.domain.interactor import android.os.userManager import com.android.systemui.broadcast.broadcastDispatcher import com.android.systemui.communal.data.repository.communalMediaRepository -import com.android.systemui.communal.data.repository.communalPrefsRepository import com.android.systemui.communal.data.repository.communalWidgetRepository import com.android.systemui.communal.widgets.EditWidgetsActivityStarter import com.android.systemui.flags.Flags @@ -46,7 +45,7 @@ val Kosmos.communalInteractor by Fixture { broadcastDispatcher = broadcastDispatcher, communalSceneInteractor = communalSceneInteractor, widgetRepository = communalWidgetRepository, - communalPrefsRepository = communalPrefsRepository, + communalPrefsInteractor = communalPrefsInteractor, mediaRepository = communalMediaRepository, smartspaceRepository = smartspaceRepository, keyguardInteractor = keyguardInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractorKosmos.kt new file mode 100644 index 000000000000..37563c4d4eeb --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalPrefsInteractorKosmos.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import com.android.systemui.communal.data.repository.communalPrefsRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.settings.userTracker +import com.android.systemui.user.domain.interactor.selectedUserInteractor +import com.android.systemui.util.mockito.mock + +var Kosmos.communalPrefsInteractor: CommunalPrefsInteractor by + Kosmos.Fixture { + CommunalPrefsInteractor( + applicationCoroutineScope, + communalPrefsRepository, + selectedUserInteractor, + userTracker, + tableLogBuffer = mock() + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt new file mode 100644 index 000000000000..6eb8a4925082 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.binder + +import android.content.applicationContext +import android.view.layoutInflater +import android.view.mockedLayoutInflater +import android.view.windowManager +import com.android.systemui.biometrics.domain.interactor.fingerprintPropertyInteractor +import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor +import com.android.systemui.common.ui.domain.interactor.configurationInteractor +import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor +import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel +import com.android.systemui.keyguard.ui.SwipeUpAnywhereGestureHandler +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerViewModel +import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel +import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerViewModel +import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerWindowViewModel +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.statusbar.gesture.TapGestureDetector +import com.android.systemui.util.mockito.mock +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@OptIn(ExperimentalCoroutinesApi::class) +val Kosmos.alternateBouncerViewBinder by + Kosmos.Fixture { + AlternateBouncerViewBinder( + applicationScope = applicationCoroutineScope, + alternateBouncerWindowViewModel = { alternateBouncerWindowViewModel }, + alternateBouncerDependencies = { alternateBouncerDependencies }, + windowManager = { windowManager }, + layoutInflater = { mockedLayoutInflater }, + ) + } + +private val Kosmos.alternateBouncerDependencies by + Kosmos.Fixture { + AlternateBouncerDependencies( + viewModel = mock<AlternateBouncerViewModel>(), + swipeUpAnywhereGestureHandler = mock<SwipeUpAnywhereGestureHandler>(), + tapGestureDetector = mock<TapGestureDetector>(), + udfpsIconViewModel = alternateBouncerUdfpsIconViewModel, + udfpsAccessibilityOverlayViewModel = { + mock<AlternateBouncerUdfpsAccessibilityOverlayViewModel>() + }, + messageAreaViewModel = mock<AlternateBouncerMessageAreaViewModel>(), + powerInteractor = powerInteractor, + ) + } + +private val Kosmos.alternateBouncerUdfpsIconViewModel by + Kosmos.Fixture { + AlternateBouncerUdfpsIconViewModel( + context = applicationContext, + configurationInteractor = configurationInteractor, + deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor, + deviceEntryBackgroundViewModel = mock<DeviceEntryBackgroundViewModel>(), + fingerprintPropertyInteractor = fingerprintPropertyInteractor, + udfpsOverlayInteractor = udfpsOverlayInteractor, + alternateBouncerViewModel = alternateBouncerViewModel, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt index 690bde7f5b47..7a04aa288dce 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt @@ -18,6 +18,7 @@ package com.android.systemui.media.controls.data.repository import android.content.applicationContext import com.android.systemui.kosmos.Kosmos +import com.android.systemui.media.controls.util.mediaSmartspaceLogger import com.android.systemui.statusbar.policy.configurationController import com.android.systemui.util.time.systemClock @@ -26,6 +27,7 @@ val Kosmos.mediaFilterRepository by MediaFilterRepository( applicationContext = applicationContext, systemClock = systemClock, - configurationController = configurationController + configurationController = configurationController, + smartspaceLogger = mediaSmartspaceLogger, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaSmartspaceLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaSmartspaceLoggerKosmos.kt new file mode 100644 index 000000000000..c63dec523228 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/util/MediaSmartspaceLoggerKosmos.kt @@ -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. + */ + +package com.android.systemui.media.controls.util + +import com.android.systemui.kosmos.Kosmos +import org.mockito.Mockito.mock + +var Kosmos.mediaSmartspaceLogger by Kosmos.Fixture { MediaSmartspaceLogger() } +val Kosmos.mockMediaSmartspaceLogger by Kosmos.Fixture { mock(MediaSmartspaceLogger::class.java) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt index 21d59f09711c..fcea9e7b2a3f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt @@ -42,6 +42,7 @@ class FakeAudioRepository : AudioRepository { private val models: MutableMap<AudioStream, MutableStateFlow<AudioStreamModel>> = mutableMapOf() private val lastAudibleVolumes: MutableMap<AudioStream, Int> = mutableMapOf() + private val deviceCategories: MutableMap<String, Int> = mutableMapOf() private fun getAudioStreamModelState( audioStream: AudioStream @@ -103,4 +104,12 @@ class FakeAudioRepository : AudioRepository { override suspend fun setRingerMode(audioStream: AudioStream, mode: RingerMode) { mutableRingerMode.value = mode } + + fun setBluetoothAudioDeviceCategory(bluetoothAddress: String, category: Int) { + deviceCategories[bluetoothAddress] = category + } + + override suspend fun getBluetoothAudioDeviceCategory(bluetoothAddress: String): Int { + return deviceCategories[bluetoothAddress] ?: AudioManager.AUDIO_DEVICE_CATEGORY_UNKNOWN + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorKosmos.kt index 95a7b9bb185b..6a46d56ba55a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractorKosmos.kt @@ -17,8 +17,10 @@ package com.android.systemui.volume.panel.component.spatial.domain.interactor import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.backgroundCoroutineContext import com.android.systemui.kosmos.testScope import com.android.systemui.media.spatializerInteractor +import com.android.systemui.volume.data.repository.audioRepository import com.android.systemui.volume.domain.interactor.audioOutputInteractor val Kosmos.spatialAudioComponentInteractor by @@ -26,6 +28,8 @@ val Kosmos.spatialAudioComponentInteractor by SpatialAudioComponentInteractor( audioOutputInteractor, spatializerInteractor, + audioRepository, + backgroundCoroutineContext, testScope.backgroundScope, ) } diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index 7f542d130cf7..e8db80a36f5b 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -310,6 +310,10 @@ message SystemMessage { // Package: android NOTE_USB_UVC = 75; + // Inform the user about adaptive notifications + // Package: com.android.systemui + NOTE_ADAPTIVE_NOTIFICATIONS = 76; + // ADD_NEW_IDS_ABOVE_THIS_LINE // Legacy IDs with arbitrary values appear below // Legacy IDs existed as stable non-conflicting constants prior to the O release diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java index 9747579fa231..2945af507d51 100644 --- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java +++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java @@ -34,6 +34,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.WindowManager; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import android.view.accessibility.Flags; import com.android.internal.R; import com.android.internal.accessibility.util.AccessibilityUtils; @@ -328,6 +329,18 @@ public class SystemActionPerformer { sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_CENTER, InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD); return true; + case AccessibilityService.GLOBAL_ACTION_MENU: + if (Flags.globalActionMenu()) { + sendDownAndUpKeyEvents(KeyEvent.KEYCODE_MENU, + InputDevice.SOURCE_KEYBOARD); + } + return true; + case AccessibilityService.GLOBAL_ACTION_MEDIA_PLAY_PAUSE: + if (Flags.globalActionMediaPlayPause()) { + sendDownAndUpKeyEvents(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, + InputDevice.SOURCE_KEYBOARD); + } + return true; default: Slog.e(TAG, "Invalid action id: " + actionId); return false; diff --git a/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java index 3fbd8560b82c..b3a2da40ff4d 100644 --- a/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java +++ b/services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java @@ -19,7 +19,6 @@ package com.android.server.companion.association; import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_ONE_SHOT; -import static android.companion.CompanionDeviceManager.REASON_INTERNAL_ERROR; import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR; import static android.content.ComponentName.createRelative; import static android.content.pm.PackageManager.FEATURE_WATCH; @@ -183,7 +182,7 @@ public class AssociationRequestsProcessor { String errorMessage = "3p apps are not allowed to create associations on watch."; Slog.e(TAG, errorMessage); try { - callback.onFailure(errorMessage); + callback.onFailure(RESULT_INTERNAL_ERROR); } catch (RemoteException e) { // ignored } @@ -252,8 +251,9 @@ public class AssociationRequestsProcessor { } catch (SecurityException e) { // Since, at this point the caller is our own UI, we need to catch the exception on // forward it back to the application via the callback. + Slog.e(TAG, e.getMessage()); try { - callback.onFailure(e.getMessage()); + callback.onFailure(RESULT_INTERNAL_ERROR); } catch (RemoteException ignore) { } return; @@ -378,7 +378,7 @@ public class AssociationRequestsProcessor { // Send the association back via the app's callback if (callback != null) { try { - callback.onFailure(REASON_INTERNAL_ERROR); + callback.onFailure(RESULT_INTERNAL_ERROR); } catch (RemoteException ignore) { } } diff --git a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java index ce4067cf3786..ef39846f4750 100644 --- a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java +++ b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java @@ -192,7 +192,8 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen for (UserInfo user : aliveUsers) { int userId = user.getUserHandle().getIdentifier(); int appUid = queryUidFromPackageName(userId, packageName); - if (mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(appUid)) { + if (mVirtualDeviceManagerInternal != null + && mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(appUid)) { if (data == null) { data = new InjectionSessionData(); data.appUid = appUid; diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java index cf4818060aa8..065568573558 100644 --- a/services/companion/java/com/android/server/companion/virtual/SensorController.java +++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java @@ -229,6 +229,10 @@ public class SensorController { Slog.e(TAG, "No sensor callback configured for sensor handle " + handle); return BAD_VALUE; } + if (mVdmInternal == null) { + Slog.e(TAG, "Virtual Device Manager is not enabled."); + return BAD_VALUE; + } VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, handle); if (sensor == null) { Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId @@ -285,6 +289,10 @@ public class SensorController { Slog.e(TAG, "No runtime sensor callback configured."); return BAD_VALUE; } + if (mVdmInternal == null) { + Slog.e(TAG, "Virtual Device Manager is not enabled."); + return BAD_VALUE; + } VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, sensorHandle); if (sensor == null) { Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 022df9a8dc81..195e94b00930 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -10235,19 +10235,6 @@ public class ActivityManagerService extends IActivityManager.Stub addStartInfoTimestampInternal(key, timestampNs, userId, callingUid); } - @Override - public void reportStartInfoViewTimestamps(long renderThreadDrawStartTimeNs, - long framePresentedTimeNs) { - int callingUid = Binder.getCallingUid(); - int userId = UserHandle.getUserId(callingUid); - addStartInfoTimestampInternal( - ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME, - renderThreadDrawStartTimeNs, userId, callingUid); - addStartInfoTimestampInternal( - ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE, - framePresentedTimeNs, userId, callingUid); - } - private void addStartInfoTimestampInternal(int key, long timestampNs, int userId, int uid) { mProcessList.getAppStartInfoTracker().addTimestampToStart( Settings.getPackageNameForUid(mContext, uid), diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java index 4a7ad31cba3e..3042b2a50d50 100644 --- a/services/core/java/com/android/server/am/AppStartInfoTracker.java +++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java @@ -1195,67 +1195,31 @@ public final class AppStartInfoTracker { // Records are sorted newest to oldest, grab record at index 0. ApplicationStartInfo startInfo = mInfos.get(0); - - if (!isAddTimestampAllowed(startInfo, key, timestampNs)) { - return; - } - - startInfo.addStartupTimestamp(key, timestampNs); - - if (key == ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME - && android.app.Flags.appStartInfoTimestamps()) { - startInfo.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN); - checkCompletenessAndCallback(startInfo); - } - } - - private boolean isAddTimestampAllowed(ApplicationStartInfo startInfo, int key, - long timestampNs) { int startupState = startInfo.getStartupState(); // If startup state is error then don't accept any further timestamps. if (startupState == ApplicationStartInfo.STARTUP_STATE_ERROR) { if (DEBUG) Slog.d(TAG, "Startup state is error, not accepting new timestamps."); - return false; + return; } - Map<Integer, Long> timestamps = startInfo.getStartupTimestamps(); - - if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN) { - switch (key) { - case ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN: - // Allowed, continue to confirm it's not already added. - break; - case ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME: - Long firstFrameTimeNs = timestamps - .get(ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME); - if (firstFrameTimeNs == null) { - // This should never happen. State can't be first frame drawn if first - // frame timestamp was not provided. - return false; - } - - if (timestampNs > firstFrameTimeNs) { - // Initial renderthread frame has to occur before first frame. - return false; - } - - // Allowed, continue to confirm it's not already added. - break; - case ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE: - // Allowed, continue to confirm it's not already added. - break; - default: - return false; + // If startup state is first frame drawn then only accept fully drawn timestamp. + if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN + && key != ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN) { + if (DEBUG) { + Slog.d(TAG, "Startup state is first frame drawn and timestamp is not fully " + + "drawn, not accepting new timestamps."); } + return; } - if (timestamps.get(key) != null) { - // Timestamp should not occur more than once for a given start. - return false; - } + startInfo.addStartupTimestamp(key, timestampNs); - return true; + if (key == ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME + && android.app.Flags.appStartInfoTimestamps()) { + startInfo.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN); + checkCompletenessAndCallback(startInfo); + } } @GuardedBy("mLock") diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java index 178171d49388..aeebae43d1ef 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java @@ -2482,7 +2482,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue { ipw.println(); if (dumpConstants) { - mConstants.dump(ipw); + mFgConstants.dump(ipw); + mBgConstants.dump(ipw); } if (dumpHistory) { diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index a8b9e43bdae4..4ff13679ed5c 100644 --- a/services/core/java/com/android/server/am/ContentProviderHelper.java +++ b/services/core/java/com/android/server/am/ContentProviderHelper.java @@ -674,7 +674,9 @@ public class ContentProviderHelper { if (conn != null) { conn.waiting = true; } - cpr.wait(wait); + if (wait > 0) { + cpr.wait(wait); + } if (cpr.provider == null) { timedOut = true; break; diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index fa0e2ca3b2d4..30efa3e87fc6 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -2335,6 +2335,14 @@ class UserController implements Handler.Callback { // Never stop system user return; } + synchronized(mLock) { + final UserState uss = mStartedUsers.get(oldUserId); + if (uss == null || uss.state == UserState.STATE_STOPPING + || uss.state == UserState.STATE_SHUTDOWN) { + // We've stopped (or are stopping) the user anyway, so don't bother scheduling. + return; + } + } if (oldUserId == mInjector.getUserManagerInternal().getMainUserId()) { // MainUser is currently special for things like Docking, so we'll exempt it for now. Slogf.i(TAG, "Exempting user %d from being stopped due to inactivity by virtue " @@ -2371,6 +2379,12 @@ class UserController implements Handler.Callback { // We'll soon want to switch to this user, so don't kill it now. return; } + final UserInfo currentOrTargetUser = getCurrentUserLU(); + if (currentOrTargetUser != null && currentOrTargetUser.isGuest()) { + // Don't kill any background users for the sake of a Guest. Just reschedule instead. + scheduleStopOfBackgroundUser(userId); + return; + } Slogf.i(TAG, "Stopping background user %d due to inactivity", userId); stopUsersLU(userId, /* allowDelayedLocking= */ true, null, null); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 1bb792227798..f61bd6040658 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2790,8 +2790,9 @@ public class AppOpsService extends IAppOpsService.Stub { * have information on them. */ private static boolean isOpAllowedForUid(int uid) { + int appId = UserHandle.getAppId(uid); return Flags.runtimePermissionAppopsMappingEnabled() - && (uid == Process.ROOT_UID || uid == Process.SYSTEM_UID); + && (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID); } @Override diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 0afca92d78f7..73aa14ba016f 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -251,7 +251,7 @@ public class ClipboardService extends SystemService { } private void registerVirtualDeviceListener() { - if (mVirtualDeviceListener != null) { + if (mVdm == null || mVirtualDeviceListener != null) { return; } mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() { @@ -891,7 +891,8 @@ public class ClipboardService extends SystemService { Slog.e(TAG, "RemoteException calling UserManager: " + e); return null; } - if (deviceId != DEVICE_ID_DEFAULT && !mVdm.isValidVirtualDeviceId(deviceId)) { + if (deviceId != DEVICE_ID_DEFAULT + && mVdm != null && !mVdm.isValidVirtualDeviceId(deviceId)) { Slog.w(TAG, "getClipboardLocked called with invalid (possibly released) deviceId " + deviceId); return null; @@ -1467,8 +1468,8 @@ public class ClipboardService extends SystemService { return; } // Don't notify if this access is coming from the privileged app which owns the device. - if (clipboard.deviceId != DEVICE_ID_DEFAULT && mVdmInternal.getDeviceOwnerUid( - clipboard.deviceId) == uid) { + if (clipboard.deviceId != DEVICE_ID_DEFAULT && mVdmInternal != null + && mVdmInternal.getDeviceOwnerUid(clipboard.deviceId) == uid) { return; } // Don't notify if already notified for this uid and clip. @@ -1519,7 +1520,7 @@ public class ClipboardService extends SystemService { private ArraySet<Context> getToastContexts(Clipboard clipboard) throws IllegalStateException { ArraySet<Context> contexts = new ArraySet<>(); - if (clipboard.deviceId != DEVICE_ID_DEFAULT) { + if (mVdmInternal != null && clipboard.deviceId != DEVICE_ID_DEFAULT) { DisplayManager displayManager = getContext().getSystemService(DisplayManager.class); int topFocusedDisplayId = mWm.getTopFocusedDisplayId(); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 2d5f38e2dd8c..e686779e4ccd 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -1548,16 +1548,20 @@ public final class DisplayManagerService extends SystemService { int flags = virtualDisplayConfig.getFlags(); if (virtualDevice != null) { final VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); - try { - if (!vdm.isValidVirtualDeviceId(virtualDevice.getDeviceId())) { - throw new SecurityException("Invalid virtual device"); + if (vdm != null) { + try { + if (!vdm.isValidVirtualDeviceId(virtualDevice.getDeviceId())) { + throw new SecurityException("Invalid virtual device"); + } + } catch (RemoteException ex) { + throw new SecurityException("Unable to validate virtual device"); + } + final VirtualDeviceManagerInternal localVdm = + getLocalService(VirtualDeviceManagerInternal.class); + if (localVdm != null) { + flags |= localVdm.getBaseVirtualDisplayFlags(virtualDevice); } - } catch (RemoteException ex) { - throw new SecurityException("Unable to validate virtual device"); } - final VirtualDeviceManagerInternal localVdm = - getLocalService(VirtualDeviceManagerInternal.class); - flags |= localVdm.getBaseVirtualDisplayFlags(virtualDevice); } if (surface != null && surface.isSingleBuffered()) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 65a729a0293e..d14f2a0c85ed 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -587,7 +587,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mUniqueDisplayId, mThermalBrightnessThrottlingDataId, logicalDisplay.getPowerThrottlingDataIdLocked(), - mDisplayDeviceConfig), mContext, flags, mSensorManager); + mDisplayDeviceConfig, + mDisplayId), mContext, flags, mSensorManager); // Seed the cached brightness saveBrightnessInfo(getScreenBrightnessSetting()); mAutomaticBrightnessStrategy = @@ -892,7 +893,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // will call updatePowerState if needed. mBrightnessClamperController.onDisplayChanged( new BrightnessClamperController.DisplayDeviceData(uniqueId, - thermalBrightnessThrottlingDataId, powerThrottlingDataId, config)); + thermalBrightnessThrottlingDataId, powerThrottlingDataId, + config, mDisplayId)); if (changed) { updatePowerState(); diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index 101ad307f50a..220640270e02 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -23,23 +23,17 @@ import static com.android.server.display.brightness.clamper.BrightnessClamper.Ty import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.content.res.Resources; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.BrightnessInfo; import android.hardware.display.DisplayManagerInternal; import android.os.Handler; import android.os.HandlerExecutor; import android.os.PowerManager; -import android.os.SystemClock; import android.provider.DeviceConfig; import android.provider.DeviceConfigInterface; import android.util.IndentingPrintWriter; import android.util.Slog; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.DisplayBrightnessState; import com.android.server.display.DisplayDeviceConfig; @@ -50,30 +44,22 @@ import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.config.SensorData; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.feature.DisplayManagerFlags; -import com.android.server.display.utils.AmbientFilter; -import com.android.server.display.utils.AmbientFilterFactory; -import com.android.server.display.utils.DebugUtils; -import com.android.server.display.utils.SensorUtils; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; /** * Clampers controller, all in DisplayControllerHandler */ public class BrightnessClamperController { private static final String TAG = "BrightnessClamperController"; - // To enable these logs, run: - // 'adb shell setprop persist.log.tag.BrightnessClamperController DEBUG && adb reboot' - private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); - public static final float INVALID_LUX = -1f; private final DeviceConfigParameterProvider mDeviceConfigParameterProvider; private final Handler mHandler; - private final SensorManager mSensorManager; + private final LightSensorController mLightSensorController; + private final ClamperChangeListener mClamperChangeListenerExternal; private final Executor mExecutor; private final List<BrightnessClamper<? super DisplayDeviceData>> mClampers; @@ -85,70 +71,49 @@ public class BrightnessClamperController { private float mCustomAnimationRate = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; @Nullable private Type mClamperType = null; - private final SensorEventListener mLightSensorListener; - private Sensor mRegisteredLightSensor = null; - private Sensor mLightSensor; - private String mLightSensorType; - private String mLightSensorName; - private AmbientFilter mAmbientFilter; - private final DisplayDeviceConfig mDisplayDeviceConfig; - private final Resources mResources; - private final int mLightSensorRate; - - private final Injector mInjector; + private boolean mClamperApplied = false; + private final LightSensorController.LightSensorListener mLightSensorListener = + new LightSensorController.LightSensorListener() { + @Override + public void onAmbientLuxChange(float lux) { + mModifiers.forEach(mModifier -> mModifier.setAmbientLux(lux)); + } + }; + public BrightnessClamperController(Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { - this(null, handler, clamperChangeListener, data, context, flags, sensorManager); + this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager); } @VisibleForTesting BrightnessClamperController(Injector injector, Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { - mInjector = injector == null ? new Injector() : injector; - mDeviceConfigParameterProvider = mInjector.getDeviceConfigParameterProvider(); + mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler = handler; - mSensorManager = sensorManager; - mDisplayDeviceConfig = data.mDisplayDeviceConfig; - mLightSensorListener = new SensorEventListener() { - @Override - public void onSensorChanged(SensorEvent event) { - long now = SystemClock.elapsedRealtime(); - mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp), - event.values[0]); - final float lux = mAmbientFilter.getEstimate(now); - mModifiers.forEach(mModifier -> mModifier.setAmbientLux(lux)); - } - - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - // unused - } - }; + mLightSensorController = injector.getLightSensorController(sensorManager, context, + mLightSensorListener, mHandler); mClamperChangeListenerExternal = clamperChangeListener; mExecutor = new HandlerExecutor(handler); - mResources = context.getResources(); - mLightSensorRate = context.getResources().getInteger( - R.integer.config_autoBrightnessLightSensorRate); Runnable clamperChangeRunnableInternal = this::recalculateBrightnessCap; - ClamperChangeListener clamperChangeListenerInternal = () -> { if (!mHandler.hasCallbacks(clamperChangeRunnableInternal)) { mHandler.post(clamperChangeRunnableInternal); } }; - mClampers = mInjector.getClampers(handler, clamperChangeListenerInternal, data, flags, + mClampers = injector.getClampers(handler, clamperChangeListenerInternal, data, flags, context); - mModifiers = mInjector.getModifiers(flags, context, handler, clamperChangeListener, - data.mDisplayDeviceConfig, mSensorManager); + mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListener, + data.mDisplayDeviceConfig); mOnPropertiesChangedListener = properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged); + mLightSensorController.configure(data.getAmbientLightSensor(), data.getDisplayId()); start(); } @@ -156,7 +121,9 @@ public class BrightnessClamperController { * Should be called when display changed. Forwards the call to individual clampers */ public void onDisplayChanged(DisplayDeviceData data) { + mLightSensorController.configure(data.getAmbientLightSensor(), data.getDisplayId()); mClampers.forEach(clamper -> clamper.onDisplayChanged(data)); + adjustLightSensorSubscription(); } /** @@ -184,9 +151,9 @@ public class BrightnessClamperController { } if (displayState != STATE_ON) { - unregisterSensorListener(); + mLightSensorController.stop(); } else { - maybeRegisterLightSensor(); + adjustLightSensorSubscription(); } for (int i = 0; i < mModifiers.size(); i++) { @@ -231,9 +198,8 @@ public class BrightnessClamperController { writer.println(" mBrightnessCap: " + mBrightnessCap); writer.println(" mClamperType: " + mClamperType); writer.println(" mClamperApplied: " + mClamperApplied); - writer.println(" mLightSensor=" + mLightSensor); - writer.println(" mRegisteredLightSensor=" + mRegisteredLightSensor); IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " "); + mLightSensorController.dump(ipw); mClampers.forEach(clamper -> clamper.dump(ipw)); mModifiers.forEach(modifier -> modifier.dump(ipw)); } @@ -245,6 +211,7 @@ public class BrightnessClamperController { public void stop() { mDeviceConfigParameterProvider.removeOnPropertiesChangedListener( mOnPropertiesChangedListener); + mLightSensorController.stop(); mClampers.forEach(BrightnessClamper::stop); mModifiers.forEach(BrightnessStateModifier::stop); } @@ -281,10 +248,15 @@ public class BrightnessClamperController { if (!mClampers.isEmpty()) { mDeviceConfigParameterProvider.addOnPropertiesChangedListener( mExecutor, mOnPropertiesChangedListener); - reloadLightSensorData(mDisplayDeviceConfig); - mLightSensor = mInjector.getLightSensor( - mSensorManager, mLightSensorType, mLightSensorName); - maybeRegisterLightSensor(); + } + adjustLightSensorSubscription(); + } + + private void adjustLightSensorSubscription() { + if (mModifiers.stream().anyMatch(BrightnessStateModifier::shouldListenToLightSensor)) { + mLightSensorController.restart(); + } else { + mLightSensorController.stop(); } } @@ -323,7 +295,7 @@ public class BrightnessClamperController { List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context, Handler handler, ClamperChangeListener listener, - DisplayDeviceConfig displayDeviceConfig, SensorManager sensorManager) { + DisplayDeviceConfig displayDeviceConfig) { List<BrightnessStateModifier> modifiers = new ArrayList<>(); modifiers.add(new DisplayDimModifier(context)); modifiers.add(new BrightnessLowPowerModeModifier()); @@ -335,11 +307,12 @@ public class BrightnessClamperController { return modifiers; } - Sensor getLightSensor(SensorManager sensorManager, String type, String name) { - return SensorUtils.findSensor(sensorManager, type, - name, Sensor.TYPE_LIGHT); + LightSensorController getLightSensorController(SensorManager sensorManager, + Context context, LightSensorController.LightSensorListener listener, + Handler handler) { + return new LightSensorController(sensorManager, context.getResources(), + listener, handler); } - } /** @@ -354,17 +327,21 @@ public class BrightnessClamperController { private final String mThermalThrottlingDataId; @NonNull private final String mPowerThrottlingDataId; - + @NonNull private final DisplayDeviceConfig mDisplayDeviceConfig; + private final int mDisplayId; + public DisplayDeviceData(@NonNull String uniqueDisplayId, @NonNull String thermalThrottlingDataId, @NonNull String powerThrottlingDataId, - @NonNull DisplayDeviceConfig displayDeviceConfig) { + @NonNull DisplayDeviceConfig displayDeviceConfig, + int displayId) { mUniqueDisplayId = uniqueDisplayId; mThermalThrottlingDataId = thermalThrottlingDataId; mPowerThrottlingDataId = powerThrottlingDataId; mDisplayDeviceConfig = displayDeviceConfig; + mDisplayId = displayId; } @@ -412,55 +389,18 @@ public class BrightnessClamperController { } @NonNull + @Override public SensorData getTempSensor() { return mDisplayDeviceConfig.getTempSensor(); } - } - - private void maybeRegisterLightSensor() { - if (mModifiers.stream().noneMatch(BrightnessStateModifier::shouldListenToLightSensor)) { - return; - } - - if (mRegisteredLightSensor == mLightSensor) { - return; - } - if (mRegisteredLightSensor != null) { - unregisterSensorListener(); - } - - mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, mResources); - mSensorManager.registerListener(mLightSensorListener, - mLightSensor, mLightSensorRate * 1000, mHandler); - mRegisteredLightSensor = mLightSensor; - - if (DEBUG) { - Slog.d(TAG, "maybeRegisterLightSensor"); - } - } - - private void unregisterSensorListener() { - mSensorManager.unregisterListener(mLightSensorListener); - mRegisteredLightSensor = null; - mModifiers.forEach(mModifier -> mModifier.setAmbientLux(INVALID_LUX)); // set lux to invalid - if (DEBUG) { - Slog.d(TAG, "unregisterSensorListener"); + @NonNull + SensorData getAmbientLightSensor() { + return mDisplayDeviceConfig.getAmbientLightSensor(); } - } - private void reloadLightSensorData(DisplayDeviceConfig displayDeviceConfig) { - // The displayDeviceConfig (ddc) contains display specific preferences. When loaded, - // it naturally falls back to the global config.xml. - if (displayDeviceConfig != null - && displayDeviceConfig.getAmbientLightSensor() != null) { - // This covers both the ddc and the config.xml fallback - mLightSensorType = displayDeviceConfig.getAmbientLightSensor().type; - mLightSensorName = displayDeviceConfig.getAmbientLightSensor().name; - } else if (mLightSensorName == null && mLightSensorType == null) { - mLightSensorType = mResources.getString( - com.android.internal.R.string.config_displayLightSensorType); - mLightSensorName = ""; + int getDisplayId() { + return mDisplayId; } } } diff --git a/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java b/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java new file mode 100644 index 000000000000..d89dd28c4a89 --- /dev/null +++ b/services/core/java/com/android/server/display/brightness/clamper/LightSensorController.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display.brightness.clamper; + +import android.annotation.Nullable; +import android.content.res.Resources; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Handler; +import android.os.SystemClock; +import android.util.Slog; +import android.view.Display; + +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.config.SensorData; +import com.android.server.display.utils.AmbientFilter; +import com.android.server.display.utils.AmbientFilterFactory; +import com.android.server.display.utils.DebugUtils; +import com.android.server.display.utils.SensorUtils; + +import java.io.PrintWriter; +import java.util.concurrent.TimeUnit; + +/** + * Manages light sensor subscription and notifies its listener about ambient lux changes + */ +public class LightSensorController { + private static final String TAG = "LightSensorController"; + + // To enable these logs, run: + // 'adb shell setprop persist.log.tag.LightSensorController DEBUG && adb reboot' + private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); + static final float INVALID_LUX = -1f; + + private final SensorManager mSensorManager; + private final LightSensorListener mLightSensorListener; + private final Handler mHandler; + private final Injector mInjector; + private final AmbientFilter mAmbientFilter; + + private Sensor mLightSensor; + private Sensor mRegisteredLightSensor = null; + private final int mLightSensorRate; + + private final SensorEventListener mLightSensorEventListener = new SensorEventListener() { + @Override + public void onSensorChanged(SensorEvent event) { + long now = mInjector.getTime(); + mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp), + event.values[0]); + final float lux = mAmbientFilter.getEstimate(now); + mLightSensorListener.onAmbientLuxChange(lux); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // unused + } + }; + + LightSensorController(SensorManager sensorManager, Resources resources, + LightSensorListener listener, Handler handler) { + this(sensorManager, resources, listener, handler, new Injector()); + } + + @VisibleForTesting + LightSensorController(SensorManager sensorManager, Resources resources, + LightSensorListener listener, Handler handler, Injector injector) { + mSensorManager = sensorManager; + mLightSensorRate = injector.getLightSensorRate(resources); + mAmbientFilter = injector.getAmbientFilter(resources); + mLightSensorListener = listener; + mHandler = handler; + mInjector = injector; + } + + void restart() { + if (mRegisteredLightSensor == mLightSensor) { + return; + } + if (mRegisteredLightSensor != null) { + stop(); + } + if (mLightSensor == null) { + return; + } + + mSensorManager.registerListener(mLightSensorEventListener, + mLightSensor, mLightSensorRate * 1000, mHandler); + mRegisteredLightSensor = mLightSensor; + + if (DEBUG) { + Slog.d(TAG, "restart"); + } + } + + void stop() { + if (mRegisteredLightSensor == null) { + return; + } + mSensorManager.unregisterListener(mLightSensorEventListener); + mRegisteredLightSensor = null; + mAmbientFilter.clear(); + mLightSensorListener.onAmbientLuxChange(INVALID_LUX); + if (DEBUG) { + Slog.d(TAG, "stop"); + } + } + + void configure(SensorData sensorData, int displayId) { + final int fallbackType = displayId == Display.DEFAULT_DISPLAY + ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK; + mLightSensor = mInjector.getLightSensor(mSensorManager, sensorData, fallbackType); + } + + void dump(PrintWriter writer) { + writer.println("LightSensorController"); + writer.println(" mLightSensor=" + mLightSensor); + writer.println(" mRegisteredLightSensor=" + mRegisteredLightSensor); + } + + static class Injector { + @Nullable + Sensor getLightSensor(SensorManager sensorManager, SensorData sensorData, + int fallbackType) { + return SensorUtils.findSensor(sensorManager, sensorData, fallbackType); + } + + AmbientFilter getAmbientFilter(Resources resources) { + return AmbientFilterFactory.createBrightnessFilter(TAG, resources); + } + + int getLightSensorRate(Resources resources) { + return resources.getInteger(R.integer.config_autoBrightnessLightSensorRate); + } + + // should be consistent with SensorEvent.timestamp + long getTime() { + return SystemClock.elapsedRealtime(); + } + } + + interface LightSensorListener { + void onAmbientLuxChange(float ambientLux); + } +} diff --git a/services/core/java/com/android/server/flags/services.aconfig b/services/core/java/com/android/server/flags/services.aconfig index 9bbcb0c99e8e..d387828872e9 100644 --- a/services/core/java/com/android/server/flags/services.aconfig +++ b/services/core/java/com/android/server/flags/services.aconfig @@ -28,3 +28,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + namespace: "wear_frameworks" + name: "optional_background_install_control" + description: "Enable BackgroundInstallControl based on system feature to prevent it from starting on form factors." + bug: "340928990" +} diff --git a/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java b/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java index 559b6252fd07..4764e4fadd6e 100644 --- a/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java +++ b/services/core/java/com/android/server/inputmethod/SecureSettingsWrapper.java @@ -44,6 +44,32 @@ final class SecureSettingsWrapper { @Nullable private static volatile ContentResolver sContentResolver = null; + private static volatile boolean sTestMode = false; + + /** + * Can be called from unit tests to start the test mode, where a fake implementation will be + * used instead. + * + * <p>The fake implementation is just an {@link ArrayMap}. By default it is empty, and the data + * written can be read back later.</p> + */ + @AnyThread + static void startTestMode() { + sTestMode = true; + } + + /** + * Can be called from unit tests to end the test mode, where a fake implementation will be used + * instead. + */ + @AnyThread + static void endTestMode() { + synchronized (sUserMap) { + sUserMap.clear(); + } + sTestMode = false; + } + /** * Not intended to be instantiated. */ @@ -78,6 +104,52 @@ final class SecureSettingsWrapper { int getInt(String key, int defaultValue); } + private static class FakeReaderWriterImpl implements ReaderWriter { + @GuardedBy("mNonPersistentKeyValues") + private final ArrayMap<String, String> mNonPersistentKeyValues = new ArrayMap<>(); + + @AnyThread + @Override + public void putString(String key, String value) { + synchronized (mNonPersistentKeyValues) { + mNonPersistentKeyValues.put(key, value); + } + } + + @AnyThread + @Nullable + @Override + public String getString(String key, String defaultValue) { + synchronized (mNonPersistentKeyValues) { + if (mNonPersistentKeyValues.containsKey(key)) { + final String result = mNonPersistentKeyValues.get(key); + return result != null ? result : defaultValue; + } + return defaultValue; + } + } + + @AnyThread + @Override + public void putInt(String key, int value) { + synchronized (mNonPersistentKeyValues) { + mNonPersistentKeyValues.put(key, String.valueOf(value)); + } + } + + @AnyThread + @Override + public int getInt(String key, int defaultValue) { + synchronized (mNonPersistentKeyValues) { + if (mNonPersistentKeyValues.containsKey(key)) { + final String result = mNonPersistentKeyValues.get(key); + return result != null ? Integer.parseInt(result) : defaultValue; + } + return defaultValue; + } + } + } + private static class UnlockedUserImpl implements ReaderWriter { @UserIdInt private final int mUserId; @@ -200,6 +272,9 @@ final class SecureSettingsWrapper { private static ReaderWriter createImpl(@NonNull UserManagerInternal userManagerInternal, @UserIdInt int userId) { + if (sTestMode) { + return new FakeReaderWriterImpl(); + } return userManagerInternal.isUserUnlockingOrUnlocked(userId) ? new UnlockedUserImpl(userId, sContentResolver) : new LockedUserImpl(userId, sContentResolver); @@ -234,6 +309,9 @@ final class SecureSettingsWrapper { return readerWriter; } } + if (sTestMode) { + return putOrGet(userId, new FakeReaderWriterImpl()); + } final UserManagerInternal userManagerInternal = LocalServices.getService(UserManagerInternal.class); if (!userManagerInternal.exists(userId)) { @@ -276,6 +354,10 @@ final class SecureSettingsWrapper { */ @AnyThread static void onUserStarting(@UserIdInt int userId) { + if (sTestMode) { + putOrGet(userId, new FakeReaderWriterImpl()); + return; + } putOrGet(userId, createImpl(LocalServices.getService(UserManagerInternal.class), userId)); } @@ -286,6 +368,10 @@ final class SecureSettingsWrapper { */ @AnyThread static void onUserUnlocking(@UserIdInt int userId) { + if (sTestMode) { + putOrGet(userId, new FakeReaderWriterImpl()); + return; + } final ReaderWriter readerWriter = new UnlockedUserImpl(userId, sContentResolver); putOrGet(userId, readerWriter); } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 22b33ddcfa2b..ae3a2afb79ef 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -254,9 +254,6 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String MIGRATED_SP_CE_ONLY = "migrated_all_users_to_sp_and_bound_ce"; private static final String MIGRATED_SP_FULL = "migrated_all_users_to_sp_and_bound_keys"; - private static final boolean FIX_UNLOCKED_DEVICE_REQUIRED_KEYS = - android.security.Flags.fixUnlockedDeviceRequiredKeysV2(); - // Duration that LockSettingsService will store the gatekeeper password for. This allows // multiple biometric enrollments without prompting the user to enter their password via // ConfirmLockPassword/ConfirmLockPattern multiple times. This needs to be at least the duration @@ -670,7 +667,6 @@ public class LockSettingsService extends ILockSettings.Stub { mActivityManager = injector.getActivityManager(); IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_STARTING); filter.addAction(Intent.ACTION_LOCALE_CHANGED); injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, @@ -909,13 +905,7 @@ public class LockSettingsService extends ILockSettings.Stub { private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) { - if (!FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - // Notify keystore that a new user was added. - final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); - AndroidKeyStoreMaintenance.onUserAdded(userHandle); - } - } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) { + if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) { final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); mStorage.prefetchUser(userHandle); } else if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { @@ -1130,32 +1120,14 @@ public class LockSettingsService extends ILockSettings.Stub { // Note: if this migration gets interrupted (e.g. by the device powering off), there // shouldn't be a problem since this will run again on the next boot, and // setCeStorageProtection() and initKeystoreSuperKeys(..., true) are idempotent. - if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - if (!getBoolean(MIGRATED_SP_FULL, false, 0)) { - for (UserInfo user : mUserManager.getAliveUsers()) { - removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); - synchronized (mSpManager) { - migrateUserToSpWithBoundKeysLocked(user.id); - } - } - setBoolean(MIGRATED_SP_FULL, true, 0); - } - } else { - if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { - for (UserInfo user : mUserManager.getAliveUsers()) { - removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); - synchronized (mSpManager) { - migrateUserToSpWithBoundCeKeyLocked(user.id); - } + if (!getBoolean(MIGRATED_SP_FULL, false, 0)) { + for (UserInfo user : mUserManager.getAliveUsers()) { + removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); + synchronized (mSpManager) { + migrateUserToSpWithBoundKeysLocked(user.id); } - setString(MIGRATED_SP_CE_ONLY, "true", 0); - } - - if (getBoolean(MIGRATED_SP_FULL, false, 0)) { - // The FIX_UNLOCKED_DEVICE_REQUIRED_KEYS flag was enabled but then got disabled. - // Ensure the full migration runs again the next time the flag is enabled... - setBoolean(MIGRATED_SP_FULL, false, 0); } + setBoolean(MIGRATED_SP_FULL, true, 0); } mThirdPartyAppsStarted = true; @@ -1163,30 +1135,6 @@ public class LockSettingsService extends ILockSettings.Stub { } @GuardedBy("mSpManager") - private void migrateUserToSpWithBoundCeKeyLocked(@UserIdInt int userId) { - if (isUserSecure(userId)) { - Slogf.d(TAG, "User %d is secured; no migration needed", userId); - return; - } - long protectorId = getCurrentLskfBasedProtectorId(userId); - if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { - Slogf.i(TAG, "Migrating unsecured user %d to SP-based credential", userId); - initializeSyntheticPassword(userId); - } else { - Slogf.i(TAG, "Existing unsecured user %d has a synthetic password; re-encrypting CE " + - "key with it", userId); - AuthenticationResult result = mSpManager.unlockLskfBasedProtector( - getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId, - null); - if (result.syntheticPassword == null) { - Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId); - return; - } - setCeStorageProtection(userId, result.syntheticPassword); - } - } - - @GuardedBy("mSpManager") private void migrateUserToSpWithBoundKeysLocked(@UserIdInt int userId) { if (isUserSecure(userId)) { Slogf.d(TAG, "User %d is secured; no migration needed", userId); @@ -1496,11 +1444,6 @@ public class LockSettingsService extends ILockSettings.Stub { } @VisibleForTesting /** Note: this method is overridden in unit tests */ - void setKeystorePassword(byte[] password, int userHandle) { - AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password); - } - - @VisibleForTesting /** Note: this method is overridden in unit tests */ void initKeystoreSuperKeys(@UserIdInt int userId, SyntheticPassword sp, boolean allowExisting) { final byte[] password = sp.deriveKeyStorePassword(); try { @@ -2237,9 +2180,7 @@ public class LockSettingsService extends ILockSettings.Stub { return; } onSyntheticPasswordUnlocked(userId, result.syntheticPassword); - if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - unlockKeystore(userId, result.syntheticPassword); - } + unlockKeystore(userId, result.syntheticPassword); unlockCeStorage(userId, result.syntheticPassword); } } @@ -2545,9 +2486,7 @@ public class LockSettingsService extends ILockSettings.Stub { // long time, so for now we keep doing it just in case it's ever important. Don't wait // until initKeystoreSuperKeys() to do this; that can be delayed if the user is being // created during early boot, and maybe something will use Keystore before then. - if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - AndroidKeyStoreMaintenance.onUserAdded(userId); - } + AndroidKeyStoreMaintenance.onUserAdded(userId); synchronized (mUserCreationAndRemovalLock) { // During early boot, don't actually create the synthetic password yet, but rather @@ -2973,9 +2912,7 @@ public class LockSettingsService extends ILockSettings.Stub { LockscreenCredential.createNone(), sp, userId); setCurrentLskfBasedProtectorId(protectorId, userId); setCeStorageProtection(userId, sp); - if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - initKeystoreSuperKeys(userId, sp, /* allowExisting= */ false); - } + initKeystoreSuperKeys(userId, sp, /* allowExisting= */ false); onSyntheticPasswordCreated(userId, sp); Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId); return sp; @@ -3090,9 +3027,6 @@ public class LockSettingsService extends ILockSettings.Stub { if (!mSpManager.hasSidForUser(userId)) { mSpManager.newSidForUser(getGateKeeperService(), sp, userId); mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId); - if (!FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - setKeystorePassword(sp.deriveKeyStorePassword(), userId); - } } } else { // Cache all profile password if they use unified challenge. This will later be used to @@ -3103,11 +3037,7 @@ public class LockSettingsService extends ILockSettings.Stub { gateKeeperClearSecureUserId(userId); unlockCeStorage(userId, sp); unlockKeystore(userId, sp); - if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { - AndroidKeyStoreMaintenance.onUserLskfRemoved(userId); - } else { - setKeystorePassword(null, userId); - } + AndroidKeyStoreMaintenance.onUserLskfRemoved(userId); removeBiometricsForUser(userId); } setCurrentLskfBasedProtectorId(newProtectorId, userId); diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java index 3673eb027096..56b93e8ded82 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java @@ -839,6 +839,13 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider { + "Disallowed route: " + route); } + + if (route.isSystemRouteType()) { + throw new SecurityException( + "Only the system is allowed to publish routes with system route types. " + + "Disallowed route: " + + route); + } } Connection connection = mConnectionRef.get(); diff --git a/services/core/java/com/android/server/notification/TimeToLiveHelper.java b/services/core/java/com/android/server/notification/TimeToLiveHelper.java index 2facab74e28e..a4460b23c73d 100644 --- a/services/core/java/com/android/server/notification/TimeToLiveHelper.java +++ b/services/core/java/com/android/server/notification/TimeToLiveHelper.java @@ -54,13 +54,17 @@ public class TimeToLiveHelper { private final AlarmManager mAm; @VisibleForTesting + @GuardedBy("mLock") final TreeSet<Pair<Long, String>> mKeys; + final Object mLock = new Object(); public TimeToLiveHelper(NotificationManagerPrivate nm, Context context) { mContext = context; mNm = nm; mAm = context.getSystemService(AlarmManager.class); - mKeys = new TreeSet<>((left, right) -> Long.compare(left.first, right.first)); + synchronized (mLock) { + mKeys = new TreeSet<>((left, right) -> Long.compare(left.first, right.first)); + } IntentFilter timeoutFilter = new IntentFilter(ACTION); timeoutFilter.addDataScheme(SCHEME_TIMEOUT); @@ -73,7 +77,9 @@ public class TimeToLiveHelper { } void dump(PrintWriter pw, String indent) { - pw.println(indent + "mKeys " + mKeys); + synchronized (mLock) { + pw.println(indent + "mKeys " + mKeys); + } } private @NonNull PendingIntent getAlarmPendingIntent(String nextKey, int flags) { @@ -93,30 +99,35 @@ public class TimeToLiveHelper { @VisibleForTesting void scheduleTimeoutLocked(NotificationRecord record, long currentTime) { - removeMatchingEntry(record.getKey()); - - final long timeoutAfter = currentTime + record.getNotification().getTimeoutAfter(); - if (record.getNotification().getTimeoutAfter() > 0) { - final Long currentEarliestTime = mKeys.isEmpty() ? null : mKeys.first().first; - - // Maybe replace alarm with an earlier one - if (currentEarliestTime == null || timeoutAfter < currentEarliestTime) { - if (currentEarliestTime != null) { - cancelFirstAlarm(); + synchronized (mLock) { + removeMatchingEntry(record.getKey()); + + final long timeoutAfter = currentTime + record.getNotification().getTimeoutAfter(); + if (record.getNotification().getTimeoutAfter() > 0) { + final Long currentEarliestTime = mKeys.isEmpty() ? null : mKeys.first().first; + + // Maybe replace alarm with an earlier one + if (currentEarliestTime == null || timeoutAfter < currentEarliestTime) { + if (currentEarliestTime != null) { + cancelFirstAlarm(); + } + mKeys.add(Pair.create(timeoutAfter, record.getKey())); + maybeScheduleFirstAlarm(); + } else { + mKeys.add(Pair.create(timeoutAfter, record.getKey())); } - mKeys.add(Pair.create(timeoutAfter, record.getKey())); - maybeScheduleFirstAlarm(); - } else { - mKeys.add(Pair.create(timeoutAfter, record.getKey())); } } } @VisibleForTesting void cancelScheduledTimeoutLocked(NotificationRecord record) { - removeMatchingEntry(record.getKey()); + synchronized (mLock) { + removeMatchingEntry(record.getKey()); + } } + @GuardedBy("mLock") private void removeMatchingEntry(String key) { if (!mKeys.isEmpty() && key.equals(mKeys.first().second)) { // cancel the first alarm, remove the first entry, maybe schedule the alarm for the new @@ -139,11 +150,13 @@ public class TimeToLiveHelper { } } + @GuardedBy("mLock") private void cancelFirstAlarm() { final PendingIntent pi = getAlarmPendingIntent(mKeys.first().second, FLAG_CANCEL_CURRENT); mAm.cancel(pi); } + @GuardedBy("mLock") private void maybeScheduleFirstAlarm() { if (!mKeys.isEmpty()) { final PendingIntent piNewFirst = getAlarmPendingIntent(mKeys.first().second, @@ -162,13 +175,17 @@ public class TimeToLiveHelper { return; } if (ACTION.equals(action)) { - Pair<Long, String> earliest = mKeys.first(); - String key = intent.getStringExtra(EXTRA_KEY); - if (!earliest.second.equals(key)) { - Slog.wtf(TAG, "Alarm triggered but wasn't the earliest we were tracking"); + String timeoutKey = null; + synchronized (mLock) { + Pair<Long, String> earliest = mKeys.first(); + String key = intent.getStringExtra(EXTRA_KEY); + if (!earliest.second.equals(key)) { + Slog.wtf(TAG, "Alarm triggered but wasn't the earliest we were tracking"); + } + removeMatchingEntry(key); + timeoutKey = earliest.second; } - removeMatchingEntry(key); - mNm.timeoutNotification(earliest.second); + mNm.timeoutNotification(timeoutKey); } } }; diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java index 69490a81fc86..5b4f310655cd 100644 --- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java +++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java @@ -126,10 +126,12 @@ final class ResolveIntentHelper { userId, resolveForStart, /*allowDynamicSplits*/ true); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - var args = new SaferIntentUtils.IntentArgs(intent, resolvedType, - false /* isReceiver */, resolveForStart, filterCallingUid, callingPid); - args.platformCompat = mPlatformCompat; - SaferIntentUtils.filterNonExportedComponents(args, query); + if (resolveForStart) { + var args = new SaferIntentUtils.IntentArgs(intent, resolvedType, + false /* isReceiver */, true, filterCallingUid, callingPid); + args.platformCompat = mPlatformCompat; + SaferIntentUtils.filterNonExportedComponents(args, query); + } final boolean queryMayBeFiltered = UserHandle.getAppId(filterCallingUid) >= Process.FIRST_APPLICATION_UID diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index db94d0e8b0ba..d1d8993168c9 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -5918,6 +5918,7 @@ public class UserManagerService extends IUserManager.Stub { return userData; } + /** For testing only! Directly, unnaturally removes userId from list of users. */ @VisibleForTesting void removeUserInfo(@UserIdInt int userId) { synchronized (mUsersLock) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 28254d0d863e..46e6546bbfca 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -274,7 +274,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { mVirtualDeviceManagerInternal = LocalServices.getService(VirtualDeviceManagerInternal.class); } - return mVirtualDeviceManagerInternal.getPersistentIdForDevice(deviceId); + return mVirtualDeviceManagerInternal == null + ? VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT + : mVirtualDeviceManagerInternal.getPersistentIdForDevice(deviceId); } @Override diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 3138a9ea9426..ddbd8091b601 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -1026,12 +1026,7 @@ public class TrustManagerService extends SystemService { continue; } - final boolean trusted; - if (android.security.Flags.fixUnlockedDeviceRequiredKeysV2()) { - trusted = getUserTrustStateInner(id) == TrustState.TRUSTED; - } else { - trusted = aggregateIsTrusted(id); - } + final boolean trusted = getUserTrustStateInner(id) == TrustState.TRUSTED; boolean showingKeyguard = true; boolean biometricAuthenticated = false; boolean currentUserIsUnlocked = false; @@ -1092,19 +1087,15 @@ public class TrustManagerService extends SystemService { private void notifyKeystoreOfDeviceLockState(int userId, boolean isLocked) { if (isLocked) { - if (android.security.Flags.fixUnlockedDeviceRequiredKeysV2()) { - // A profile with unified challenge is unlockable not by its own biometrics and - // trust agents, but rather by those of the parent user. Therefore, when protecting - // the profile's UnlockedDeviceRequired keys, we must use the parent's list of - // biometric SIDs and weak unlock methods, not the profile's. - int authUserId = mLockPatternUtils.isProfileWithUnifiedChallenge(userId) - ? resolveProfileParent(userId) : userId; - - mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(authUserId), - isWeakUnlockMethodEnabled(authUserId)); - } else { - mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(userId), false); - } + // A profile with unified challenge is unlockable not by its own biometrics and + // trust agents, but rather by those of the parent user. Therefore, when protecting + // the profile's UnlockedDeviceRequired keys, we must use the parent's list of + // biometric SIDs and weak unlock methods, not the profile's. + int authUserId = mLockPatternUtils.isProfileWithUnifiedChallenge(userId) + ? resolveProfileParent(userId) : userId; + + mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(authUserId), + isWeakUnlockMethodEnabled(authUserId)); } else { // Notify Keystore that the device is now unlocked for the user. Note that for unlocks // with LSKF, this is redundant with the call from LockSettingsService which provides diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index 84c37180d93c..6537228583ec 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -69,6 +69,7 @@ abstract class Vibration { CANCELLED_BY_USER(VibrationProto.CANCELLED_BY_USER), CANCELLED_BY_UNKNOWN_REASON(VibrationProto.CANCELLED_BY_UNKNOWN_REASON), CANCELLED_SUPERSEDED(VibrationProto.CANCELLED_SUPERSEDED), + CANCELLED_BY_APP_OPS(VibrationProto.CANCELLED_BY_APP_OPS), IGNORED_ERROR_APP_OPS(VibrationProto.IGNORED_ERROR_APP_OPS), IGNORED_ERROR_CANCELLING(VibrationProto.IGNORED_ERROR_CANCELLING), IGNORED_ERROR_SCHEDULING(VibrationProto.IGNORED_ERROR_SCHEDULING), diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 3dcc7a6f76e5..7f60dc443df7 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -193,6 +193,27 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } }; + @VisibleForTesting + final AppOpsManager.OnOpChangedInternalListener mAppOpsChangeListener = + new AppOpsManager.OnOpChangedInternalListener() { + @Override + public void onOpChanged(int op, String packageName) { + if (op != AppOpsManager.OP_VIBRATE) { + return; + } + synchronized (mLock) { + if (shouldCancelAppOpModeChangedLocked(mNextVibration)) { + clearNextVibrationLocked( + new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_APP_OPS)); + } + if (shouldCancelAppOpModeChangedLocked(mCurrentVibration)) { + mCurrentVibration.notifyCancelled(new Vibration.EndInfo( + Vibration.Status.CANCELLED_BY_APP_OPS), /* immediate= */ false); + } + } + } + }; + static native long nativeInit(OnSyncedVibrationCompleteListener listener); static native long nativeGetFinalizer(); @@ -238,6 +259,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mBatteryStatsService = injector.getBatteryStatsService(); mAppOps = mContext.getSystemService(AppOpsManager.class); + if (Flags.cancelByAppops()) { + mAppOps.startWatchingMode(AppOpsManager.OP_VIBRATE, null, mAppOpsChangeListener); + } PowerManager pm = context.getSystemService(PowerManager.class); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); @@ -1390,6 +1414,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } @GuardedBy("mLock") + private boolean shouldCancelAppOpModeChangedLocked(@Nullable VibrationStepConductor conductor) { + if (conductor == null) { + return false; + } + return checkAppOpModeLocked(conductor.getVibration().callerInfo) + != AppOpsManager.MODE_ALLOWED; + } + + @GuardedBy("mLock") private void onAllVibratorsLocked(Consumer<VibratorController> consumer) { for (int i = 0; i < mVibrators.size(); i++) { consumer.accept(mVibrators.valueAt(i)); diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 1ce324f68569..5699fdd15c31 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -252,7 +252,8 @@ class BackNavigationController { // skip if one of participant activity is translucent backType = BackNavigationInfo.TYPE_CALLBACK; } else if (prevActivities.size() > 0) { - if (!isOccluded || isAllActivitiesCanShowWhenLocked(prevActivities)) { + if ((!isOccluded || isAllActivitiesCanShowWhenLocked(prevActivities)) + && isAllActivitiesCreated(prevActivities)) { // We have another Activity in the same currentTask to go to final WindowContainer parent = currentActivity.getParent(); final boolean canCustomize = parent != null @@ -549,6 +550,17 @@ class BackNavigationController { return !prevActivities.isEmpty(); } + private static boolean isAllActivitiesCreated( + @NonNull ArrayList<ActivityRecord> prevActivities) { + for (int i = prevActivities.size() - 1; i >= 0; --i) { + final ActivityRecord check = prevActivities.get(i); + if (check.isState(ActivityRecord.State.INITIALIZING)) { + return false; + } + } + return !prevActivities.isEmpty(); + } + boolean isMonitoringTransition() { return mAnimationHandler.mComposed || mNavigationMonitor.isMonitorForRemote(); } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 3b3eeb496ab7..4a0239bc29b2 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -41,7 +41,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static com.android.window.flags.Flags.windowSessionRelayoutInfo; import android.annotation.NonNull; import android.annotation.Nullable; @@ -64,7 +63,6 @@ import android.os.Trace; import android.os.UserHandle; import android.text.TextUtils; import android.util.ArraySet; -import android.util.MergedConfiguration; import android.util.Slog; import android.view.IWindow; import android.view.IWindowId; @@ -81,7 +79,6 @@ import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager; import android.view.WindowRelayoutResult; -import android.window.ClientWindowFrames; import android.window.InputTransferToken; import android.window.OnBackInvokedCallbackInfo; @@ -290,37 +287,12 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { return res; } - /** @deprecated */ - @Deprecated - @Override - public int relayoutLegacy(IWindow window, WindowManager.LayoutParams attrs, - int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq, - int lastSyncSeqId, ClientWindowFrames outFrames, - MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, - InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls, - Bundle outBundle) { - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); - int res = mService.relayoutWindow(this, window, attrs, - requestedWidth, requestedHeight, viewFlags, flags, seq, - lastSyncSeqId, outFrames, mergedConfiguration, outSurfaceControl, outInsetsState, - outActiveControls, outBundle); - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - return res; - } - @Override public void relayoutAsync(IWindow window, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq, int lastSyncSeqId) { - if (windowSessionRelayoutInfo()) { - relayout(window, attrs, requestedWidth, requestedHeight, viewFlags, flags, seq, - lastSyncSeqId, null /* outRelayoutResult */); - } else { - relayoutLegacy(window, attrs, requestedWidth, requestedHeight, viewFlags, flags, seq, - lastSyncSeqId, null /* outFrames */, null /* mergedConfiguration */, - null /* outSurfaceControl */, null /* outInsetsState */, - null /* outActiveControls */, null /* outSyncIdBundle */); - } + relayout(window, attrs, requestedWidth, requestedHeight, viewFlags, flags, seq, + lastSyncSeqId, null /* outRelayoutResult */); } @Override diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 7f6499f0f4b5..acdb66a49251 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.app.WindowConfiguration.isFloating; import static android.content.pm.ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; @@ -2248,8 +2249,10 @@ class TaskFragment extends WindowContainer<WindowContainer> { void resolveTmpOverrides(DisplayContent dc, Configuration parentConfig, boolean isFixedRotationTransforming) { mParentAppBoundsOverride = new Rect(parentConfig.windowConfiguration.getAppBounds()); + mTmpOverrideConfigOrientation = parentConfig.orientation; final Insets insets; - if (mUseOverrideInsetsForConfig && dc != null) { + if (mUseOverrideInsetsForConfig && dc != null + && !isFloating(parentConfig.windowConfiguration.getWindowingMode())) { // Insets are decoupled from configuration by default from V+, use legacy // compatibility behaviour for apps targeting SDK earlier than 35 // (see applySizeOverrideIfNeeded). diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index bc45c7063705..a029f38de128 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1903,7 +1903,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } else { final List<TransitionInfo.Change> changes = info.getChanges(); for (int i = changes.size() - 1; i >= 0; --i) { - if (mTargets.get(i).mContainer.asActivityRecord() != null) { + final WindowContainer<?> container = mTargets.get(i).mContainer; + if (container.asActivityRecord() != null + || (container.asTask() != null + && mOverrideOptions.getOverrideTaskTransition())) { changes.get(i).setAnimationOptions(mOverrideOptions); // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions. changes.get(i).setBackgroundColor(mOverrideOptions.getBackgroundColor()); @@ -2541,9 +2544,8 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (wc.asWindowState() != null) continue; final ChangeInfo changeInfo = changes.get(wc); - - // Reject no-ops - if (!changeInfo.hasChanged()) { + // Reject no-ops, unless wallpaper + if (!changeInfo.hasChanged() && wc.asWallpaperToken() == null) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " Rejecting as no-op: %s", wc); continue; diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 3e43f5a2da66..a3e03029c095 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -764,10 +764,10 @@ class WallpaperController { void collectTopWallpapers(Transition transition) { if (mFindResults.hasTopShowWhenLockedWallpaper()) { - transition.collect(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper); + transition.collect(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper.mToken); } if (mFindResults.hasTopHideWhenLockedWallpaper()) { - transition.collect(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper); + transition.collect(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper.mToken); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2b375e16e5b4..72ec05847973 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2292,32 +2292,7 @@ public class WindowManagerService extends IWindowManager.Stub outInsetsState = null; outActiveControls = null; } - return relayoutWindowInner(session, client, attrs, requestedWidth, requestedHeight, - viewVisibility, flags, seq, lastSyncSeqId, outFrames, outMergedConfiguration, - outSurfaceControl, outInsetsState, outActiveControls, null /* outBundle */, - outRelayoutResult); - } - /** @deprecated */ - @Deprecated - public int relayoutWindow(Session session, IWindow client, LayoutParams attrs, - int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq, - int lastSyncSeqId, ClientWindowFrames outFrames, - MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl, - InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls, - Bundle outBundle) { - return relayoutWindowInner(session, client, attrs, requestedWidth, requestedHeight, - viewVisibility, flags, seq, lastSyncSeqId, outFrames, outMergedConfiguration, - outSurfaceControl, outInsetsState, outActiveControls, outBundle, - null /* outRelayoutResult */); - } - - private int relayoutWindowInner(Session session, IWindow client, LayoutParams attrs, - int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq, - int lastSyncSeqId, ClientWindowFrames outFrames, - MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl, - InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls, - Bundle outBundle, WindowRelayoutResult outRelayoutResult) { if (outActiveControls != null) { outActiveControls.set(null, false /* copyControls */); } @@ -2649,14 +2624,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (outFrames != null && outMergedConfiguration != null) { - final boolean shouldReportActivityWindowInfo; - if (Flags.windowSessionRelayoutInfo()) { - shouldReportActivityWindowInfo = outRelayoutResult != null - && win.mLastReportedActivityWindowInfo != null; - } else { - shouldReportActivityWindowInfo = outBundle != null + final boolean shouldReportActivityWindowInfo = outRelayoutResult != null && win.mLastReportedActivityWindowInfo != null; - } final ActivityWindowInfo outActivityWindowInfo = shouldReportActivityWindowInfo ? new ActivityWindowInfo() : null; @@ -2665,13 +2634,7 @@ public class WindowManagerService extends IWindowManager.Stub outActivityWindowInfo, false /* useLatestConfig */, shouldRelayout); if (shouldReportActivityWindowInfo) { - if (Flags.windowSessionRelayoutInfo()) { - outRelayoutResult.activityWindowInfo = outActivityWindowInfo; - } else { - outBundle.putParcelable( - IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO, - outActivityWindowInfo); - } + outRelayoutResult.activityWindowInfo = outActivityWindowInfo; } // Set resize-handled here because the values are sent back to the client. @@ -2702,28 +2665,16 @@ public class WindowManagerService extends IWindowManager.Stub win.isVisible() /* visible */, false /* removed */); } - if (Flags.windowSessionRelayoutInfo()) { - if (outRelayoutResult != null) { - if (win.syncNextBuffer() && viewVisibility == View.VISIBLE - && win.mSyncSeqId > lastSyncSeqId) { - outRelayoutResult.syncSeqId = win.shouldSyncWithBuffers() - ? win.mSyncSeqId - : -1; - win.markRedrawForSyncReported(); - } else { - outRelayoutResult.syncSeqId = -1; - } - } - } else if (outBundle != null) { - final int maybeSyncSeqId; + if (outRelayoutResult != null) { if (win.syncNextBuffer() && viewVisibility == View.VISIBLE && win.mSyncSeqId > lastSyncSeqId) { - maybeSyncSeqId = win.shouldSyncWithBuffers() ? win.mSyncSeqId : -1; + outRelayoutResult.syncSeqId = win.shouldSyncWithBuffers() + ? win.mSyncSeqId + : -1; win.markRedrawForSyncReported(); } else { - maybeSyncSeqId = -1; + outRelayoutResult.syncSeqId = -1; } - outBundle.putInt(IWindowSession.KEY_RELAYOUT_BUNDLE_SEQID, maybeSyncSeqId); } if (configChanged) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 611a4eb10dab..215cf2c5c85c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -2644,9 +2644,13 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(MediaMetricsManagerService.class); t.traceEnd(); - t.traceBegin("StartBackgroundInstallControlService"); - mSystemServiceManager.startService(BackgroundInstallControlService.class); - t.traceEnd(); + if (!com.android.server.flags.Flags.optionalBackgroundInstallControl() + || SystemProperties.getBoolean( + "ro.system_settings.service.backgound_install_control_enabled", true)) { + t.traceBegin("StartBackgroundInstallControlService"); + mSystemServiceManager.startService(BackgroundInstallControlService.class); + t.traceEnd(); + } } t.traceBegin("StartMediaProjectionManager"); diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp index 0da17e126d7d..3bce9b54e320 100644 --- a/services/tests/InputMethodSystemServerTests/Android.bp +++ b/services/tests/InputMethodSystemServerTests/Android.bp @@ -84,7 +84,6 @@ android_ravenwood_test { ], srcs: [ "src/com/android/server/inputmethod/**/ClientControllerTest.java", - "src/com/android/server/inputmethod/**/UserDataRepositoryTest.java", ], auto_gen_config: true, } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java index c3a87dafe7ce..79943f6330ba 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java @@ -30,6 +30,7 @@ import android.platform.test.ravenwood.RavenwoodRule; import com.android.server.pm.UserManagerInternal; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -63,6 +64,7 @@ public final class UserDataRepositoryTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); + SecureSettingsWrapper.startTestMode(); mHandler = new Handler(Looper.getMainLooper()); mBindingControllerFactory = new IntFunction<InputMethodBindingController>() { @@ -73,6 +75,11 @@ public final class UserDataRepositoryTest { }; } + @After + public void tearDown() { + SecureSettingsWrapper.endTestMode(); + } + @Test public void testUserDataRepository_addsNewUserInfoOnUserCreatedEvent() { // Create UserDataRepository and capture the user lifecycle listener diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java index 69043f5704de..e982153acbd1 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java @@ -16,19 +16,19 @@ package com.android.server.display.brightness.clamper; +import static android.view.Display.STATE_OFF; import static android.view.Display.STATE_ON; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.BrightnessInfo; import android.hardware.display.DisplayManagerInternal; @@ -40,12 +40,10 @@ import android.testing.TestableContext; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.util.test.FakeSettingsProvider; -import com.android.internal.util.test.FakeSettingsProviderRule; import com.android.server.display.DisplayBrightnessState; import com.android.server.display.DisplayDeviceConfig; -import com.android.server.display.TestUtils; import com.android.server.display.brightness.BrightnessReason; +import com.android.server.display.config.SensorData; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.testutils.OffsettableClock; @@ -63,6 +61,7 @@ import java.util.List; @SmallTest public class BrightnessClamperControllerTest { private static final float FLOAT_TOLERANCE = 0.001f; + private static final int DISPLAY_ID = 2; private final OffsettableClock mClock = new OffsettableClock(); private final TestHandler mTestHandler = new TestHandler(null, mClock); @@ -78,8 +77,12 @@ public class BrightnessClamperControllerTest { @Mock private BrightnessClamperController.DisplayDeviceData mMockDisplayDeviceData; @Mock + private SensorData mMockSensorData; + @Mock private DeviceConfigParameterProvider mMockDeviceConfigParameterProvider; @Mock + private LightSensorController mMockLightSensorController; + @Mock private BrightnessClamper<BrightnessClamperController.DisplayDeviceData> mMockClamper; @Mock private DisplayManagerFlags mFlags; @@ -88,23 +91,17 @@ public class BrightnessClamperControllerTest { @Mock private DisplayManagerInternal.DisplayPowerRequest mMockRequest; - Sensor mLightSensor; - @Mock private DeviceConfig.Properties mMockProperties; private BrightnessClamperController mClamperController; private TestInjector mTestInjector; - @Rule - public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); - @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mLightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor"); mTestInjector = new TestInjector(List.of(mMockClamper), List.of(mMockModifier)); - when(mSensorManager.getDefaultSensor(anyInt())).thenReturn(mLightSensor); - when(mMockModifier.shouldListenToLightSensor()).thenReturn(true); + when(mMockDisplayDeviceData.getDisplayId()).thenReturn(DISPLAY_ID); + when(mMockDisplayDeviceData.getAmbientLightSensor()).thenReturn(mMockSensorData); mClamperController = createBrightnessClamperController(); } @@ -115,6 +112,25 @@ public class BrightnessClamperControllerTest { } @Test + public void testConstructor_ConfiguresLightSensorController() { + verify(mMockLightSensorController).configure(mMockSensorData, DISPLAY_ID); + } + + @Test + public void testConstructor_doesNotStartsLightSensorController() { + verify(mMockLightSensorController, never()).restart(); + } + + @Test + public void testConstructor_startsLightSensorController() { + when(mMockModifier.shouldListenToLightSensor()).thenReturn(true); + + mClamperController = createBrightnessClamperController(); + + verify(mMockLightSensorController).restart(); + } + + @Test public void testStop_RemovesOnPropertiesChangeListener() { ArgumentCaptor<DeviceConfig.OnPropertiesChangedListener> captor = ArgumentCaptor.forClass( DeviceConfig.OnPropertiesChangedListener.class); @@ -152,6 +168,21 @@ public class BrightnessClamperControllerTest { } @Test + public void testOnDisplayChanged_doesNotRestartLightSensor() { + mClamperController.onDisplayChanged(mMockDisplayDeviceData); + + verify(mMockLightSensorController, never()).restart(); + } + + @Test + public void testOnDisplayChanged_restartsLightSensor() { + when(mMockModifier.shouldListenToLightSensor()).thenReturn(true); + mClamperController.onDisplayChanged(mMockDisplayDeviceData); + + verify(mMockLightSensorController).restart(); + } + + @Test public void testClamp_AppliesModifier() { float initialBrightness = 0.2f; boolean initialSlowChange = true; @@ -161,6 +192,26 @@ public class BrightnessClamperControllerTest { } @Test + public void testClamp_restartsLightSensor() { + float initialBrightness = 0.2f; + boolean initialSlowChange = true; + when(mMockModifier.shouldListenToLightSensor()).thenReturn(true); + mClamperController.clamp(mMockRequest, initialBrightness, initialSlowChange, STATE_ON); + + verify(mMockLightSensorController).restart(); + } + + @Test + public void testClamp_stopsLightSensor() { + float initialBrightness = 0.2f; + boolean initialSlowChange = true; + clearInvocations(mMockLightSensorController); + mClamperController.clamp(mMockRequest, initialBrightness, initialSlowChange, STATE_OFF); + + verify(mMockLightSensorController).stop(); + } + + @Test public void testClamp_inactiveClamperNotApplied() { float initialBrightness = 0.8f; boolean initialSlowChange = true; @@ -260,33 +311,17 @@ public class BrightnessClamperControllerTest { } @Test - public void testAmbientLuxChanges() throws Exception { - ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass( - SensorEventListener.class); - - verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor), - anyInt(), any(Handler.class)); - SensorEventListener listener = listenerCaptor.getValue(); - - when(mSensorManager.getSensorList(eq(Sensor.TYPE_ALL))).thenReturn(List.of(mLightSensor)); - - float initialBrightness = 0.8f; - boolean initialSlowChange = true; - - DisplayBrightnessState state = mClamperController.clamp(mMockRequest, initialBrightness, - initialSlowChange, STATE_ON); - assertEquals(initialBrightness, state.getBrightness(), FLOAT_TOLERANCE); + public void testAmbientLuxChanges() { + mTestInjector.mCapturedLightSensorListener.onAmbientLuxChange(50); - listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 50, mClock.now())); verify(mMockModifier).setAmbientLux(50); - - listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 300, mClock.now())); - verify(mMockModifier).setAmbientLux(300); } @Test public void testStop() { + clearInvocations(mMockLightSensorController); mClamperController.stop(); + verify(mMockLightSensorController).stop(); verify(mMockModifier).stop(); verify(mMockClamper).stop(); } @@ -303,6 +338,7 @@ public class BrightnessClamperControllerTest { private final List<BrightnessStateModifier> mModifiers; private BrightnessClamperController.ClamperChangeListener mCapturedChangeListener; + private LightSensorController.LightSensorListener mCapturedLightSensorListener; private TestInjector( List<BrightnessClamper<? super BrightnessClamperController.DisplayDeviceData>> @@ -330,8 +366,15 @@ public class BrightnessClamperControllerTest { @Override List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context, Handler handler, BrightnessClamperController.ClamperChangeListener listener, - DisplayDeviceConfig displayDeviceConfig, SensorManager sensorManager) { + DisplayDeviceConfig displayDeviceConfig) { return mModifiers; } + + @Override + LightSensorController getLightSensorController(SensorManager sensorManager, Context context, + LightSensorController.LightSensorListener listener, Handler handler) { + mCapturedLightSensorListener = listener; + return mMockLightSensorController; + } } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt new file mode 100644 index 000000000000..b742d021f2e9 --- /dev/null +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/LightSensorControllerTest.kt @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display.brightness.clamper + +import android.content.res.Resources +import android.hardware.Sensor +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.os.Handler +import androidx.test.filters.SmallTest +import com.android.server.display.TestUtils +import com.android.server.display.brightness.clamper.LightSensorController.Injector +import com.android.server.display.brightness.clamper.LightSensorController.LightSensorListener +import com.android.server.display.config.SensorData +import com.android.server.display.utils.AmbientFilter +import org.junit.Before +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.eq +import org.mockito.kotlin.inOrder +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoMoreInteractions +import org.mockito.kotlin.whenever + +private const val LIGHT_SENSOR_RATE: Int = 10 +private const val DISPLAY_ID: Int = 3 +private const val NOW: Long = 3_000 + +@SmallTest +class LightSensorControllerTest { + + private val mockSensorManager: SensorManager = mock() + private val mockResources: Resources = mock() + private val mockLightSensorListener: LightSensorListener = mock() + private val mockHandler: Handler = mock() + private val mockAmbientFilter: AmbientFilter = mock() + + private val testInjector = TestInjector() + private val dummySensorData = SensorData() + + private lateinit var controller: LightSensorController + + @Before + fun setUp() { + controller = LightSensorController(mockSensorManager, mockResources, + mockLightSensorListener, mockHandler, testInjector) + } + + fun `does not register light sensor if is not configured`() { + controller.restart() + + verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) + } + + fun `does not register light sensor if missing`() { + controller.configure(dummySensorData, DISPLAY_ID) + controller.restart() + + verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) + } + + fun `register light sensor if configured and present`() { + testInjector.lightSensor = TestUtils + .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) + controller.configure(dummySensorData, DISPLAY_ID) + controller.restart() + + verify(mockSensorManager).registerListener(any(), + testInjector.lightSensor, LIGHT_SENSOR_RATE * 1000, mockHandler) + verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) + } + + fun `register light sensor once if not changed`() { + testInjector.lightSensor = TestUtils + .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) + controller.configure(dummySensorData, DISPLAY_ID) + + controller.restart() + controller.restart() + + verify(mockSensorManager).registerListener(any(), + testInjector.lightSensor, LIGHT_SENSOR_RATE * 1000, mockHandler) + verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) + } + + fun `register new light sensor and unregister old if changed`() { + val lightSensor1 = TestUtils + .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) + testInjector.lightSensor = lightSensor1 + controller.configure(dummySensorData, DISPLAY_ID) + controller.restart() + + val lightSensor2 = TestUtils + .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) + testInjector.lightSensor = lightSensor2 + controller.configure(dummySensorData, DISPLAY_ID) + controller.restart() + + inOrder { + verify(mockSensorManager).registerListener(any(), + lightSensor1, LIGHT_SENSOR_RATE * 1000, mockHandler) + verify(mockSensorManager).unregisterListener(any<SensorEventListener>()) + verify(mockAmbientFilter).clear() + verify(mockLightSensorListener).onAmbientLuxChange(LightSensorController.INVALID_LUX) + verify(mockSensorManager).registerListener(any(), + lightSensor2, LIGHT_SENSOR_RATE * 1000, mockHandler) + } + verifyNoMoreInteractions(mockSensorManager, mockAmbientFilter, mockLightSensorListener) + } + + fun `notifies listener on ambient lux change`() { + val expectedLux = 40f + val eventLux = 50 + val eventTime = 60L + whenever(mockAmbientFilter.getEstimate(NOW)).thenReturn(expectedLux) + val listenerCaptor = argumentCaptor<SensorEventListener>() + testInjector.lightSensor = TestUtils + .createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT) + controller.configure(dummySensorData, DISPLAY_ID) + controller.restart() + verify(mockSensorManager).registerListener(listenerCaptor.capture(), + eq(testInjector.lightSensor), eq(LIGHT_SENSOR_RATE * 1000), eq(mockHandler)) + + val listener = listenerCaptor.lastValue + listener.onSensorChanged(TestUtils.createSensorEvent(testInjector.lightSensor, + eventLux, eventTime * 1_000_000)) + + inOrder { + verify(mockAmbientFilter).addValue(eventTime, eventLux.toFloat()) + verify(mockLightSensorListener).onAmbientLuxChange(expectedLux) + } + } + + private inner class TestInjector : Injector() { + var lightSensor: Sensor? = null + override fun getLightSensor(sensorManager: SensorManager?, + sensorData: SensorData?, fallbackType: Int): Sensor? { + return lightSensor + } + + override fun getLightSensorRate(resources: Resources?): Int { + return LIGHT_SENSOR_RATE + } + + override fun getAmbientFilter(resources: Resources?): AmbientFilter { + return mockAmbientFilter + } + + override fun getTime(): Long { + return NOW + } + } +}
\ No newline at end of file diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java index 3d03bf218557..e2b93ae3e9e7 100644 --- a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java +++ b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java @@ -205,7 +205,7 @@ public class TestDreamEnvironment { @Override public DreamOverlayConnectionHandler createOverlayConnection( - ComponentName overlayComponent) { + ComponentName overlayComponent, Runnable onDisconnected) { return mDreamOverlayConnectionHandler; } diff --git a/services/tests/mockingservicestests/src/android/service/dreams/DreamOverlayConnectionHandlerTest.java b/services/tests/mockingservicestests/src/android/service/dreams/DreamOverlayConnectionHandlerTest.java index 22d7e7300bba..3e6558532b94 100644 --- a/services/tests/mockingservicestests/src/android/service/dreams/DreamOverlayConnectionHandlerTest.java +++ b/services/tests/mockingservicestests/src/android/service/dreams/DreamOverlayConnectionHandlerTest.java @@ -49,10 +49,6 @@ import java.util.function.Consumer; @SmallTest @RunWith(AndroidJUnit4.class) public class DreamOverlayConnectionHandlerTest { - private static final int MIN_CONNECTION_DURATION_MS = 100; - private static final int MAX_RECONNECT_ATTEMPTS = 3; - private static final int BASE_RECONNECT_DELAY_MS = 50; - @Mock private Context mContext; @Mock @@ -63,6 +59,8 @@ public class DreamOverlayConnectionHandlerTest { private IDreamOverlay mOverlayService; @Mock private IDreamOverlayClient mOverlayClient; + @Mock + private Runnable mOnDisconnectRunnable; private TestLooper mTestLooper; private DreamOverlayConnectionHandler mDreamOverlayConnectionHandler; @@ -75,9 +73,7 @@ public class DreamOverlayConnectionHandlerTest { mContext, mTestLooper.getLooper(), mServiceIntent, - MIN_CONNECTION_DURATION_MS, - MAX_RECONNECT_ATTEMPTS, - BASE_RECONNECT_DELAY_MS, + mOnDisconnectRunnable, new TestInjector(mConnection)); } @@ -119,12 +115,14 @@ public class DreamOverlayConnectionHandlerTest { mTestLooper.dispatchAll(); // No client yet, so we shouldn't have executed verify(consumer, never()).accept(mOverlayClient); + verify(mOnDisconnectRunnable, never()).run(); provideClient(); // Service disconnected before looper could handle the message. disconnectService(); mTestLooper.dispatchAll(); verify(consumer, never()).accept(mOverlayClient); + verify(mOnDisconnectRunnable).run(); } @Test @@ -237,8 +235,7 @@ public class DreamOverlayConnectionHandlerTest { @Override public PersistentServiceConnection<IDreamOverlay> buildConnection(Context context, - Handler handler, Intent serviceIntent, int minConnectionDurationMs, - int maxReconnectAttempts, int baseReconnectDelayMs) { + Handler handler, Intent serviceIntent) { return mConnection; } } diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java index 75e8e68dd98a..72883e269a65 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/UserWakeupStoreTest.java @@ -134,6 +134,18 @@ public class UserWakeupStoreTest { } @Test + public void testOnUserStarting_userIsRemovedFromTheStore() { + mUserWakeupStore.addUserWakeup(USER_ID_1, TEST_TIMESTAMP - 19_000); + mUserWakeupStore.addUserWakeup(USER_ID_2, TEST_TIMESTAMP - 7_000); + mUserWakeupStore.addUserWakeup(USER_ID_3, TEST_TIMESTAMP - 13_000); + assertEquals(3, mUserWakeupStore.getUserIdsToWakeup(TEST_TIMESTAMP).length); + mUserWakeupStore.onUserStarting(USER_ID_3); + // getWakeupTimeForUser returns negative wakeup time if there is no entry for user. + assertEquals(-1, mUserWakeupStore.getWakeupTimeForUser(USER_ID_3)); + assertEquals(2, mUserWakeupStore.getUserIdsToWakeup(TEST_TIMESTAMP).length); + } + + @Test public void testGetNextUserWakeup() { mUserWakeupStore.addUserWakeup(USER_ID_1, TEST_TIMESTAMP - 19_000); mUserWakeupStore.addUserWakeup(USER_ID_2, TEST_TIMESTAMP - 3_000); 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 2a670294a470..7aec42b7eceb 100644 --- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java @@ -72,9 +72,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.security.KeyStoreAuthorization; import android.service.trust.GrantTrustResult; @@ -124,9 +121,6 @@ public class TrustManagerServiceTest { .build(); @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - - @Rule public final MockContext mMockContext = new MockContext( ApplicationProvider.getApplicationContext()); @@ -418,7 +412,6 @@ public class TrustManagerServiceTest { // user, not the profile. This matches the authentication that is needed to unlock the device // for the profile again. @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testLockDeviceForManagedProfileWithUnifiedChallenge_usesParentBiometricSids() throws Exception { setupMocksForProfile(/* unifiedChallenge= */ true); @@ -617,7 +610,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockEnabled_whenWeakFingerprintIsSetupAndAllowed() throws Exception { setupStrongAuthTrackerToAllowEverything(); @@ -626,7 +618,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockEnabled_whenWeakFaceIsSetupAndAllowed() throws Exception { setupStrongAuthTrackerToAllowEverything(); setupFace(SensorProperties.STRENGTH_WEAK); @@ -634,7 +625,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockEnabled_whenConvenienceFingerprintIsSetupAndAllowed() throws Exception { setupStrongAuthTrackerToAllowEverything(); @@ -643,7 +633,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockEnabled_whenConvenienceFaceIsSetupAndAllowed() throws Exception { setupStrongAuthTrackerToAllowEverything(); @@ -652,7 +641,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenStrongAuthRequired() throws Exception { setupStrongAuthTracker(StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, true); setupFace(SensorProperties.STRENGTH_WEAK); @@ -660,7 +648,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenNonStrongBiometricNotAllowed() throws Exception { setupStrongAuthTracker(StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED, /* isNonStrongBiometricAllowed= */ false); @@ -669,7 +656,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenWeakFingerprintSensorIsPresentButNotEnrolled() throws Exception { setupStrongAuthTrackerToAllowEverything(); @@ -678,7 +664,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenWeakFaceSensorIsPresentButNotEnrolled() throws Exception { setupStrongAuthTrackerToAllowEverything(); @@ -687,7 +672,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenWeakFingerprintIsSetupButForbiddenByDevicePolicy() throws Exception { @@ -699,7 +683,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenWeakFaceIsSetupButForbiddenByDevicePolicy() throws Exception { setupStrongAuthTrackerToAllowEverything(); @@ -710,7 +693,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenOnlyStrongFingerprintIsSetup() throws Exception { setupStrongAuthTrackerToAllowEverything(); setupFingerprint(SensorProperties.STRENGTH_STRONG); @@ -718,7 +700,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenOnlyStrongFaceIsSetup() throws Exception { setupStrongAuthTrackerToAllowEverything(); setupFace(SensorProperties.STRENGTH_STRONG); @@ -726,7 +707,6 @@ public class TrustManagerServiceTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) public void testKeystoreWeakUnlockDisabled_whenNoBiometricsAreSetup() throws Exception { setupStrongAuthTrackerToAllowEverything(); verifyWeakUnlockDisabled(); diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index 30e3b1808819..dbab54b76a2e 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -672,6 +672,61 @@ public class UserControllerTest { new HashSet<>(mUserController.getRunningUsersLU())); } + /** Test scheduling stopping of background users - reschedule if current user is a guest. */ + @Test + public void testScheduleStopOfBackgroundUser_rescheduleWhenGuest() throws Exception { + mSetFlagsRule.enableFlags(android.multiuser.Flags.FLAG_SCHEDULE_STOP_OF_BACKGROUND_USER); + + mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true, + /* maxRunningUsers= */ 10, /* delayUserDataLocking= */ false, + /* backgroundUserScheduledStopTimeSecs= */ 2); + + final int TEST_USER_GUEST = 902; + setUpUser(TEST_USER_GUEST, UserInfo.FLAG_GUEST); + + setUpUser(TEST_USER_ID2, NO_USERINFO_FLAGS); + + // Switch to TEST_USER_ID from user 0 + int numberOfUserSwitches = 0; + addForegroundUserAndContinueUserSwitch(TEST_USER_ID, UserHandle.USER_SYSTEM, + ++numberOfUserSwitches, false, + /* expectScheduleBackgroundUserStopping= */ false); + assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID), + mUserController.getRunningUsersLU()); + + // Switch to TEST_USER_GUEST from TEST_USER_ID + addForegroundUserAndContinueUserSwitch(TEST_USER_GUEST, TEST_USER_ID, + ++numberOfUserSwitches, false, + /* expectScheduleBackgroundUserStopping= */ true); + assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_GUEST), + mUserController.getRunningUsersLU()); + + // Allow the post-switch processing to complete. + // TEST_USER_ID may be scheduled for stopping, but it shouldn't actually stop since the + // current user is a Guest. + assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID); + assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_GUEST); + assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_GUEST), + mUserController.getRunningUsersLU()); + + // Switch to TEST_USER_ID2 from TEST_USER_GUEST + // Guests are automatically stopped in the background, so it won't be scheduled. + addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_GUEST, + ++numberOfUserSwitches, true, + /* expectScheduleBackgroundUserStopping= */ false); + assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID, TEST_USER_ID2), + mUserController.getRunningUsersLU()); + + // Allow the post-switch processing to complete. + // TEST_USER_ID should *still* be scheduled for stopping, since we skipped stopping it + // earlier. + assertAndProcessScheduledStopBackgroundUser(true, TEST_USER_ID); + assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_GUEST); + assertAndProcessScheduledStopBackgroundUser(false, TEST_USER_ID2); + assertEquals(Arrays.asList(SYSTEM_USER_ID, TEST_USER_ID2), + mUserController.getRunningUsersLU()); + } + /** * Process queued SCHEDULED_STOP_BACKGROUND_USER_MSG message, if expected. * @param userId the user we are checking to see whether it is scheduled. @@ -682,11 +737,11 @@ public class UserControllerTest { boolean expectScheduled, @Nullable Integer userId) { TestHandler handler = mInjector.mHandler; if (expectScheduled) { - assertTrue(handler.hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId)); + assertTrue(handler.hasEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId)); handler.removeMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId); mUserController.processScheduledStopOfBackgroundUser(userId); } else { - assertFalse(handler.hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId)); + assertFalse(handler.hasEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, userId)); } } @@ -1534,9 +1589,9 @@ public class UserControllerTest { mInjector.mHandler.clearAllRecordedMessages(); // Verify that continueUserSwitch worked as expected continueAndCompleteUserSwitch(userState, oldUserId, newUserId); - assertEquals(mInjector.mHandler - .hasMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, expectedOldUserId), - expectScheduleBackgroundUserStopping); + assertEquals(expectScheduleBackgroundUserStopping, + mInjector.mHandler + .hasEqualMessages(SCHEDULED_STOP_BACKGROUND_USER_MSG, expectedOldUserId)); verify(mInjector, times(expectedNumberOfCalls)).dismissUserSwitchingDialog(any()); continueUserSwitchAssertions(oldUserId, newUserId, expectOldUserStopping, expectScheduleBackgroundUserStopping); @@ -1810,6 +1865,13 @@ public class UserControllerTest { } private static class TestHandler extends Handler { + /** + * Keeps an accessible copy of messages that were queued for us to query. + * + * WARNING: queued messages get added to this, but processed/removed messages to NOT + * automatically get removed. This can lead to confusing bugs. Maybe one day someone will + * fix this, but in the meantime, this is your warning. + */ private final List<Message> mMessages = new ArrayList<>(); TestHandler(Looper looper) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index f9077c4ae602..93fc071a5bb7 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -196,11 +196,6 @@ public class LockSettingsServiceTestable extends LockSettingsService { } @Override - void setKeystorePassword(byte[] password, int userHandle) { - - } - - @Override void initKeystoreSuperKeys(int userId, SyntheticPassword sp, boolean allowExisting) { } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index d6c0fef9649a..18752847910b 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -781,6 +781,34 @@ public class VibratorManagerServiceTest { } @Test + @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_CANCEL_BY_APPOPS) + public void vibrate_thenDeniedAppOps_getsCancelled() throws Throwable { + mockVibrators(1); + VibratorManagerService service = createSystemReadyService(); + + var vib = vibrate(service, + VibrationEffect.createWaveform(new long[]{100, 100, 100, 100}, 0), RINGTONE_ATTRS); + + assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS)); + + when(mAppOpsManagerMock.checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE), + eq(AudioAttributes.USAGE_NOTIFICATION_RINGTONE), anyInt(), anyString())) + .thenReturn(AppOpsManager.MODE_IGNORED); + + service.mAppOpsChangeListener.onOpChanged(AppOpsManager.OP_VIBRATE, null); + + assertTrue(waitUntil(s -> vib.hasEnded(), service, TEST_TIMEOUT_MILLIS)); + + var statsInfoCaptor = ArgumentCaptor.forClass(VibrationStats.StatsInfo.class); + verify(mVibratorFrameworkStatsLoggerMock, timeout(TEST_TIMEOUT_MILLIS)) + .writeVibrationReportedAsync(statsInfoCaptor.capture()); + + VibrationStats.StatsInfo touchMetrics = statsInfoCaptor.getAllValues().get(0); + assertEquals(Vibration.Status.CANCELLED_BY_APP_OPS.getProtoEnumValue(), + touchMetrics.status); + } + + @Test public void vibrate_withVibrationAttributes_usesCorrespondingAudioUsageInAppOpsManager() { VibratorManagerService service = createSystemReadyService(); diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index c67d1ec63827..8b4d7796290c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -30,6 +30,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.ActivityRecord.State.STOPPED; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -245,6 +246,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { assertTrue("Animation scheduled", backNavigationInfo.isPrepareRemoteAnimation()); // reset drawing status + testCase.recordBack.setState(STOPPED, "stopped"); backNavigationInfo.onBackNavigationFinished(false); mBackNavigationController.clearBackAnimations(); makeWindowVisibleAndDrawn(testCase.recordFront.findMainWindow()); @@ -937,6 +939,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { testCase.recordFront = record2; testCase.windowBack = window1; testCase.windowFront = window2; + record1.setState(STOPPED, "stopped"); return testCase; } diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index ac1aa20b322f..3a854511e3de 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -4271,6 +4271,27 @@ public class SizeCompatTests extends WindowTestsBase { } + @Test + public void testInsetOverrideNotAppliedInFreeform() { + final int notchHeight = 100; + final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2800) + .setNotch(notchHeight) + .build(); + setUpApp(display); + + // Simulate inset override for legacy app bound behaviour + mActivity.mResolveConfigHint.mUseOverrideInsetsForConfig = true; + // Set task as freeform + mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); + prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); + + Rect bounds = new Rect(mActivity.getWindowConfiguration().getBounds()); + Rect appBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds()); + // App bounds should not include insets and should match bounds when in freeform. + assertEquals(new Rect(0, 0, 1000, 2800), appBounds); + assertEquals(new Rect(0, 0, 1000, 2800), bounds); + } + private void assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity( float letterboxVerticalPositionMultiplier, Rect fixedOrientationLetterbox, Rect sizeCompatUnscaled, Rect sizeCompatScaled) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java index 24ebad60a191..fcf7a3fe79c1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java @@ -78,7 +78,6 @@ import android.app.IApplicationThread; import android.content.pm.ActivityInfo; import android.graphics.Rect; import android.os.Binder; -import android.os.Bundle; import android.os.IBinder; import android.os.InputConfig; import android.os.Process; @@ -94,7 +93,6 @@ import android.util.ArraySet; import android.util.MergedConfiguration; import android.view.ContentRecordingSession; import android.view.IWindow; -import android.view.IWindowSession; import android.view.InputChannel; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -265,69 +263,7 @@ public class WindowManagerServiceTests extends WindowTestsBase { } @Test - public void testRelayoutExitingWindow_legacy() { - mSetFlagsRule.disableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO); - - final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin"); - final WindowSurfaceController surfaceController = mock(WindowSurfaceController.class); - win.mWinAnimator.mSurfaceController = surfaceController; - win.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN; - doReturn(true).when(surfaceController).hasSurface(); - spyOn(win.mTransitionController); - doReturn(true).when(win.mTransitionController).isShellTransitionsEnabled(); - doReturn(true).when(win.mTransitionController).inTransition( - eq(win.mActivityRecord)); - win.mViewVisibility = View.VISIBLE; - win.mHasSurface = true; - win.mActivityRecord.mAppStopped = true; - mWm.mWindowMap.put(win.mClient.asBinder(), win); - spyOn(mWm.mWindowPlacerLocked); - // Skip unnecessary operations of relayout. - doNothing().when(mWm.mWindowPlacerLocked).performSurfacePlacement(anyBoolean()); - final int w = 100; - final int h = 200; - final ClientWindowFrames outFrames = new ClientWindowFrames(); - final MergedConfiguration outConfig = new MergedConfiguration(); - final SurfaceControl outSurfaceControl = new SurfaceControl(); - final InsetsState outInsetsState = new InsetsState(); - final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array(); - final Bundle outBundle = new Bundle(); - mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.GONE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - // The window is in transition, so its destruction is deferred. - assertTrue(win.mAnimatingExit); - assertFalse(win.mDestroying); - assertTrue(win.mTransitionController.mAnimatingExitWindows.contains(win)); - - win.mAnimatingExit = false; - win.mViewVisibility = View.VISIBLE; - win.mActivityRecord.setVisibleRequested(false); - win.mActivityRecord.setVisible(false); - mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.GONE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - // Because the window is already invisible, it doesn't need to apply exiting animation - // and WMS#tryStartExitingAnimation() will destroy the surface directly. - assertFalse(win.mAnimatingExit); - assertFalse(win.mHasSurface); - assertNull(win.mWinAnimator.mSurfaceController); - - // Invisible requested activity should not get the last config even if its view is visible. - mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - assertEquals(0, outConfig.getMergedConfiguration().densityDpi); - // Non activity window can still get the last config. - win.mActivityRecord = null; - win.fillClientWindowFramesAndConfiguration(outFrames, outConfig, - null /* outActivityWindowInfo*/, false /* useLatestConfig */, - true /* relayoutVisible */); - assertEquals(win.getConfiguration().densityDpi, - outConfig.getMergedConfiguration().densityDpi); - } - - @Test public void testRelayoutExitingWindow() { - mSetFlagsRule.enableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO); - final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin"); final WindowSurfaceController surfaceController = mock(WindowSurfaceController.class); win.mWinAnimator.mSurfaceController = surfaceController; @@ -483,15 +419,8 @@ public class WindowManagerServiceTests extends WindowTestsBase { win.mRelayoutSeq = 1; seq = 2; } - if (Flags.windowSessionRelayoutInfo()) { - mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq, - 0, new WindowRelayoutResult()); - } else { - mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq, - 0, new ClientWindowFrames(), new MergedConfiguration(), - new SurfaceControl(), new InsetsState(), new InsetsSourceControl.Array(), - new Bundle()); - } + mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq, + 0, new WindowRelayoutResult()); ArgumentCaptor<Integer> changedFlags = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Integer> changedPrivateFlags = ArgumentCaptor.forClass(Integer.class); @@ -1364,70 +1293,8 @@ public class WindowManagerServiceTests extends WindowTestsBase { } @Test - public void testRelayout_appWindowSendActivityWindowInfo_legacy() { - mSetFlagsRule.enableFlags(Flags.FLAG_ACTIVITY_WINDOW_INFO_FLAG); - mSetFlagsRule.disableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO); - - // Skip unnecessary operations of relayout. - spyOn(mWm.mWindowPlacerLocked); - doNothing().when(mWm.mWindowPlacerLocked).performSurfacePlacement(anyBoolean()); - - final Task task = createTask(mDisplayContent); - final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "appWindow"); - mWm.mWindowMap.put(win.mClient.asBinder(), win); - - final int w = 100; - final int h = 200; - final ClientWindowFrames outFrames = new ClientWindowFrames(); - final MergedConfiguration outConfig = new MergedConfiguration(); - final SurfaceControl outSurfaceControl = new SurfaceControl(); - final InsetsState outInsetsState = new InsetsState(); - final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array(); - final Bundle outBundle = new Bundle(); - - final ActivityRecord activity = win.mActivityRecord; - final ActivityWindowInfo expectedInfo = new ActivityWindowInfo(); - expectedInfo.set(true, new Rect(0, 0, 1000, 2000), new Rect(0, 0, 500, 2000)); - doReturn(expectedInfo).when(activity).getActivityWindowInfo(); - activity.setVisibleRequested(false); - activity.setVisible(false); - - mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - - // No latest reported value, so return empty when activity is invisible - final ActivityWindowInfo activityWindowInfo = outBundle.getParcelable( - IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO, ActivityWindowInfo.class); - assertEquals(new ActivityWindowInfo(), activityWindowInfo); - - activity.setVisibleRequested(true); - activity.setVisible(true); - - mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - - // Report the latest when activity is visible. - final ActivityWindowInfo activityWindowInfo2 = outBundle.getParcelable( - IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO, ActivityWindowInfo.class); - assertEquals(expectedInfo, activityWindowInfo2); - - expectedInfo.set(false, new Rect(0, 0, 1000, 2000), new Rect(0, 0, 1000, 2000)); - activity.setVisibleRequested(false); - activity.setVisible(false); - - mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.VISIBLE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - - // Report the last reported value when activity is invisible. - final ActivityWindowInfo activityWindowInfo3 = outBundle.getParcelable( - IWindowSession.KEY_RELAYOUT_BUNDLE_ACTIVITY_WINDOW_INFO, ActivityWindowInfo.class); - assertEquals(activityWindowInfo2, activityWindowInfo3); - } - - @Test public void testRelayout_appWindowSendActivityWindowInfo() { mSetFlagsRule.enableFlags(Flags.FLAG_ACTIVITY_WINDOW_INFO_FLAG); - mSetFlagsRule.enableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO); // Skip unnecessary operations of relayout. spyOn(mWm.mWindowPlacerLocked); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index b152c3e5355f..e13376b34e7b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -86,7 +86,6 @@ import android.content.res.Configuration; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; -import android.os.Bundle; import android.os.IBinder; import android.os.InputConfig; import android.os.RemoteException; @@ -114,7 +113,6 @@ import androidx.test.filters.SmallTest; import com.android.server.testutils.StubTransaction; import com.android.server.wm.SensitiveContentPackages.PackageInfo; -import com.android.window.flags.Flags; import org.junit.After; import org.junit.Test; @@ -1369,67 +1367,7 @@ public class WindowStateTests extends WindowTestsBase { @SetupWindows(addWindows = {W_INPUT_METHOD}) @Test - public void testImeTargetChangeListener_OnImeTargetOverlayVisibilityChanged_legacy() { - mSetFlagsRule.disableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO); - - final TestImeTargetChangeListener listener = new TestImeTargetChangeListener(); - mWm.mImeTargetChangeListener = listener; - - // Scenario 1: test addWindow/relayoutWindow to add Ime layering overlay window as visible. - final WindowToken windowToken = createTestWindowToken(TYPE_APPLICATION_OVERLAY, - mDisplayContent); - final IWindow client = new TestIWindow(); - final Session session = getTestSession(); - final ClientWindowFrames outFrames = new ClientWindowFrames(); - final MergedConfiguration outConfig = new MergedConfiguration(); - final SurfaceControl outSurfaceControl = new SurfaceControl(); - final InsetsState outInsetsState = new InsetsState(); - final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array(); - final Bundle outBundle = new Bundle(); - final WindowManager.LayoutParams params = new WindowManager.LayoutParams( - TYPE_APPLICATION_OVERLAY); - params.setTitle("imeLayeringTargetOverlay"); - params.token = windowToken.token; - params.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM; - - mWm.addWindow(session, client, params, View.VISIBLE, DEFAULT_DISPLAY, - 0 /* userUd */, WindowInsets.Type.defaultVisible(), null, new InsetsState(), - new InsetsSourceControl.Array(), new Rect(), new float[1]); - mWm.relayoutWindow(session, client, params, 100, 200, View.VISIBLE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - waitHandlerIdle(mWm.mH); - - final WindowState imeLayeringTargetOverlay = mDisplayContent.getWindow( - w -> w.mClient.asBinder() == client.asBinder()); - assertThat(imeLayeringTargetOverlay.isVisible()).isTrue(); - assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder()); - assertThat(listener.mIsRemoved).isFalse(); - assertThat(listener.mIsVisibleForImeTargetOverlay).isTrue(); - - // Scenario 2: test relayoutWindow to let the Ime layering target overlay window invisible. - mWm.relayoutWindow(session, client, params, 100, 200, View.GONE, 0, 0, 0, - outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle); - waitHandlerIdle(mWm.mH); - - assertThat(imeLayeringTargetOverlay.isVisible()).isFalse(); - assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder()); - assertThat(listener.mIsRemoved).isFalse(); - assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse(); - - // Scenario 3: test removeWindow to remove the Ime layering target overlay window. - mWm.removeClientToken(session, client.asBinder()); - waitHandlerIdle(mWm.mH); - - assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder()); - assertThat(listener.mIsRemoved).isTrue(); - assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse(); - } - - @SetupWindows(addWindows = {W_INPUT_METHOD}) - @Test public void testImeTargetChangeListener_OnImeTargetOverlayVisibilityChanged() { - mSetFlagsRule.enableFlags(Flags.FLAG_WINDOW_SESSION_RELAYOUT_INFO); - final TestImeTargetChangeListener listener = new TestImeTargetChangeListener(); mWm.mImeTargetChangeListener = listener; diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java index eadb726bf63b..2b515c9b5cd1 100644 --- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java +++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java @@ -64,6 +64,14 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable { * @hide */ public static final int DEFAULT_DESTINATION_PORT = DESTINATION_PORT_ANY; + /** + * @hide + */ + public static final int MAX_STRING_LENGTH = 256; + /** + * @hide + */ + public static final int MAX_LIST_SIZE = 100; /** * Builder class for {@link VisualVoicemailSmsFilterSettings} objects. @@ -82,11 +90,16 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable { /** * Sets the client prefix for the visual voicemail SMS filter. The client prefix will appear * at the start of a visual voicemail SMS message, followed by a colon(:). + * @throws IllegalArgumentException if the string length is greater than 256 characters */ public Builder setClientPrefix(String clientPrefix) { if (clientPrefix == null) { throw new IllegalArgumentException("Client prefix cannot be null"); } + if (clientPrefix.length() > MAX_STRING_LENGTH) { + throw new IllegalArgumentException("Client prefix cannot be greater than " + + MAX_STRING_LENGTH + " characters"); + } mClientPrefix = clientPrefix; return this; } @@ -95,11 +108,25 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable { * Sets the originating number allow list for the visual voicemail SMS filter. If the list * is not null only the SMS messages from a number in the list can be considered as a visual * voicemail SMS. Otherwise, messages from any address will be considered. + * @throws IllegalArgumentException if the size of the originatingNumbers list is greater + * than 100 elements + * @throws IllegalArgumentException if an element within the originatingNumbers list has + * a string length greater than 256 */ public Builder setOriginatingNumbers(List<String> originatingNumbers) { if (originatingNumbers == null) { throw new IllegalArgumentException("Originating numbers cannot be null"); } + if (originatingNumbers.size() > MAX_LIST_SIZE) { + throw new IllegalArgumentException("The originatingNumbers list size cannot be" + + " greater than " + MAX_STRING_LENGTH + " elements"); + } + for (String num : originatingNumbers) { + if (num != null && num.length() > MAX_STRING_LENGTH) { + throw new IllegalArgumentException("Numbers within the originatingNumbers list" + + " cannot be greater than" + MAX_STRING_LENGTH + " characters"); + } + } mOriginatingNumbers = originatingNumbers; return this; } diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt index d0e56268a27d..0c3c7e2af6f2 100644 --- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt @@ -17,9 +17,6 @@ package android.trust.test import android.content.pm.PackageManager -import android.platform.test.annotations.RequiresFlagsDisabled -import android.platform.test.annotations.RequiresFlagsEnabled -import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.service.trust.GrantTrustResult import android.trust.BaseTrustAgentService import android.trust.TrustTestActivity @@ -58,7 +55,6 @@ class GrantAndRevokeTrustTest { .around(ScreenLockRule()) .around(lockStateTrackingRule) .around(trustAgentRule) - .around(DeviceFlagsValueProvider.createCheckFlagsRule()) @Before fun manageTrust() { @@ -93,7 +89,6 @@ class GrantAndRevokeTrustTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) fun grantCannotActivelyUnlockDevice() { // On automotive, trust agents can actively unlock the device. assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) @@ -120,24 +115,6 @@ class GrantAndRevokeTrustTest { } @Test - @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) - fun grantCouldCauseWrongDeviceLockedStateDueToBug() { - // On automotive, trust agents can actively unlock the device. - assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) - - // Verify that b/296464083 exists. That is, when the device is locked - // and a trust agent grants trust, the deviceLocked state incorrectly - // becomes false even though the device correctly remains locked. - uiDevice.sleep() - lockStateTrackingRule.assertLocked() - trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {} - uiDevice.wakeUp() - uiDevice.sleep() - await() - lockStateTrackingRule.assertUnlockedButNotReally() - } - - @Test fun grantDoesNotCallBack() { val callback = mock<(GrantTrustResult) -> Unit>() trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0, callback) diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt index 01218099f34c..80d79478c898 100644 --- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt @@ -64,13 +64,6 @@ class LockStateTrackingRule : TestRule { wait("not trusted") { trustState.trusted == false } } - // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2 - fun assertUnlockedButNotReally() { - wait("device unlocked") { !keyguardManager.isDeviceLocked } - wait("not trusted") { trustState.trusted == false } - wait("keyguard locked") { windowManager.isKeyguardLocked } - } - fun assertUnlockedAndTrusted() { wait("device unlocked") { !keyguardManager.isDeviceLocked } wait("trusted") { trustState.trusted == true } |