diff options
90 files changed, 3612 insertions, 358 deletions
diff --git a/Android.bp b/Android.bp index b0a1f93acd97..287f271be384 100644 --- a/Android.bp +++ b/Android.bp @@ -298,6 +298,7 @@ java_defaults { "contacts-provider-platform-compat-config", ], libs: [ + "androidx.annotation_annotation", "app-compat-annotations", "ext", "framework-updatable-stubs-module_libs_api", diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp index 2182f0bc2501..23464f879518 100644 --- a/apct-tests/perftests/core/Android.bp +++ b/apct-tests/perftests/core/Android.bp @@ -43,12 +43,13 @@ android_test { "apct-perftests-resources-manager-apps", "apct-perftests-utils", "collector-device-lib", + "core-tests-support", "guava", ], libs: ["android.test.base"], - java_resources: [ ":GoogleFontDancingScript", ], + java_resources: [":GoogleFontDancingScript"], data: [":perfetto_artifacts"], diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java index 03c9d43d3258..adcd5710ef19 100644 --- a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java +++ b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java @@ -158,14 +158,6 @@ public class ExpensiveObjectsPerfTest { } @Test - public void timeNewSimpleDateFormat() { - BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); - while (state.keepRunning()) { - new SimpleDateFormat(); - } - } - - @Test public void timeClonedSimpleDateFormat() { SimpleDateFormat sdf = new SimpleDateFormat(); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java new file mode 100644 index 000000000000..694d609cd950 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import libcore.java.security.TestKeyStore; +import libcore.javax.net.ssl.TestSSLContext; +import libcore.javax.net.ssl.TestSSLSocketPair; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.net.ssl.SSLSocket; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SSLLoopbackPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void time() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TestSSLContext context = + TestSSLContext.create(TestKeyStore.getClient(), TestKeyStore.getServer()); + SSLSocket[] sockets = TestSSLSocketPair.connect(context, null, null); + context.close(); + sockets[0].close(); + sockets[1].close(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java new file mode 100644 index 000000000000..bdbbcb0da006 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.net.ssl.SSLSocketFactory; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SSLSocketFactoryPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void time() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SSLSocketFactory.getDefault(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java new file mode 100644 index 000000000000..42dc5811e6db --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@RunWith(Parameterized.class) +@LargeTest +public final class SchemePrefixPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum Strategy { + JAVA() { + @Override + String execute(String spec) { + int colon = spec.indexOf(':'); + + if (colon < 1) { + return null; + } + + for (int i = 0; i < colon; i++) { + char c = spec.charAt(i); + if (!isValidSchemeChar(i, c)) { + return null; + } + } + + return spec.substring(0, colon).toLowerCase(Locale.US); + } + + private boolean isValidSchemeChar(int index, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + return true; + } + if (index > 0 && ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')) { + return true; + } + return false; + } + }, + + REGEX() { + private final Pattern mPattern = Pattern.compile("^([a-zA-Z][a-zA-Z0-9+\\-.]*):"); + + @Override + String execute(String spec) { + Matcher matcher = mPattern.matcher(spec); + if (matcher.find()) { + return matcher.group(1).toLowerCase(Locale.US); + } else { + return null; + } + } + }; + + abstract String execute(String spec); + } + + @Parameters(name = "mStrategy={0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] {{Strategy.REGEX}, {Strategy.JAVA}}); + } + + @Parameterized.Parameter(0) + public Strategy mStrategy; + + @Test + public void timeSchemePrefix() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStrategy.execute("http://android.com"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java new file mode 100644 index 000000000000..1ec22d217109 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.ArrayList; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SerializationPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private static byte[] bytes(Object o) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + out.writeObject(o); + out.close(); + return baos.toByteArray(); + } + + @Test + public void timeReadIntArray() throws Exception { + int[] intArray = new int[256]; + readSingleObject(intArray); + } + + @Test + public void timeWriteIntArray() throws Exception { + int[] intArray = new int[256]; + writeSingleObject(intArray); + } + + @Test + public void timeReadArrayListInteger() throws Exception { + ArrayList<Integer> object = new ArrayList<Integer>(); + for (int i = 0; i < 256; ++i) { + object.add(i); + } + readSingleObject(object); + } + + @Test + public void timeWriteArrayListInteger() throws Exception { + ArrayList<Integer> object = new ArrayList<Integer>(); + for (int i = 0; i < 256; ++i) { + object.add(i); + } + writeSingleObject(object); + } + + @Test + public void timeReadString() throws Exception { + readSingleObject("hello"); + } + + @Test + public void timeReadObjectStreamClass() throws Exception { + // A special case because serialization itself requires this class. + // (This should really be a unit test.) + ObjectStreamClass osc = ObjectStreamClass.lookup(String.class); + readSingleObject(osc); + } + + @Test + public void timeWriteString() throws Exception { + // String is a special case that avoids JNI. + writeSingleObject("hello"); + } + + @Test + public void timeWriteObjectStreamClass() throws Exception { + // A special case because serialization itself requires this class. + // (This should really be a unit test.) + ObjectStreamClass osc = ObjectStreamClass.lookup(String.class); + writeSingleObject(osc); + } + + // This is + // + // @Testa baseline for the others. + public void timeWriteNoObjects() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + out.reset(); + baos.reset(); + } + out.close(); + } + + private void readSingleObject(Object object) throws Exception { + byte[] bytes = bytes(object); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + ObjectInputStream in = new ObjectInputStream(bais); + in.readObject(); + in.close(); + bais.reset(); + } + } + + private void writeSingleObject(Object o) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + out.writeObject(o); + out.reset(); + baos.reset(); + } + out.close(); + } + + @Test + public void timeWriteEveryKindOfField() throws Exception { + writeSingleObject(new LittleBitOfEverything()); + } + + @Test + public void timeWriteSerializableBoolean() throws Exception { + writeSingleObject(new SerializableBoolean()); + } + + @Test + public void timeWriteSerializableByte() throws Exception { + writeSingleObject(new SerializableByte()); + } + + @Test + public void timeWriteSerializableChar() throws Exception { + writeSingleObject(new SerializableChar()); + } + + @Test + public void timeWriteSerializableDouble() throws Exception { + writeSingleObject(new SerializableDouble()); + } + + @Test + public void timeWriteSerializableFloat() throws Exception { + writeSingleObject(new SerializableFloat()); + } + + @Test + public void timeWriteSerializableInt() throws Exception { + writeSingleObject(new SerializableInt()); + } + + @Test + public void timeWriteSerializableLong() throws Exception { + writeSingleObject(new SerializableLong()); + } + + @Test + public void timeWriteSerializableShort() throws Exception { + writeSingleObject(new SerializableShort()); + } + + @Test + public void timeWriteSerializableReference() throws Exception { + writeSingleObject(new SerializableReference()); + } + + @Test + public void timeReadEveryKindOfField() throws Exception { + readSingleObject(new LittleBitOfEverything()); + } + + @Test + public void timeReadSerializableBoolean() throws Exception { + readSingleObject(new SerializableBoolean()); + } + + @Test + public void timeReadSerializableByte() throws Exception { + readSingleObject(new SerializableByte()); + } + + @Test + public void timeReadSerializableChar() throws Exception { + readSingleObject(new SerializableChar()); + } + + @Test + public void timeReadSerializableDouble() throws Exception { + readSingleObject(new SerializableDouble()); + } + + @Test + public void timeReadSerializableFloat() throws Exception { + readSingleObject(new SerializableFloat()); + } + + @Test + public void timeReadSerializableInt() throws Exception { + readSingleObject(new SerializableInt()); + } + + @Test + public void timeReadSerializableLong() throws Exception { + readSingleObject(new SerializableLong()); + } + + @Test + public void timeReadSerializableShort() throws Exception { + readSingleObject(new SerializableShort()); + } + + @Test + public void timeReadSerializableReference() throws Exception { + readSingleObject(new SerializableReference()); + } + + public static class SerializableBoolean implements Serializable { + boolean mZ; + } + + public static class SerializableByte implements Serializable { + byte mB; + } + + public static class SerializableChar implements Serializable { + char mC; + } + + public static class SerializableDouble implements Serializable { + double mD; + } + + public static class SerializableFloat implements Serializable { + float mF; + } + + public static class SerializableInt implements Serializable { + int mI; + } + + public static class SerializableLong implements Serializable { + long mJ; + } + + public static class SerializableShort implements Serializable { + short mS; + } + + public static class SerializableReference implements Serializable { + Object mL; + } + + public static class LittleBitOfEverything implements Serializable { + boolean mZ; + byte mB; + char mC; + double mD; + float mF; + int mI; + long mJ; + short mS; + Object mL; + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java new file mode 100644 index 000000000000..96e7cb27afef --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** Tests RSA and DSA mSignature creation and verification. */ +@RunWith(Parameterized.class) +@LargeTest +public class SignaturePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mAlgorithm={0}, mImplementation={1}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {Algorithm.MD5WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA1WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA256WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA384WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA512WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA1withDSA, Implementation.BouncyCastle} + }); + } + + @Parameterized.Parameter(0) + public Algorithm mAlgorithm; + + @Parameterized.Parameter(1) + public Implementation mImplementation; + + private static final int DATA_SIZE = 8192; + private static final byte[] DATA = new byte[DATA_SIZE]; + + static { + for (int i = 0; i < DATA_SIZE; i++) { + DATA[i] = (byte) i; + } + } + + public enum Algorithm { + MD5WithRSA, + SHA1WithRSA, + SHA256WithRSA, + SHA384WithRSA, + SHA512WithRSA, + SHA1withDSA + }; + + public enum Implementation { + OpenSSL, + BouncyCastle + }; + + // Key generation and signing aren't part of the benchmark for verification + // so cache the results + private static Map<String, KeyPair> sKeyPairs = new HashMap<String, KeyPair>(); + private static Map<String, byte[]> sSignatures = new HashMap<String, byte[]>(); + + private String mSignatureAlgorithm; + private byte[] mSignature; + private PrivateKey mPrivateKey; + private PublicKey mPublicKey; + + @Before + public void setUp() throws Exception { + this.mSignatureAlgorithm = mAlgorithm.toString(); + + String keyAlgorithm = + mSignatureAlgorithm.substring( + mSignatureAlgorithm.length() - 3, mSignatureAlgorithm.length()); + KeyPair keyPair = sKeyPairs.get(keyAlgorithm); + if (keyPair == null) { + KeyPairGenerator generator = KeyPairGenerator.getInstance(keyAlgorithm); + keyPair = generator.generateKeyPair(); + sKeyPairs.put(keyAlgorithm, keyPair); + } + this.mPrivateKey = keyPair.getPrivate(); + this.mPublicKey = keyPair.getPublic(); + + this.mSignature = sSignatures.get(mSignatureAlgorithm); + if (this.mSignature == null) { + Signature signer = Signature.getInstance(mSignatureAlgorithm); + signer.initSign(keyPair.getPrivate()); + signer.update(DATA); + this.mSignature = signer.sign(); + sSignatures.put(mSignatureAlgorithm, mSignature); + } + } + + @Test + public void timeSign() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Signature signer; + switch (mImplementation) { + case OpenSSL: + signer = Signature.getInstance(mSignatureAlgorithm, "AndroidOpenSSL"); + break; + case BouncyCastle: + signer = Signature.getInstance(mSignatureAlgorithm, "BC"); + break; + default: + throw new RuntimeException(mImplementation.toString()); + } + signer.initSign(mPrivateKey); + signer.update(DATA); + signer.sign(); + } + } + + @Test + public void timeVerify() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Signature verifier; + switch (mImplementation) { + case OpenSSL: + verifier = Signature.getInstance(mSignatureAlgorithm, "AndroidOpenSSL"); + break; + case BouncyCastle: + verifier = Signature.getInstance(mSignatureAlgorithm, "BC"); + break; + default: + throw new RuntimeException(mImplementation.toString()); + } + verifier.initVerify(mPublicKey); + verifier.update(DATA); + verifier.verify(mSignature); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java new file mode 100644 index 000000000000..c25b0ce6d7d9 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java @@ -0,0 +1,112 @@ +/* + * 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Benchmark for java.text.SimpleDateFormat. This tests common formatting, parsing and creation + * operations with a specific focus on TimeZone handling. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SimpleDateFormatPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void time_createFormatWithTimeZone() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + } + } + + @Test + public void time_parseWithTimeZoneShort() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.parse("2000.01.01 PST"); + } + } + + @Test + public void time_parseWithTimeZoneLong() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.parse("2000.01.01 Pacific Standard Time"); + } + } + + @Test + public void time_parseWithoutTimeZone() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.parse("2000.01.01"); + } + } + + @Test + public void time_createAndParseWithTimeZoneShort() throws ParseException { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + sdf.parse("2000.01.01 PST"); + } + } + + @Test + public void time_createAndParseWithTimeZoneLong() throws ParseException { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz"); + sdf.parse("2000.01.01 Pacific Standard Time"); + } + } + + @Test + public void time_formatWithTimeZoneShort() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.format(new Date()); + } + } + + @Test + public void time_formatWithTimeZoneLong() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.format(new Date()); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java new file mode 100644 index 000000000000..eeccb5bd64f4 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Many of these tests are bogus in that the cost will vary wildly depending on inputs. For _my_ + * current purposes, that's okay. But beware! + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StrictMathPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private final double mDouble = 1.2; + private final float mFloat = 1.2f; + private final int mInt = 1; + private final long mLong = 1L; + + /* Values for full line coverage of ceiling function */ + private static final double[] CEIL_DOUBLES = + new double[] { + 3245817.2018463886, + 1418139.083668501, + 3.572936802189103E15, + -4.7828929737254625E249, + 213596.58636369856, + 6.891928421440976E-96, + -7.9318566885477E-36, + -1.9610339084804148E15, + -4.696725715628246E10, + 3742491.296880909, + 7.140274745333553E11 + }; + + /* Values for full line coverage of floor function */ + private static final double[] FLOOR_DOUBLES = + new double[] { + 7.140274745333553E11, + 3742491.296880909, + -4.696725715628246E10, + -1.9610339084804148E15, + 7.049948629370372E-56, + -7.702933170334643E-16, + -1.99657681810579, + -1.1659287182288336E236, + 4.085518816513057E15, + -1500948.440658056, + -2.2316479921415575E7 + }; + + @Test + public void timeAbsD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mDouble); + } + } + + @Test + public void timeAbsF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mFloat); + } + } + + @Test + public void timeAbsI() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mInt); + } + } + + @Test + public void timeAbsL() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mLong); + } + } + + @Test + public void timeAcos() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.acos(mDouble); + } + } + + @Test + public void timeAsin() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.asin(mDouble); + } + } + + @Test + public void timeAtan() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.atan(mDouble); + } + } + + @Test + public void timeAtan2() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.atan2(3, 4); + } + } + + @Test + public void timeCbrt() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.cbrt(mDouble); + } + } + + @Test + public void timeCeilOverInterestingValues() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < CEIL_DOUBLES.length; ++i) { + StrictMath.ceil(CEIL_DOUBLES[i]); + } + } + } + + @Test + public void timeCopySignD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.copySign(mDouble, mDouble); + } + } + + @Test + public void timeCopySignF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.copySign(mFloat, mFloat); + } + } + + @Test + public void timeCos() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.cos(mDouble); + } + } + + @Test + public void timeCosh() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.cosh(mDouble); + } + } + + @Test + public void timeExp() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.exp(mDouble); + } + } + + @Test + public void timeExpm1() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.expm1(mDouble); + } + } + + @Test + public void timeFloorOverInterestingValues() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < FLOOR_DOUBLES.length; ++i) { + StrictMath.floor(FLOOR_DOUBLES[i]); + } + } + } + + @Test + public void timeGetExponentD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.getExponent(mDouble); + } + } + + @Test + public void timeGetExponentF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.getExponent(mFloat); + } + } + + @Test + public void timeHypot() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.hypot(mDouble, mDouble); + } + } + + @Test + public void timeIEEEremainder() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.IEEEremainder(mDouble, mDouble); + } + } + + @Test + public void timeLog() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.log(mDouble); + } + } + + @Test + public void timeLog10() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.log10(mDouble); + } + } + + @Test + public void timeLog1p() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.log1p(mDouble); + } + } + + @Test + public void timeMaxD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mDouble, mDouble); + } + } + + @Test + public void timeMaxF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mFloat, mFloat); + } + } + + @Test + public void timeMaxI() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mInt, mInt); + } + } + + @Test + public void timeMaxL() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mLong, mLong); + } + } + + @Test + public void timeMinD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mDouble, mDouble); + } + } + + @Test + public void timeMinF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mFloat, mFloat); + } + } + + @Test + public void timeMinI() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mInt, mInt); + } + } + + @Test + public void timeMinL() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mLong, mLong); + } + } + + @Test + public void timeNextAfterD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextAfter(mDouble, mDouble); + } + } + + @Test + public void timeNextAfterF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextAfter(mFloat, mFloat); + } + } + + @Test + public void timeNextUpD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextUp(mDouble); + } + } + + @Test + public void timeNextUpF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextUp(mFloat); + } + } + + @Test + public void timePow() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.pow(mDouble, mDouble); + } + } + + @Test + public void timeRandom() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.random(); + } + } + + @Test + public void timeRint() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.rint(mDouble); + } + } + + @Test + public void timeRoundD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.round(mDouble); + } + } + + @Test + public void timeRoundF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.round(mFloat); + } + } + + @Test + public void timeScalbD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.scalb(mDouble, 5); + } + } + + @Test + public void timeScalbF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.scalb(mFloat, 5); + } + } + + @Test + public void timeSignumD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.signum(mDouble); + } + } + + @Test + public void timeSignumF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.signum(mFloat); + } + } + + @Test + public void timeSin() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.sin(mDouble); + } + } + + @Test + public void timeSinh() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.sinh(mDouble); + } + } + + @Test + public void timeSqrt() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.sqrt(mDouble); + } + } + + @Test + public void timeTan() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.tan(mDouble); + } + } + + @Test + public void timeTanh() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.tanh(mDouble); + } + } + + @Test + public void timeToDegrees() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.toDegrees(mDouble); + } + } + + @Test + public void timeToRadians() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.toRadians(mDouble); + } + } + + @Test + public void timeUlpD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.ulp(mDouble); + } + } + + @Test + public void timeUlpF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.ulp(mFloat); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java new file mode 100644 index 000000000000..34fb88bf8627 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +/** Tests the performance of various StringBuilder methods. */ +@RunWith(Parameterized.class) +@LargeTest +public class StringBuilderPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mLength={0}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] {{1}, {10}, {100}}); + } + + @Parameterized.Parameter(0) + public int mLength; + + @Test + public void timeAppendBoolean() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(true); + } + } + } + + @Test + public void timeAppendChar() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append('c'); + } + } + } + + @Test + public void timeAppendCharArray() { + char[] chars = "chars".toCharArray(); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(chars); + } + } + } + + @Test + public void timeAppendCharSequence() { + CharSequence cs = "chars"; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(cs); + } + } + } + + @Test + public void timeAppendSubCharSequence() { + CharSequence cs = "chars"; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(cs); + } + } + } + + @Test + public void timeAppendDouble() { + double d = 1.2; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(d); + } + } + } + + @Test + public void timeAppendFloat() { + float f = 1.2f; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(f); + } + } + } + + @Test + public void timeAppendInt() { + int n = 123; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(n); + } + } + } + + @Test + public void timeAppendLong() { + long l = 123; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(l); + } + } + } + + @Test + public void timeAppendObject() { + // We don't want to time the toString, so ensure we're calling a trivial one... + Object o = + new Object() { + @Override + public String toString() { + return "constant"; + } + }; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(o); + } + } + } + + @Test + public void timeAppendString() { + String s = "chars"; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(s); + } + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java new file mode 100644 index 000000000000..6854c0de9387 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Benchmarks to measure the performance of String.equals for Strings of varying lengths. Each + * benchmarks makes 5 measurements, aiming at covering cases like strings of equal length that are + * not equal, identical strings with different references, strings with different endings, interned + * strings, and strings of different lengths. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringEqualsPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private final String mLong1 = + "Ahead-of-time compilation is possible as the compiler may just convert an instruction" + + " thus: dex code: add-int v1000, v2000, v3000 C code: setIntRegter(1000," + + " call_dex_add_int(getIntRegister(2000), getIntRegister(3000)) This means even" + + " lidinstructions may have code generated, however, it is not expected that code" + + " generate inthis way will perform well. The job of AOT verification is to tell" + + " the compiler thatinstructions are sound and provide tests to detect unsound" + + " sequences so slow path codemay be generated. Other than for totally invalid" + + " code, the verification may fail at AOrrun-time. At AOT time it can be because" + + " of incomplete information, at run-time it can ethat code in a different apk" + + " that the application depends upon has changed. The Dalvikverifier would return" + + " a bool to state whether a Class were good or bad. In ART the fail case becomes" + + " either a soft or hard failure. Classes have new states to represent that a soft" + + " failure occurred at compile time and should be re-verified at run-time."; + + private final String mVeryLong = + "Garbage collection has two phases. The first distinguishes live objects from garbage" + + " objects. The second is reclaiming the rage of garbage objectIn the mark-sweep" + + " algorithm used by Dalvik, the first phase is achievd by computing the closure" + + " of all reachable objects in a process known as tracing from theoots. After" + + " thetrace has completed, garbage objects are reclaimed. Each of these" + + " operations can beparallelized and can be interleaved with the operation of the" + + " applicationTraditionally,the tracing phase dominates the time spent in garbage" + + " collection. The greatreduction ipause time can be achieved by interleaving as" + + " much of this phase as possible with theapplication. If we simply ran the GC in" + + " a separate thread with no other changes, normaloperation of an application" + + " would confound the trace. Abstractly, the GC walks the h oall reachable" + + " objects. When the application is paused, the object graph cannot change.The GC" + + " can therefore walk this structure and assume that all reachable objects" + + " live.When the application is running, this graph may be altered. New nodes may" + + " be addnd edgemay be changed. These changes may cause live objects to be hidden" + + " and falsely recla bythe GC. To avoid this problem a write barrier is used to" + + " intercept and record modifionto objects in a separate structure. After" + + " performing its walk, the GC will revisit theupdated objects and re-validate its" + + " assumptions. Without a card table, the garbagecollector would have to visit" + + " all objects reached during the trace looking for dirtied objects. The cost of" + + " this operation would be proportional to the amount of live data.With a card" + + " table, the cost of this operation is proportional to the amount of updateatThe" + + " write barrier in Dalvik is a card marking write barrier. Card marking is the" + + " proceof noting the location of object connectivity changes on a sub-page" + + " granularity. A caris merely a colorful term for a contiguous extent of memory" + + " smaller than a page, commonsomewhere between 128- and 512-bytes. Card marking" + + " is implemented by instrumenting alllocations in the virtual machine which can" + + " assign a pointer to an object. After themalpointer assignment has occurred, a" + + " byte is written to a byte-map spanning the heap whiccorresponds to the location" + + " of the updated object. This byte map is known as a card taThe garbage" + + " collector visits this card table and looks for written bytes to reckon" + + " thelocation of updated objects. It then rescans all objects located on the" + + " dirty card,correcting liveness assumptions that were invalidated by the" + + " application. While cardmarking imposes a small burden on the application" + + " outside of a garbage collection, theoverhead of maintaining the card table is" + + " paid for by the reduced time spent insidegarbage collection. With the" + + " concurrent garbage collection thread and a write barriersupported by the" + + " interpreter, JIT, and Runtime we modify garbage collection"; + + private final String[][] mShortStrings = + new String[][] { + // Equal, constant comparison + {"a", "a"}, + // Different constants, first character different + {":", " :"}, + // Different constants, last character different, same length + {"ja M", "ja N"}, + // Different constants, different lengths + {"$$$", "$$"}, + // Force execution of code beyond reference equality check + {"hi", new String("hi")} + }; + + private final String[][] mMediumStrings = + new String[][] { + // Equal, constant comparison + {"Hello my name is ", "Hello my name is "}, + // Different constants, different lengths + {"What's your name?", "Whats your name?"}, + // Force execution of code beyond reference equality check + {"Android Runtime", new String("Android Runtime")}, + // Different constants, last character different, same length + {"v3ry Cre@tiVe?****", "v3ry Cre@tiVe?***."}, + // Different constants, first character different, same length + {"!@#$%^&*()_++*^$#@", "0@#$%^&*()_++*^$#@"} + }; + + private final String[][] mLongStrings = + new String[][] { + // Force execution of code beyond reference equality check + {mLong1, new String(mLong1)}, + // Different constants, last character different, same length + {mLong1 + "fun!", mLong1 + "----"}, + // Equal, constant comparison + {mLong1 + mLong1, mLong1 + mLong1}, + // Different constants, different lengths + {mLong1 + "123456789", mLong1 + "12345678"}, + // Different constants, first character different, same length + {"Android Runtime" + mLong1, "android Runtime" + mLong1} + }; + + private final String[][] mVeryLongStrings = + new String[][] { + // Force execution of code beyond reference equality check + {mVeryLong, new String(mVeryLong)}, + // Different constants, different lengths + {mVeryLong + mVeryLong, mVeryLong + " " + mVeryLong}, + // Equal, constant comparison + {mVeryLong + mVeryLong + mVeryLong, mVeryLong + mVeryLong + mVeryLong}, + // Different constants, last character different, same length + {mVeryLong + "77777", mVeryLong + "99999"}, + // Different constants, first character different + {"Android Runtime" + mVeryLong, "android Runtime" + mVeryLong} + }; + + private final String[][] mEndStrings = + new String[][] { + // Different constants, medium but different lengths + {"Hello", "Hello "}, + // Different constants, long but different lengths + {mLong1, mLong1 + "x"}, + // Different constants, very long but different lengths + {mVeryLong, mVeryLong + "?"}, + // Different constants, same medium lengths + {"How are you doing today?", "How are you doing today "}, + // Different constants, short but different lengths + {"1", "1."} + }; + + private final String mTmpStr1 = + "012345678901234567890" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789"; + + private final String mTmpStr2 = + "z012345678901234567890" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678x"; + + private final String[][] mNonalignedStrings = + new String[][] { + // Different non-word aligned medium length strings + {mTmpStr1, mTmpStr1.substring(1)}, + // Different differently non-word aligned medium length strings + {mTmpStr2, mTmpStr2.substring(2)}, + // Different non-word aligned long length strings + {mLong1, mLong1.substring(3)}, + // Different non-word aligned very long length strings + {mVeryLong, mVeryLong.substring(1)}, + // Equal non-word aligned constant strings + {"hello", "hello".substring(1)} + }; + + private final Object[] mObjects = + new Object[] { + // Compare to Double object + new Double(1.5), + // Compare to Integer object + new Integer(9999999), + // Compare to String array + new String[] {"h", "i"}, + // Compare to int array + new int[] {1, 2, 3}, + // Compare to Character object + new Character('a') + }; + + // Check assumptions about how the compiler, new String(String), and String.intern() work. + // Any failures here would invalidate these benchmarks. + @Before + public void setUp() throws Exception { + // String constants are the same object + Assert.assertSame("abc", "abc"); + // new String(String) makes a copy + Assert.assertNotSame("abc", new String("abc")); + // Interned strings are treated like constants, so it is not necessary to + // separately benchmark interned strings. + Assert.assertSame("abc", "abc".intern()); + Assert.assertSame("abc", new String("abc").intern()); + // Compiler folds constant strings into new constants + Assert.assertSame(mLong1 + mLong1, mLong1 + mLong1); + } + + // Benchmark cases of String.equals(null) + @Test + public void timeEqualsNull() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mMediumStrings.length; i++) { + mMediumStrings[i][0].equals(null); + } + } + } + + // Benchmark cases with very short (<5 character) Strings + @Test + public void timeEqualsShort() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mShortStrings.length; i++) { + mShortStrings[i][0].equals(mShortStrings[i][1]); + } + } + } + + // Benchmark cases with medium length (10-15 character) Strings + @Test + public void timeEqualsMedium() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mMediumStrings.length; i++) { + mMediumStrings[i][0].equals(mMediumStrings[i][1]); + } + } + } + + // Benchmark cases with long (>100 character) Strings + @Test + public void timeEqualsLong() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mLongStrings.length; i++) { + mLongStrings[i][0].equals(mLongStrings[i][1]); + } + } + } + + // Benchmark cases with very long (>1000 character) Strings + @Test + public void timeEqualsVeryLong() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mVeryLongStrings.length; i++) { + mVeryLongStrings[i][0].equals(mVeryLongStrings[i][1]); + } + } + } + + // Benchmark cases with non-word aligned Strings + @Test + public void timeEqualsNonWordAligned() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mNonalignedStrings.length; i++) { + mNonalignedStrings[i][0].equals(mNonalignedStrings[i][1]); + } + } + } + + // Benchmark cases with slight differences in the endings + @Test + public void timeEqualsEnd() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mEndStrings.length; i++) { + mEndStrings[i][0].equals(mEndStrings[i][1]); + } + } + } + + // Benchmark cases of comparing a string to a non-string object + @Test + public void timeEqualsNonString() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mMediumStrings.length; i++) { + mMediumStrings[i][0].equals(mObjects[i]); + } + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java new file mode 100644 index 000000000000..79ff646bbfff --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringIsEmptyPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeIsEmpty_NonEmpty() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".isEmpty()); + } + if (!result) throw new RuntimeException(); + } + + @Test + public void timeIsEmpty_Empty() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= ("".isEmpty()); + } + if (!result) throw new RuntimeException(); + } + + @Test + public void timeLengthEqualsZero() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length() == 0); + } + if (!result) throw new RuntimeException(); + } + + @Test + public void timeEqualsEmpty() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= !"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".equals(""); + } + if (!result) throw new RuntimeException(); + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java new file mode 100644 index 000000000000..8dbf9f58fbf8 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringLengthPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeLength() { + int length = 0; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + length = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length(); + } + if (length != 51) throw new RuntimeException(); + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java new file mode 100644 index 000000000000..02194b1b9745 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum StringLengths { + EMPTY(""), + SHORT("short"), + EIGHTY(makeString(80)), + EIGHT_KI(makeString(8192)); + final String mValue; + + StringLengths(String value) { + this.mValue = value; + } + } + + @Parameters(name = "mStringLengths={0}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {StringLengths.EIGHT_KI}, + {StringLengths.EIGHTY}, + {StringLengths.SHORT}, + {StringLengths.EMPTY} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + private static String makeString(int length) { + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + result.append((char) i); + } + return result.toString(); + } + + @Test + public void timeHashCode() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.hashCode(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java new file mode 100644 index 000000000000..b0d1ee4132fa --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringReplaceAllPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + // NOTE: These estimates of MOVEABLE / NON_MOVEABLE are based on a knowledge of + // ART implementation details. They make a difference here because JNI calls related + // to strings took different paths depending on whether the String in question was + // moveable or not. + enum StringLengths { + EMPTY(""), + MOVEABLE_16(makeString(16)), + MOVEABLE_256(makeString(256)), + MOVEABLE_1024(makeString(1024)), + NON_MOVEABLE(makeString(64 * 1024)), + BOOT_IMAGE(java.util.jar.JarFile.MANIFEST_NAME); + + private final String mValue; + + StringLengths(String s) { + this.mValue = s; + } + } + + private static String makeString(int length) { + final String sequence8 = "abcdefghijklmnop"; + final int numAppends = (length / 16) - 1; + StringBuilder stringBuilder = new StringBuilder(length); + + // (n-1) occurrences of "abcdefghijklmnop" + for (int i = 0; i < numAppends; ++i) { + stringBuilder.append(sequence8); + } + + // and one final occurrence of qrstuvwx. + stringBuilder.append("qrstuvwx"); + + return stringBuilder.toString(); + } + + @Parameters(name = "mStringLengths={0}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {StringLengths.BOOT_IMAGE}, + {StringLengths.EMPTY}, + {StringLengths.MOVEABLE_16}, + {StringLengths.MOVEABLE_256}, + {StringLengths.MOVEABLE_1024}, + {StringLengths.NON_MOVEABLE} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + @Test + public void timeReplaceAllTrivialPatternNonExistent() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replaceAll("fish", "0"); + } + } + + @Test + public void timeReplaceTrivialPatternAllRepeated() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replaceAll("jklm", "0"); + } + } + + @Test + public void timeReplaceAllTrivialPatternSingleOccurrence() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replaceAll("qrst", "0"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java new file mode 100644 index 000000000000..d2e657a78608 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringReplacePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum StringLengths { + EMPTY(""), + L_16(makeString(16)), + L_64(makeString(64)), + L_256(makeString(256)), + L_512(makeString(512)); + + private final String mValue; + + StringLengths(String s) { + this.mValue = s; + } + } + + private static String makeString(int length) { + final String sequence8 = "abcdefghijklmnop"; + final int numAppends = (length / 16) - 1; + StringBuilder stringBuilder = new StringBuilder(length); + + // (n-1) occurrences of "abcdefghijklmnop" + for (int i = 0; i < numAppends; ++i) { + stringBuilder.append(sequence8); + } + + // and one final occurrence of qrstuvwx. + stringBuilder.append("qrstuvwx"); + + return stringBuilder.toString(); + } + + @Parameters(name = "mStringLengths={0}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {StringLengths.EMPTY}, + {StringLengths.L_16}, + {StringLengths.L_64}, + {StringLengths.L_256}, + {StringLengths.L_512} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + @Test + public void timeReplaceCharNonExistent() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace('z', '0'); + } + } + + @Test + public void timeReplaceCharRepeated() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace('a', '0'); + } + } + + @Test + public void timeReplaceSingleChar() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace('q', '0'); + } + } + + @Test + public void timeReplaceSequenceNonExistent() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace("fish", "0"); + } + } + + @Test + public void timeReplaceSequenceRepeated() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace("jklm", "0"); + } + } + + @Test + public void timeReplaceSingleSequence() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace("qrst", "0"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java new file mode 100644 index 000000000000..2bb25ac56694 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.regex.Pattern; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringSplitPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeStringSplitComma() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this,is,a,simple,example".split(","); + } + } + + @Test + public void timeStringSplitLiteralDot() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this.is.a.simple.example".split("\\."); + } + } + + @Test + public void timeStringSplitNewline() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this\nis\na\nsimple\nexample\n".split("\n"); + } + } + + @Test + public void timePatternSplitComma() { + Pattern p = Pattern.compile(","); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + p.split("this,is,a,simple,example"); + } + } + + @Test + public void timePatternSplitLiteralDot() { + Pattern p = Pattern.compile("\\."); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + p.split("this.is.a.simple.example"); + } + } + + @Test + public void timeStringSplitHard() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this,is,a,harder,example".split("[,]"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java new file mode 100644 index 000000000000..1efc188f4e4d --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringToBytesPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum StringLengths { + EMPTY(""), + L_16(makeString(16)), + L_64(makeString(64)), + L_256(makeString(256)), + L_512(makeString(512)), + A_16(makeAsciiString(16)), + A_64(makeAsciiString(64)), + A_256(makeAsciiString(256)), + A_512(makeAsciiString(512)); + + private final String mValue; + + StringLengths(String s) { + this.mValue = s; + } + } + + @Parameters(name = "mStringLengths={0}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {StringLengths.EMPTY}, + {StringLengths.L_16}, + {StringLengths.L_64}, + {StringLengths.L_256}, + {StringLengths.L_512}, + {StringLengths.A_16}, + {StringLengths.A_64}, + {StringLengths.A_256}, + {StringLengths.A_512} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + private static String makeString(int length) { + char[] chars = new char[length]; + for (int i = 0; i < length; ++i) { + chars[i] = (char) i; + } + return new String(chars); + } + + private static String makeAsciiString(int length) { + char[] chars = new char[length]; + for (int i = 0; i < length; ++i) { + chars[i] = ((i & 0x7f) != 0) ? (char) (i & 0x7f) : '?'; + } + return new String(chars); + } + + @Test + public void timeGetBytesUtf8() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.getBytes(StandardCharsets.UTF_8); + } + } + + @Test + public void timeGetBytesIso88591() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.getBytes(StandardCharsets.ISO_8859_1); + } + } + + @Test + public void timeGetBytesAscii() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.getBytes(StandardCharsets.US_ASCII); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java new file mode 100644 index 000000000000..b01948aa2255 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringToRealPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mString={0}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {"NaN"}, + {"-1"}, + {"0"}, + {"1"}, + {"1.2"}, + {"-123.45"}, + {"-123.45e8"}, + {"-123.45e36"} + }); + } + + @Parameterized.Parameter(0) + public String mString; + + @Test + public void timeFloat_parseFloat() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Float.parseFloat(mString); + } + } + + @Test + public void timeDouble_parseDouble() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Double.parseDouble(mString); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java new file mode 100644 index 000000000000..f2565550c6c5 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ThreadLocalPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private static final ThreadLocal<char[]> BUFFER = + new ThreadLocal<char[]>() { + @Override + protected char[] initialValue() { + return new char[20]; + } + }; + + @Test + public void timeThreadLocal_get() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + BUFFER.get(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java new file mode 100644 index 000000000000..8274512e1501 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.TimeZone; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class TimeZonePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeTimeZone_getDefault() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getDefault(); + } + } + + @Test + public void timeTimeZone_getTimeZoneUTC() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("UTC"); + } + } + + @Test + public void timeTimeZone_getTimeZone_default() throws Exception { + String defaultId = TimeZone.getDefault().getID(); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone(defaultId); + } + } + + // A time zone with relatively few transitions. + @Test + public void timeTimeZone_getTimeZone_America_Caracas() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("America/Caracas"); + } + } + + // A time zone with a lot of transitions. + @Test + public void timeTimeZone_getTimeZone_America_Santiago() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("America/Santiago"); + } + } + + @Test + public void timeTimeZone_getTimeZone_GMT_plus_10() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("GMT+10"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java new file mode 100644 index 000000000000..2ea834d0b71c --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 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.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.xml.sax.InputSource; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.StringReader; +import java.util.Arrays; +import java.util.Collection; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +// http://code.google.com/p/android/issues/detail?id=18102 +@RunWith(Parameterized.class) +@LargeTest +public final class XMLEntitiesPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mLength={0}, mEntityFraction={1}") + public static Collection<Object[]> data() { + return Arrays.asList( + new Object[][] { + {10, 0}, + {10, 0.5f}, + {10, 1.0f}, + {100, 0}, + {100, 0.5f}, + {100, 1.0f}, + {1000, 0}, + {1000, 0.5f}, + {1000, 1.0f} + }); + } + + @Parameterized.Parameter(0) + public int mLength; + + @Parameterized.Parameter(1) + public float mEntityFraction; + + private XmlPullParserFactory mXmlPullParserFactory; + private DocumentBuilderFactory mDocumentBuilderFactory; + + /** a string like {@code <doc>&&++</doc>}. */ + private String mXml; + + @Before + public void setUp() throws Exception { + mXmlPullParserFactory = XmlPullParserFactory.newInstance(); + mDocumentBuilderFactory = DocumentBuilderFactory.newInstance(); + + StringBuilder xmlBuilder = new StringBuilder(); + xmlBuilder.append("<doc>"); + for (int i = 0; i < (mLength * mEntityFraction); i++) { + xmlBuilder.append("&"); + } + while (xmlBuilder.length() < mLength) { + xmlBuilder.append("+"); + } + xmlBuilder.append("</doc>"); + mXml = xmlBuilder.toString(); + } + + @Test + public void timeXmlParser() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + XmlPullParser parser = mXmlPullParserFactory.newPullParser(); + parser.setInput(new StringReader(mXml)); + while (parser.next() != XmlPullParser.END_DOCUMENT) { + // Keep running + } + } + } + + @Test + public void timeDocumentBuilder() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + DocumentBuilder documentBuilder = mDocumentBuilderFactory.newDocumentBuilder(); + documentBuilder.parse(new InputSource(new StringReader(mXml))); + } + } +} diff --git a/config/boot-image-profile-extra.txt b/config/boot-image-profile-extra.txt new file mode 100644 index 000000000000..e3b187e0a66d --- /dev/null +++ b/config/boot-image-profile-extra.txt @@ -0,0 +1,21 @@ +# +# Copyright (C) 2022 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. +# + +# A list of methods that are found to be latency sensitive. We have this manual +# due to current limitations of our boot image profiling, where knowing what +# methods are latency sensitive is difficult. For example, this method is executed +# in the system server, not on the UI thread of an app. +HSPLandroid/graphics/Color;->luminance()F diff --git a/core/api/system-current.txt b/core/api/system-current.txt index abc2b74c0645..cf3f07f5891d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -230,6 +230,7 @@ package android { field public static final String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL"; field public static final String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL"; field public static final String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS"; + field public static final String RECEIVE_BLUETOOTH_MAP = "android.permission.RECEIVE_BLUETOOTH_MAP"; field public static final String RECEIVE_DATA_ACTIVITY_CHANGE = "android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"; field public static final String RECEIVE_DEVICE_CUSTOMIZATION_READY = "android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY"; field public static final String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST"; @@ -311,6 +312,7 @@ package android { field public static final String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"; field @Deprecated public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE"; field public static final String WRITE_OBB = "android.permission.WRITE_OBB"; + field public static final String WRITE_SMS = "android.permission.WRITE_SMS"; } public static final class Manifest.permission_group { @@ -1978,6 +1980,7 @@ package android.content { method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.content.Intent registerReceiverForAllUsers(@Nullable android.content.BroadcastReceiver, @NonNull android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler, int); method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle); + method public void sendBroadcastMultiplePermissions(@NonNull android.content.Intent, @NonNull String[], @Nullable android.app.BroadcastOptions); method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle); field public static final String APP_HIBERNATION_SERVICE = "app_hibernation"; @@ -2077,6 +2080,7 @@ package android.content { field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP"; field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED"; field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED"; + field public static final String ACTION_USER_SWITCHED = "android.intent.action.USER_SWITCHED"; field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST"; field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS"; field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE"; @@ -2097,7 +2101,9 @@ package android.content { field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED"; field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME"; field public static final String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP"; + field public static final String EXTRA_USER_HANDLE = "android.intent.extra.user_handle"; field public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE"; + field public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 16777216; // 0x1000000 field public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 67108864; // 0x4000000 field public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION"; } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index bfbb9105dbb8..51ecd4cc61c6 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -149,6 +149,7 @@ package android.app { method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener); method public static void setExitTransitionTimeout(long); method public void setLaunchActivityType(int); + method public void setLaunchTaskDisplayAreaFeatureId(int); method public void setLaunchWindowingMode(int); method public void setLaunchedFromBubble(boolean); method public void setTaskAlwaysOnTop(boolean); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 6a877f97f180..d7ff7e9b3b5b 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -4366,8 +4366,8 @@ public class ActivityManager { try { getService().broadcastIntentWithFeature( null, null, intent, null, null, Activity.RESULT_OK, null, null, - null /*requiredPermissions*/, null /*excludedPermissions*/, appOp, null, false, - true, userId); + null /*requiredPermissions*/, null /*excludedPermissions*/, + null /*excludedPackages*/, appOp, null, false, true, userId); } catch (RemoteException ex) { } } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 0ff9f6655b8a..a92cbf3b96e5 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; +import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; import android.annotation.IntDef; import android.annotation.NonNull; @@ -208,6 +209,14 @@ public class ActivityOptions { "android.activity.launchTaskDisplayAreaToken"; /** + * The task display area feature id the activity should be launched into. + * @see #setLaunchTaskDisplayAreaFeatureId(int) + * @hide + */ + private static final String KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID = + "android.activity.launchTaskDisplayAreaFeatureId"; + + /** * The root task token the activity should be launched into. * @see #setLaunchRootTask(WindowContainerToken) * @hide @@ -404,6 +413,7 @@ public class ActivityOptions { private int mLaunchDisplayId = INVALID_DISPLAY; private int mCallerDisplayId = INVALID_DISPLAY; private WindowContainerToken mLaunchTaskDisplayArea; + private int mLaunchTaskDisplayAreaFeatureId = FEATURE_UNDEFINED; private WindowContainerToken mLaunchRootTask; private IBinder mLaunchTaskFragmentToken; @WindowConfiguration.WindowingMode @@ -1147,6 +1157,8 @@ public class ActivityOptions { mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY); mCallerDisplayId = opts.getInt(KEY_CALLER_DISPLAY_ID, INVALID_DISPLAY); mLaunchTaskDisplayArea = opts.getParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN); + mLaunchTaskDisplayAreaFeatureId = opts.getInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, + FEATURE_UNDEFINED); mLaunchRootTask = opts.getParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN); mLaunchTaskFragmentToken = opts.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN); mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED); @@ -1472,6 +1484,23 @@ public class ActivityOptions { } /** @hide */ + public int getLaunchTaskDisplayAreaFeatureId() { + return mLaunchTaskDisplayAreaFeatureId; + } + + /** + * Sets the TaskDisplayArea feature Id the activity should launch into. + * Note: It is possible to have TaskDisplayAreas with the same featureId on multiple displays. + * If launch display id is not specified, the TaskDisplayArea on the default display will be + * used. + * @hide + */ + @TestApi + public void setLaunchTaskDisplayAreaFeatureId(int launchTaskDisplayAreaFeatureId) { + mLaunchTaskDisplayAreaFeatureId = launchTaskDisplayAreaFeatureId; + } + + /** @hide */ public WindowContainerToken getLaunchRootTask() { return mLaunchRootTask; } @@ -1902,6 +1931,9 @@ public class ActivityOptions { if (mLaunchTaskDisplayArea != null) { b.putParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN, mLaunchTaskDisplayArea); } + if (mLaunchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) { + b.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, mLaunchTaskDisplayAreaFeatureId); + } if (mLaunchRootTask != null) { b.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, mLaunchRootTask); } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 24046c0c327b..52228e5db742 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1185,7 +1185,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/, - AppOpsManager.OP_NONE, null, false, false, getUserId()); + null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1202,7 +1202,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, false, false, + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1218,7 +1218,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, false, false, + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1235,8 +1235,8 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, options, false, false, - getUserId()); + null /*excludedPermissions=*/, null /*excludedPackages*/, + AppOpsManager.OP_NONE, options, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1251,7 +1251,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, false, false, + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1260,7 +1260,7 @@ class ContextImpl extends Context { @Override public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions, - String[] excludedPermissions) { + String[] excludedPermissions, String[] excludedPackages) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { @@ -1268,7 +1268,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, excludedPermissions, - AppOpsManager.OP_NONE, null, false, false, getUserId()); + excludedPackages, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1285,8 +1285,8 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, options, false, false, - getUserId()); + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, options, false, + false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1303,7 +1303,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, appOp, null, false, false, getUserId()); + null /*excludedPermissions=*/, null, appOp, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1320,7 +1320,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, true, false, + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1384,7 +1384,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermissions, - null /*excludedPermissions=*/, appOp, options, true, false, getUserId()); + null /*excludedPermissions=*/, null, appOp, options, true, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1398,7 +1398,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/, - AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); + null, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1421,8 +1421,8 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, options, false, false, - user.getIdentifier()); + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, options, false, + false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1439,7 +1439,8 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, - null /*excludedPermissions=*/, appOp, null, false, false, user.getIdentifier()); + null /*excludedPermissions=*/, null, appOp, null, false, false, + user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1490,7 +1491,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermissions, - null /*excludedPermissions=*/, appOp, options, true, false, + null /*excludedPermissions=*/, null, appOp, options, true, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1532,7 +1533,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/, - AppOpsManager.OP_NONE, null, false, true, getUserId()); + null, AppOpsManager.OP_NONE, null, false, true, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1571,7 +1572,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/, - AppOpsManager.OP_NONE, options, false, true, getUserId()); + null, AppOpsManager.OP_NONE, options, false, true, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1607,7 +1608,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, true, true, + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, true, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1640,7 +1641,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/, - AppOpsManager.OP_NONE, null, false, true, user.getIdentifier()); + null, AppOpsManager.OP_NONE, null, false, true, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1655,7 +1656,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/, - AppOpsManager.OP_NONE, options, false, true, user.getIdentifier()); + null, AppOpsManager.OP_NONE, options, false, true, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1690,7 +1691,7 @@ class ContextImpl extends Context { ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, - null /*excludedPermissions=*/, AppOpsManager.OP_NONE, null, true, true, + null /*excludedPermissions=*/, null, AppOpsManager.OP_NONE, null, true, true, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index df95f8f43bad..f2c808b544ae 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -138,7 +138,7 @@ interface IActivityManager { int broadcastIntentWithFeature(in IApplicationThread caller, in String callingFeatureId, in Intent intent, in String resolvedType, in IIntentReceiver resultTo, int resultCode, in String resultData, in Bundle map, in String[] requiredPermissions, in String[] excludePermissions, - int appOp, in Bundle options, boolean serialized, boolean sticky, int userId); + in String[] excludePackages, int appOp, in Bundle options, boolean serialized, boolean sticky, int userId); void unbroadcastIntent(in IApplicationThread caller, in Intent intent, int userId); @UnsupportedAppUsage oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map, diff --git a/core/java/android/app/smartspace/OWNERS b/core/java/android/app/smartspace/OWNERS index 19ef9d774e6a..4d9a633d7547 100644 --- a/core/java/android/app/smartspace/OWNERS +++ b/core/java/android/app/smartspace/OWNERS @@ -1,2 +1 @@ -srazdan@google.com -alexmang@google.com
\ No newline at end of file +include /core/java/android/service/smartspace/OWNERS diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 402007d754c0..de9d49174712 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -37,6 +37,7 @@ import android.annotation.TestApi; import android.annotation.UiContext; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.app.BroadcastOptions; import android.app.GameManager; import android.app.IApplicationThread; import android.app.IServiceConnection; @@ -2224,6 +2225,19 @@ public abstract class Context { */ public void sendBroadcastMultiplePermissions(@NonNull Intent intent, @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions) { + sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, null); + } + + + /** + * Like {@link #sendBroadcastMultiplePermissions(Intent, String[], String[])}, but also allows + * specification of a list of excluded packages. + * + * @hide + */ + public void sendBroadcastMultiplePermissions(@NonNull Intent intent, + @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions, + @Nullable String[] excludedPackages) { throw new RuntimeException("Not implemented. Must override in a subclass."); } @@ -2248,6 +2262,27 @@ public abstract class Context { } /** + * Version of {@link #sendBroadcastMultiplePermissions(Intent, String[])} that allows you to + * specify the {@link android.app.BroadcastOptions}. + * + * @param intent The Intent to broadcast; all receivers matching this + * Intent will receive the broadcast. + * @param receiverPermissions Array of names of permissions that a receiver must hold + * in order to receive your broadcast. + * If empty, no permissions are required. + * @param options Additional sending options, generated from a + * {@link android.app.BroadcastOptions}. + * @see #sendBroadcastMultiplePermissions(Intent, String[]) + * @see android.app.BroadcastOptions + * @hide + */ + @SystemApi + public void sendBroadcastMultiplePermissions(@NonNull Intent intent, + @NonNull String[] receiverPermissions, @Nullable BroadcastOptions options) { + sendBroadcastMultiplePermissions(intent, receiverPermissions, options.toBundle()); + } + + /** * Broadcast the given intent to all interested BroadcastReceivers, allowing * an array of required permissions to be enforced. This call is asynchronous; it returns * immediately, and you will continue executing while the receivers are run. No results are diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 3a02004edb1f..18a46cf5cf1f 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -494,8 +494,10 @@ public class ContextWrapper extends Context { /** @hide */ @Override public void sendBroadcastMultiplePermissions(@NonNull Intent intent, - @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions) { - mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions); + @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions, + @Nullable String[] excludedPackages) { + mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, + excludedPackages); } /** @hide */ diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 22c838c2f7bb..76591cafa4bf 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3836,7 +3836,7 @@ public class Intent implements Parcelable, Cloneable { * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @SystemApi public static final String ACTION_USER_SWITCHED = "android.intent.action.USER_SWITCHED"; @@ -5970,6 +5970,8 @@ public class Intent implements Parcelable, Cloneable { * * @hide */ + @SystemApi + @SuppressLint("ActionValue") public static final String EXTRA_USER_HANDLE = "android.intent.extra.user_handle"; @@ -6824,6 +6826,7 @@ public class Intent implements Parcelable, Cloneable { * * @hide */ + @SystemApi public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000; /** * If set, the broadcast will never go to manifest receivers in background (cached diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index a411eeef969b..61325bc6e52d 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -168,7 +168,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * signature checks} or * <a href="https://developer.android.com/training/articles/security-tips#Permissions">permissions</a>. * - * <p><b>Warning:</b> Note that does flag not behave the same as + * <p><b>Warning:</b> Note that this flag does not behave the same as * {@link android.R.attr#protectionLevel android:protectionLevel} {@code system} or * {@code signatureOrSystem}. */ diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java index d06bc1d2053d..3e41d63b0365 100644 --- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java +++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java @@ -122,6 +122,9 @@ public final class HdmiPlaybackClient extends HdmiClient { } private IHdmiControlCallback getCallbackWrapper(final OneTouchPlayCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("OneTouchPlayCallback cannot be null."); + } return new IHdmiControlCallback.Stub() { @Override public void onComplete(int result) { @@ -131,6 +134,9 @@ public final class HdmiPlaybackClient extends HdmiClient { } private IHdmiControlCallback getCallbackWrapper(final DisplayStatusCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("DisplayStatusCallback cannot be null."); + } return new IHdmiControlCallback.Stub() { @Override public void onComplete(int status) { diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 59db8f495dd9..a7c7ce2291db 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -350,7 +350,7 @@ public class Binder implements IBinder { } /** - * Reset the identity of the incoming IPC on the current thread. This can + * Reset the kernel binder identity of the incoming IPC on the current thread. This can * be useful if, while handling an incoming call, you will be calling * on interfaces of other objects that may be local to your process and * need to do permission checks on the calls coming into them (so they @@ -369,7 +369,7 @@ public class Binder implements IBinder { public static final native long clearCallingIdentity(); /** - * Restore the identity of the incoming IPC on the current thread + * Restore the kernel binder identity of the incoming IPC on the current thread * back to a previously identity that was returned by {@link * #clearCallingIdentity}. * diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 40e678085445..9649d3875342 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -33,6 +33,7 @@ import android.util.ArraySet; import android.util.ExceptionUtils; import android.util.Log; import android.util.MathUtils; +import android.util.Pair; import android.util.Size; import android.util.SizeF; import android.util.Slog; @@ -4858,28 +4859,36 @@ public final class Parcel { if (name == null) { return null; } - Parcelable.Creator<?> creator; - HashMap<String, Parcelable.Creator<?>> map; - synchronized (mCreators) { - map = mCreators.get(loader); + + Pair<Parcelable.Creator<?>, Class<?>> creatorAndParcelableClass; + synchronized (sPairedCreators) { + HashMap<String, Pair<Parcelable.Creator<?>, Class<?>>> map = + sPairedCreators.get(loader); if (map == null) { - map = new HashMap<>(); - mCreators.put(loader, map); + sPairedCreators.put(loader, new HashMap<>()); + mCreators.put(loader, new HashMap<>()); + creatorAndParcelableClass = null; + } else { + creatorAndParcelableClass = map.get(name); } - creator = map.get(name); } - if (creator != null) { + + if (creatorAndParcelableClass != null) { + Parcelable.Creator<?> creator = creatorAndParcelableClass.first; + Class<?> parcelableClass = creatorAndParcelableClass.second; if (clazz != null) { - Class<?> parcelableClass = creator.getClass().getEnclosingClass(); if (!clazz.isAssignableFrom(parcelableClass)) { throw new BadTypeParcelableException("Parcelable creator " + name + " is not " + "a subclass of required class " + clazz.getName() + " provided in the parameter"); } } + return (Parcelable.Creator<T>) creator; } + Parcelable.Creator<?> creator; + Class<?> parcelableClass; try { // If loader == null, explicitly emulate Class.forName(String) "caller // classloader" behavior. @@ -4887,7 +4896,7 @@ public final class Parcel { (loader == null ? getClass().getClassLoader() : loader); // Avoid initializing the Parcelable class until we know it implements // Parcelable and has the necessary CREATOR field. http://b/1171613. - Class<?> parcelableClass = Class.forName(name, false /* initialize */, + parcelableClass = Class.forName(name, false /* initialize */, parcelableClassLoader); if (!Parcelable.class.isAssignableFrom(parcelableClass)) { throw new BadParcelableException("Parcelable protocol requires subclassing " @@ -4934,8 +4943,9 @@ public final class Parcel { + "CREATOR on class " + name); } - synchronized (mCreators) { - map.put(name, creator); + synchronized (sPairedCreators) { + sPairedCreators.get(loader).put(name, Pair.create(creator, parcelableClass)); + mCreators.get(loader).put(name, creator); } return (Parcelable.Creator<T>) creator; @@ -5086,12 +5096,17 @@ public final class Parcel { } } - // Cache of previously looked up CREATOR.createFromParcel() methods for - // particular classes. Keys are the names of the classes, values are - // Method objects. + + // Left due to the UnsupportedAppUsage. Do not use anymore - use sPairedCreators instead @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator<?>>> - mCreators = new HashMap<>(); + private static final HashMap<ClassLoader, HashMap<String, Parcelable.Creator<?>>> + mCreators = new HashMap<>(); + + // Cache of previously looked up CREATOR.createFromParcel() methods for particular classes. + // Keys are the names of the classes, values are a pair consisting of a parcelable creator, + // and the class of the parcelable type for the object. + private static final HashMap<ClassLoader, HashMap<String, + Pair<Parcelable.Creator<?>, Class<?>>>> sPairedCreators = new HashMap<>(); /** @hide for internal use only. */ static protected final Parcel obtain(int obj) { diff --git a/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS index cb521c842816..4564c30b5d61 100644 --- a/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS +++ b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS @@ -1,8 +1,7 @@ -ewol@google.com +ashfall@google.com hackbod@google.com jsharkey@google.com narayan@google.com patb@google.com -svetoslavganov@google.com yamasani@google.com zhanghai@google.com diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS index 49f4bf71c172..d34b45bf1ff1 100644 --- a/core/java/android/permission/OWNERS +++ b/core/java/android/permission/OWNERS @@ -2,7 +2,7 @@ evanseverson@google.com evanxinchen@google.com -ewol@google.com +ashfall@google.com guojing@google.com jaysullivan@google.com kvakil@google.com diff --git a/core/java/android/service/appprediction/OWNERS b/core/java/android/service/appprediction/OWNERS index fe012da8e307..6efb975458d3 100644 --- a/core/java/android/service/appprediction/OWNERS +++ b/core/java/android/service/appprediction/OWNERS @@ -1,2 +1,4 @@ adamcohen@google.com +hyunyoungs@google.com +pinyaoting@google.com sunnygoyal@google.com diff --git a/core/java/android/service/smartspace/OWNERS b/core/java/android/service/smartspace/OWNERS index 19ef9d774e6a..d3acd3d3853c 100644 --- a/core/java/android/service/smartspace/OWNERS +++ b/core/java/android/service/smartspace/OWNERS @@ -1,2 +1,4 @@ +hyunyoungs@google.com +awickham@google.com srazdan@google.com -alexmang@google.com
\ No newline at end of file +sunnygoyal@google.com diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp index 0d530f6aa2bb..bb4ab39a59d1 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -549,10 +549,15 @@ static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong na return NULL; } - // do not marshall if there are binder objects in the parcel + if (parcel->isForRpc()) { + jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall an RPC Parcel."); + return NULL; + } + if (parcel->objectsCount()) { - jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); + jniThrowException(env, "java/lang/RuntimeException", + "Tried to marshall a Parcel that contains objects (binders or FDs)."); return NULL; } diff --git a/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp b/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp index 83e2f2b3f89e..22798563e8f5 100644 --- a/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp +++ b/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp @@ -21,17 +21,17 @@ #include "jni.h" namespace android { -static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz, +static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jclass clazz, jboolean hasConnectivity) { setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE); } -static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint socket) { +static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jclass clazz, jint socket) { return (jboolean)!protectFromVpn(socket); } -static jboolean android_net_utils_protectFromVpnWithFd(JNIEnv *env, jobject thiz, jobject javaFd) { - return android_net_utils_protectFromVpn(env, thiz, AFileDescriptor_getFd(env, javaFd)); +static jboolean android_net_utils_protectFromVpnWithFd(JNIEnv *env, jclass clazz, jobject javaFd) { + return android_net_utils_protectFromVpn(env, clazz, AFileDescriptor_getFd(env, javaFd)); } static const JNINativeMethod gNetworkUtilMethods[] = { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5a5d7e8ec035..02453a47b735 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1536,7 +1536,7 @@ android:protectionLevel="normal" android:permissionFlags="removed"/> - <!-- @hide We need to keep this around for backwards compatibility --> + <!-- @SystemApi @hide We need to keep this around for backwards compatibility --> <permission android:name="android.permission.WRITE_SMS" android:protectionLevel="normal" android:permissionFlags="removed"/> @@ -1614,7 +1614,7 @@ <permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST" android:protectionLevel="signature|privileged" /> - <!-- Allows an application to monitor incoming Bluetooth MAP messages, to record + <!-- @SystemApi Allows an application to monitor incoming Bluetooth MAP messages, to record or perform processing on them. --> <!-- @hide --> <permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP" diff --git a/core/res/res/values-mcc440-mnc20/config.xml b/core/res/res/values-mcc440-mnc20/config.xml index 62001d904482..7a483421a975 100644 --- a/core/res/res/values-mcc440-mnc20/config.xml +++ b/core/res/res/values-mcc440-mnc20/config.xml @@ -23,6 +23,6 @@ <!-- Configure mobile network MTU. Carrier specific value is set here. --> - <integer name="config_mobile_mtu">1422</integer> + <integer name="config_mobile_mtu">1358</integer> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index cd7f99f9c723..4ece840c03fe 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5199,4 +5199,12 @@ <!-- Whether this device should support taking app snapshots on closure --> <bool name="config_disableTaskSnapshots">false</bool> + + <!-- List of system components which are allowed to receive ServiceState entries in an + un-sanitized form, even if the location toggle is off. This is intended ONLY for system + components, such as the telephony stack, which require access to the full ServiceState for + tasks such as network registration. --> + <string-array name="config_serviceStateLocationAllowedPackages"> + <item>"com.android.phone"</item> + </string-array> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5c95721e390e..89797e8a3391 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4463,5 +4463,6 @@ <java-symbol type="bool" name="config_disableTaskSnapshots" /> + <java-symbol type="array" name="config_serviceStateLocationAllowedPackages" /> <java-symbol type="dimen" name="status_bar_height_default" /> </resources> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index dab4f1bdda4d..8519ddf002d6 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -61,7 +61,7 @@ <shortcode country="bg" pattern="\\d{4,5}" premium="18(?:16|423)|19(?:1[56]|35)" free="116\\d{3}|1988|1490" /> <!-- Bahrain: 1-5 digits (standard system default, not country specific) --> - <shortcode country="bh" pattern="\\d{1,5}" free="81181" /> + <shortcode country="bh" pattern="\\d{1,5}" free="81181|85999" /> <!-- Brazil: 1-5 digits (standard system default, not country specific) --> <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000" /> @@ -83,7 +83,7 @@ <shortcode country="cn" premium="1066.*" free="1065.*" /> <!-- Colombia: 1-6 digits (not confirmed) --> - <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739" /> + <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739|85517" /> <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU --> <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" /> @@ -190,7 +190,7 @@ <shortcode country="mk" pattern="\\d{1,6}" free="129005|122" /> <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed --> - <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963" /> + <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101" /> <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf --> <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" /> diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index a743d30939d0..ed87990f9a89 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -90,11 +90,36 @@ CopyResult Readback::copySurfaceInto(ANativeWindow* window, const Rect& inSrcRec SkRect srcRect = inSrcRect.toSkRect(); - SkRect imageSrcRect = - SkRect::MakeLTRB(cropRect.left, cropRect.top, cropRect.right, cropRect.bottom); - if (imageSrcRect.isEmpty()) { - imageSrcRect = SkRect::MakeIWH(description.width, description.height); + SkRect imageSrcRect = SkRect::MakeIWH(description.width, description.height); + SkISize imageWH = SkISize::Make(description.width, description.height); + if (cropRect.left < cropRect.right && cropRect.top < cropRect.bottom) { + imageSrcRect = + SkRect::MakeLTRB(cropRect.left, cropRect.top, cropRect.right, cropRect.bottom); + imageWH = SkISize::Make(cropRect.right - cropRect.left, cropRect.bottom - cropRect.top); + + // Chroma channels of YUV420 images are subsampled we may need to shrink the crop region by + // a whole texel on each side. Since skia still adds its own 0.5 inset, we apply an + // additional 0.5 inset. See GLConsumer::computeTransformMatrix for details. + float shrinkAmount = 0.0f; + switch (description.format) { + // Use HAL formats since some AHB formats are only available in vndk + case HAL_PIXEL_FORMAT_YCBCR_420_888: + case HAL_PIXEL_FORMAT_YV12: + case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: + shrinkAmount = 0.5f; + break; + default: + break; + } + + // Shrink the crop if it has more than 1-px and differs from the buffer size. + if (imageWH.width() > 1 && imageWH.width() < (int32_t)description.width) + imageSrcRect = imageSrcRect.makeInset(shrinkAmount, 0); + + if (imageWH.height() > 1 && imageWH.height() < (int32_t)description.height) + imageSrcRect = imageSrcRect.makeInset(0, shrinkAmount); } + ALOGV("imageSrcRect = " RECT_STRING, SK_RECT_ARGS(imageSrcRect)); // Represents the "logical" width/height of the texture. That is, the dimensions of the buffer @@ -153,7 +178,7 @@ CopyResult Readback::copySurfaceInto(ANativeWindow* window, const Rect& inSrcRec */ SkMatrix m; - const SkRect imageDstRect = SkRect::MakeIWH(imageSrcRect.width(), imageSrcRect.height()); + const SkRect imageDstRect = SkRect::Make(imageWH); const float px = imageDstRect.centerX(); const float py = imageDstRect.centerY(); if (windowTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp index 132d71eb6db8..128be3c33ac5 100644 --- a/libs/protoutil/Android.bp +++ b/libs/protoutil/Android.bp @@ -55,6 +55,7 @@ cc_library { export_include_dirs: ["include"], + min_sdk_version: "30", apex_available: [ "//apex_available:platform", "com.android.os.statsd", @@ -81,5 +82,5 @@ cc_test { proto: { type: "full", - } + }, } diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index b27a00c67d06..c49553580f2e 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -1200,6 +1200,8 @@ public final class AudioAttributes implements Parcelable { /** * Specifying if haptic should be muted or not when playing audio-haptic coupled data. * By default, haptic channels are disabled. + * <p>This will be ignored if the caller doesn't have the + * {@link android.Manifest.permission#VIBRATE} permission. * @param muted true to force muting haptic channels. * @return the same Builder instance. */ diff --git a/media/java/android/media/audiofx/HapticGenerator.java b/media/java/android/media/audiofx/HapticGenerator.java index fe7f29e1fc00..d2523ef43b9e 100644 --- a/media/java/android/media/audiofx/HapticGenerator.java +++ b/media/java/android/media/audiofx/HapticGenerator.java @@ -91,7 +91,8 @@ public class HapticGenerator extends AudioEffect implements AutoCloseable { } /** - * Enable or disable the effect. + * Enable or disable the effect. The effect can only be enabled if the caller has the + * {@link android.Manifest.permission#VIBRATE} permission. * * @param enabled the requested enable state * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION} diff --git a/services/accessibility/OWNERS b/services/accessibility/OWNERS index a31cfae995b2..2b9f179b832d 100644 --- a/services/accessibility/OWNERS +++ b/services/accessibility/OWNERS @@ -1,4 +1,4 @@ -svetoslavganov@google.com pweaver@google.com -rhedjao@google.com +sallyyuen@google.com ryanlwlin@google.com +fuego@google.com diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 7cbe218a9234..16c48804bec4 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -125,6 +125,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.DataUnit; +import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -354,6 +355,8 @@ class StorageManagerService extends IStorageManager.Stub private static final float DEFAULT_LOW_BATTERY_LEVEL = 20F; // Decide whether charging is required to turn on the feature private static final boolean DEFAULT_CHARGING_REQUIRED = true; + // Minimum GC interval sleep time in ms + private static final int DEFAULT_MIN_GC_SLEEPTIME = 10000; private volatile int mLifetimePercentThreshold; private volatile int mMinSegmentsThreshold; @@ -361,6 +364,7 @@ class StorageManagerService extends IStorageManager.Stub private volatile float mSegmentReclaimWeight; private volatile float mLowBatteryLevel; private volatile boolean mChargingRequired; + private volatile int mMinGCSleepTime; private volatile boolean mNeedGC; private volatile boolean mPassedLifetimeThresh; @@ -2611,6 +2615,8 @@ class StorageManagerService extends IStorageManager.Stub "low_battery_level", DEFAULT_LOW_BATTERY_LEVEL); mChargingRequired = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, "charging_required", DEFAULT_CHARGING_REQUIRED); + mMinGCSleepTime = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, + "min_gc_sleeptime", DEFAULT_MIN_GC_SLEEPTIME); // If we use the smart idle maintenance, we need to turn off GC in the traditional idle // maintenance to avoid the conflict @@ -2728,6 +2734,14 @@ class StorageManagerService extends IStorageManager.Stub enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); try { + int latestWrite = mVold.getWriteAmount(); + if (latestWrite == -1) { + Slog.w(TAG, "Failed to get storage write record"); + return; + } + + updateStorageWriteRecords(latestWrite); + // Block based checkpoint process runs fstrim. So, if checkpoint is in progress // (first boot after OTA), We skip the smart idle maintenance if (!needsCheckpoint() || !supportsBlockCheckpoint()) { @@ -2735,13 +2749,6 @@ class StorageManagerService extends IStorageManager.Stub return; } - int latestWrite = mVold.getWriteAmount(); - if (latestWrite == -1) { - Slog.w(TAG, "Failed to get storage write record"); - return; - } - - updateStorageWriteRecords(latestWrite); int avgWriteAmount = getAverageWriteAmount(); Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " + @@ -2749,9 +2756,11 @@ class StorageManagerService extends IStorageManager.Stub ", min segment threshold: " + mMinSegmentsThreshold + ", dirty reclaim rate: " + mDirtyReclaimRate + ", segment reclaim weight: " + mSegmentReclaimWeight + - ", period: " + sSmartIdleMaintPeriod); + ", period(min): " + sSmartIdleMaintPeriod + + ", min gc sleep time(ms): " + mMinGCSleepTime); mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate, - mSegmentReclaimWeight, sSmartIdleMaintPeriod); + mSegmentReclaimWeight, sSmartIdleMaintPeriod, + mMinGCSleepTime); } else { Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress"); } @@ -3274,11 +3283,21 @@ class StorageManagerService extends IStorageManager.Stub mInstaller.tryMountDataMirror(volumeUuid); } } - } catch (RemoteException | Installer.InstallerException e) { + } catch (Exception e) { + EventLog.writeEvent(0x534e4554, "224585613", -1, ""); Slog.wtf(TAG, e); // Make sure to re-throw this exception; we must not ignore failure // to prepare the user storage as it could indicate that encryption // wasn't successfully set up. + // + // Very unfortunately, these errors need to be ignored for broken + // users that already existed on-disk from older Android versions. + UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); + if (umInternal.shouldIgnorePrepareStorageErrors(userId)) { + Slog.wtf(TAG, "ignoring error preparing storage for existing user " + userId + + "; device may be insecure!"); + return; + } throw new RuntimeException(e); } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 724d17bac8e0..481b53c0a940 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -3065,42 +3065,88 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { Binder.restoreCallingIdentity(ident); } + // Send the broadcast exactly once to all possible disjoint sets of apps. + // If the location master switch is on, broadcast the ServiceState 4 times: + // - Full ServiceState sent to apps with ACCESS_FINE_LOCATION and READ_PHONE_STATE + // - Full ServiceState sent to apps with ACCESS_FINE_LOCATION and + // READ_PRIVILEGED_PHONE_STATE but not READ_PHONE_STATE + // - Sanitized ServiceState sent to apps with READ_PHONE_STATE but not ACCESS_FINE_LOCATION + // - Sanitized ServiceState sent to apps with READ_PRIVILEGED_PHONE_STATE but neither + // READ_PHONE_STATE nor ACCESS_FINE_LOCATION + // If the location master switch is off, broadcast the ServiceState multiple times: + // - Full ServiceState sent to all apps permitted to bypass the location master switch if + // they have either READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE + // - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE + // - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not + // READ_PHONE_STATE + if (Binder.withCleanCallingIdentity(() -> + LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId()))) { + Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + fullIntent, + new String[]{Manifest.permission.READ_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION}); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + fullIntent, + new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION}, + new String[]{Manifest.permission.READ_PHONE_STATE}); + + Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + sanitizedIntent, + new String[]{Manifest.permission.READ_PHONE_STATE}, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + sanitizedIntent, + new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, + new String[]{Manifest.permission.READ_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION}); + } else { + String[] locationBypassPackages = Binder.withCleanCallingIdentity(() -> + LocationAccessPolicy.getLocationBypassPackages(mContext)); + for (String locationBypassPackage : locationBypassPackages) { + Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false); + fullIntent.setPackage(locationBypassPackage); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + fullIntent, + new String[]{Manifest.permission.READ_PHONE_STATE}); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + fullIntent, + new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, + new String[]{Manifest.permission.READ_PHONE_STATE}); + } + + Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + sanitizedIntent, + new String[]{Manifest.permission.READ_PHONE_STATE}, + new String[]{/* no excluded permissions */}, + locationBypassPackages); + mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions( + sanitizedIntent, + new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, + new String[]{Manifest.permission.READ_PHONE_STATE}, + locationBypassPackages); + } + } + + private Intent createServiceStateIntent(ServiceState state, int subId, int phoneId, + boolean sanitizeLocation) { Intent intent = new Intent(Intent.ACTION_SERVICE_STATE); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Bundle data = new Bundle(); - state.fillInNotifierBundle(data); + if (sanitizeLocation) { + state.createLocationInfoSanitizedCopy(true).fillInNotifierBundle(data); + } else { + state.fillInNotifierBundle(data); + } intent.putExtras(data); - // Pass the subscription along with the intent. intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId); intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId); intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId); intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId); - - // Send the broadcast twice -- once for all apps with READ_PHONE_STATE, then again - // for all apps with READ_PRIVILEGED_PHONE_STATE but not READ_PHONE_STATE. - // Do this again twice, the first time for apps with ACCESS_FINE_LOCATION, then again with - // the location-sanitized service state for all apps without ACCESS_FINE_LOCATION. - // This ensures that any app holding either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE - // get this broadcast exactly once, and we are not exposing location without permission. - mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent, - new String[] {Manifest.permission.READ_PHONE_STATE, - Manifest.permission.ACCESS_FINE_LOCATION}); - mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent, - new String[] {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, - Manifest.permission.ACCESS_FINE_LOCATION}, - new String[] {Manifest.permission.READ_PHONE_STATE}); - - // Replace bundle with location-sanitized ServiceState - data = new Bundle(); - state.createLocationInfoSanitizedCopy(true).fillInNotifierBundle(data); - intent.putExtras(data); - mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent, - new String[] {Manifest.permission.READ_PHONE_STATE}, - new String[] {Manifest.permission.ACCESS_FINE_LOCATION}); - mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent, - new String[] {Manifest.permission.READ_PRIVILEGED_PHONE_STATE}, - new String[] {Manifest.permission.READ_PHONE_STATE, - Manifest.permission.ACCESS_FINE_LOCATION}); + return intent; } private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId, diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java index d3ef6bed46a0..c9a420eabbd8 100644 --- a/services/core/java/com/android/server/VpnManagerService.java +++ b/services/core/java/com/android/server/VpnManagerService.java @@ -45,6 +45,7 @@ import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.INetworkManagementService; +import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.ServiceManager; @@ -131,6 +132,12 @@ public class VpnManagerService extends IVpnManager.Stub { return INetworkManagementService.Stub.asInterface( ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); } + + /** Create a VPN. */ + public Vpn createVpn(Looper looper, Context context, INetworkManagementService nms, + INetd netd, int userId) { + return new Vpn(looper, context, nms, netd, userId, new VpnProfileStore()); + } } public VpnManagerService(Context context, Dependencies deps) { @@ -688,6 +695,7 @@ public class VpnManagerService extends IVpnManager.Stub { // Listen to package add and removal events for all users. intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); @@ -738,6 +746,10 @@ public class VpnManagerService extends IVpnManager.Stub { final boolean isReplacing = intent.getBooleanExtra( Intent.EXTRA_REPLACING, false); onPackageRemoved(packageName, uid, isReplacing); + } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { + final boolean isReplacing = intent.getBooleanExtra( + Intent.EXTRA_REPLACING, false); + onPackageAdded(packageName, uid, isReplacing); } else { Log.wtf(TAG, "received unexpected intent: " + action); } @@ -764,8 +776,7 @@ public class VpnManagerService extends IVpnManager.Stub { loge("Starting user already has a VPN"); return; } - userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, - new VpnProfileStore()); + userVpn = mDeps.createVpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId); mVpns.put(userId, userVpn); if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) { updateLockdownVpn(); @@ -851,15 +862,33 @@ public class VpnManagerService extends IVpnManager.Stub { final int userId = UserHandle.getUserId(uid); synchronized (mVpns) { final Vpn vpn = mVpns.get(userId); - if (vpn == null) { + if (vpn == null || isReplacing) { return; } // Legacy always-on VPN won't be affected since the package name is not set. - if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) { + if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) { log("Removing always-on VPN package " + packageName + " for user " + userId); vpn.setAlwaysOnPackage(null, false, null); } + + vpn.refreshPlatformVpnAppExclusionList(); + } + } + + private void onPackageAdded(String packageName, int uid, boolean isReplacing) { + if (TextUtils.isEmpty(packageName) || uid < 0) { + Log.wtf(TAG, "Invalid package in onPackageAdded: " + packageName + " | " + uid); + return; + } + + final int userId = UserHandle.getUserId(uid); + synchronized (mVpns) { + final Vpn vpn = mVpns.get(userId); + + if (vpn != null && !isReplacing) { + vpn.refreshPlatformVpnAppExclusionList(); + } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 683b730b4f45..09b601c34905 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2574,7 +2574,7 @@ public class ActivityManagerService extends IActivityManager.Stub public void batterySendBroadcast(Intent intent) { synchronized (this) { broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, null, - OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(), + null, OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); } } @@ -4051,7 +4051,7 @@ public class ActivityManagerService extends IActivityManager.Stub intent.putExtra(Intent.EXTRA_UID, uid); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid)); broadcastIntentLocked(null, null, null, intent, - null, null, 0, null, null, null, null, OP_NONE, + null, null, 0, null, null, null, null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.getUserId(uid)); } @@ -7746,7 +7746,7 @@ public class ActivityManagerService extends IActivityManager.Stub | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, null, intent, - null, null, 0, null, null, null, null, OP_NONE, + null, null, 0, null, null, null, null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, currentUserId); intent = new Intent(Intent.ACTION_USER_STARTING); @@ -7758,8 +7758,8 @@ public class ActivityManagerService extends IActivityManager.Stub public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) {} - }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, OP_NONE, - null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, + }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, null, + OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); } catch (Throwable e) { Slog.wtf(TAG, "Failed sending first user broadcasts", e); @@ -12577,8 +12577,8 @@ public class ActivityManagerService extends IActivityManager.Stub Intent intent = allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, - null, null, -1, -1, false, null, null, null, OP_NONE, null, receivers, - null, 0, null, null, false, true, true, -1, false, null, + null, null, -1, -1, false, null, null, null, null, OP_NONE, null, + receivers, null, 0, null, null, false, true, true, -1, false, null, false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */); queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); @@ -12820,12 +12820,14 @@ public class ActivityManagerService extends IActivityManager.Stub String callerPackage, String callerFeatureId, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, String[] excludedPermissions, - int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, + String[] excludedPackages, int appOp, Bundle bOptions, boolean ordered, + boolean sticky, int callingPid, int callingUid, int realCallingUid, int realCallingPid, int userId) { return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, - excludedPermissions, appOp, bOptions, ordered, sticky, callingPid, callingUid, - realCallingUid, realCallingPid, userId, false /* allowBackgroundActivityStarts */, + excludedPermissions, excludedPackages, appOp, bOptions, ordered, sticky, callingPid, + callingUid, realCallingUid, realCallingPid, userId, + false /* allowBackgroundActivityStarts */, null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastAllowList */); } @@ -12834,7 +12836,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Nullable String callerFeatureId, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, - String[] excludedPermissions, int appOp, Bundle bOptions, + String[] excludedPermissions, String[] excludedPackages, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid, int realCallingPid, int userId, boolean allowBackgroundActivityStarts, @@ -13411,10 +13413,10 @@ public class ActivityManagerService extends IActivityManager.Stub final BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, - requiredPermissions, excludedPermissions, appOp, brOptions, registeredReceivers, - resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId, - allowBackgroundActivityStarts, backgroundActivityStartsToken, - timeoutExempt); + requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions, + registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, + sticky, false, userId, allowBackgroundActivityStarts, + backgroundActivityStartsToken, timeoutExempt); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r); final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null); @@ -13509,7 +13511,7 @@ public class ActivityManagerService extends IActivityManager.Stub BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, - requiredPermissions, excludedPermissions, appOp, brOptions, + requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions, receivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId, allowBackgroundActivityStarts, backgroundActivityStartsToken, timeoutExempt); @@ -13638,14 +13640,16 @@ public class ActivityManagerService extends IActivityManager.Stub String[] requiredPermissions, int appOp, Bundle bOptions, boolean serialized, boolean sticky, int userId) { return broadcastIntentWithFeature(caller, null, intent, resolvedType, resultTo, resultCode, - resultData, resultExtras, requiredPermissions, null, appOp, bOptions, serialized, - sticky, userId); + resultData, resultExtras, requiredPermissions, null, null, appOp, bOptions, + serialized, sticky, userId); } + @Override public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, - String[] requiredPermissions, String[] excludedPermissions, int appOp, Bundle bOptions, + String[] requiredPermissions, String[] excludedPermissions, + String[] excludedPackages, int appOp, Bundle bOptions, boolean serialized, boolean sticky, int userId) { enforceNotIsolatedCaller("broadcastIntent"); synchronized(this) { @@ -13660,8 +13664,8 @@ public class ActivityManagerService extends IActivityManager.Stub return broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, callingFeatureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, - requiredPermissions, excludedPermissions, appOp, bOptions, serialized, - sticky, callingPid, callingUid, callingUid, callingPid, userId); + requiredPermissions, excludedPermissions, excludedPackages, appOp, bOptions, + serialized, sticky, callingPid, callingUid, callingUid, callingPid, userId); } finally { Binder.restoreCallingIdentity(origId); } @@ -13683,7 +13687,7 @@ public class ActivityManagerService extends IActivityManager.Stub try { return broadcastIntentLocked(null, packageName, featureId, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, null, - OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, + null, OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid, realCallingPid, userId, allowBackgroundActivityStarts, backgroundActivityStartsToken, null /* broadcastAllowList */); @@ -15951,10 +15955,11 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManagerService.this.broadcastIntentLocked(null /*callerApp*/, null /*callerPackage*/, null /*callingFeatureId*/, intent, null /*resolvedType*/, resultTo, 0 /*resultCode*/, null /*resultData*/, - null /*resultExtras*/, requiredPermissions, null, AppOpsManager.OP_NONE, - bOptions /*options*/, serialized, false /*sticky*/, callingPid, - callingUid, callingUid, callingPid, userId, - false /*allowBackgroundStarts*/, + null /*resultExtras*/, requiredPermissions, + null /*excludedPermissions*/, null /*excludedPackages*/, + AppOpsManager.OP_NONE, bOptions /*options*/, serialized, + false /*sticky*/, callingPid, callingUid, callingUid, callingPid, + userId, false /*allowBackgroundStarts*/, null /*tokenNeededForBackgroundActivityStarts*/, appIdAllowList); } finally { Binder.restoreCallingIdentity(origId); @@ -16076,7 +16081,7 @@ public class ActivityManagerService extends IActivityManager.Stub | Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, - null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, + null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { intent = new Intent(Intent.ACTION_LOCALE_CHANGED); @@ -16091,8 +16096,8 @@ public class ActivityManagerService extends IActivityManager.Stub TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, PowerExemptionManager.REASON_LOCALE_CHANGED, ""); broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, - null, OP_NONE, bOptions.toBundle(), false, false, MY_PID, SYSTEM_UID, - Binder.getCallingUid(), Binder.getCallingPid(), + null, null, OP_NONE, bOptions.toBundle(), false, false, MY_PID, + SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); } @@ -16107,8 +16112,9 @@ public class ActivityManagerService extends IActivityManager.Stub String[] permissions = new String[] { android.Manifest.permission.INSTALL_PACKAGES }; broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, - permissions, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, - Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); + permissions, null, null, OP_NONE, null, false, false, MY_PID, + SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), + UserHandle.USER_ALL); } } } @@ -16132,8 +16138,8 @@ public class ActivityManagerService extends IActivityManager.Stub } broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, - null, OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(), - Binder.getCallingPid(), UserHandle.USER_ALL); + null, null, OP_NONE, null, false, false, -1, SYSTEM_UID, + Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index ea28117a6a3d..827c5c417a65 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -24,6 +24,7 @@ import static android.app.WaitResult.launchStateToString; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; +import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; @@ -170,6 +171,7 @@ final class ActivityManagerShellCommand extends ShellCommand { private String mAgent; // Agent to attach on startup. private boolean mAttachAgentDuringBind; // Whether agent should be attached late. private int mDisplayId; + private int mTaskDisplayAreaFeatureId; private int mWindowingMode; private int mActivityType; private int mTaskId; @@ -353,6 +355,7 @@ final class ActivityManagerShellCommand extends ShellCommand { mStreaming = false; mUserId = defUser; mDisplayId = INVALID_DISPLAY; + mTaskDisplayAreaFeatureId = FEATURE_UNDEFINED; mWindowingMode = WINDOWING_MODE_UNDEFINED; mActivityType = ACTIVITY_TYPE_UNDEFINED; mTaskId = INVALID_TASK_ID; @@ -408,6 +411,8 @@ final class ActivityManagerShellCommand extends ShellCommand { mReceiverPermission = getNextArgRequired(); } else if (opt.equals("--display")) { mDisplayId = Integer.parseInt(getNextArgRequired()); + } else if (opt.equals("--task-display-area-feature-id")) { + mTaskDisplayAreaFeatureId = Integer.parseInt(getNextArgRequired()); } else if (opt.equals("--windowingMode")) { mWindowingMode = Integer.parseInt(getNextArgRequired()); } else if (opt.equals("--activityType")) { @@ -535,6 +540,12 @@ final class ActivityManagerShellCommand extends ShellCommand { options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(mDisplayId); } + if (mTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) { + if (options == null) { + options = ActivityOptions.makeBasic(); + } + options.setLaunchTaskDisplayAreaFeatureId(mTaskDisplayAreaFeatureId); + } if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { if (options == null) { options = ActivityOptions.makeBasic(); @@ -773,8 +784,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.flush(); Bundle bundle = mBroadcastOptions == null ? null : mBroadcastOptions.toBundle(); mInterface.broadcastIntentWithFeature(null, null, intent, null, receiver, 0, null, null, - requiredPermissions, null, android.app.AppOpsManager.OP_NONE, bundle, true, false, - mUserId); + requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, bundle, true, + false, mUserId); if (!mAsync) { receiver.waitForFinish(); } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 2da41070a6f4..6daf7099fd44 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -67,6 +67,7 @@ import android.util.SparseIntArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import java.io.FileDescriptor; @@ -766,6 +767,22 @@ public final class BroadcastQueue { skip = true; } } + + // Check that the receiver does *not* belong to any of the excluded packages + if (!skip && r.excludedPackages != null && r.excludedPackages.length > 0) { + if (ArrayUtils.contains(r.excludedPackages, filter.packageName)) { + Slog.w(TAG, "Skipping delivery of excluded package " + + r.intent.toString() + + " to " + filter.receiverList.app + + " (pid=" + filter.receiverList.pid + + ", uid=" + filter.receiverList.uid + ")" + + " excludes package " + filter.packageName + + " due to sender " + r.callerPackage + + " (uid " + r.callingUid + ")"); + skip = true; + } + } + // If the broadcast also requires an app op check that as well. if (!skip && r.appOp != AppOpsManager.OP_NONE && mService.getAppOpsManager().noteOpNoThrow(r.appOp, @@ -1600,6 +1617,19 @@ public final class BroadcastQueue { } } + // Check that the receiver does *not* belong to any of the excluded packages + if (!skip && r.excludedPackages != null && r.excludedPackages.length > 0) { + if (ArrayUtils.contains(r.excludedPackages, component.getPackageName())) { + Slog.w(TAG, "Skipping delivery of excluded package " + + r.intent + " to " + + component.flattenToShortString() + + " excludes package " + component.getPackageName() + + " due to sender " + r.callerPackage + + " (uid " + r.callingUid + ")"); + skip = true; + } + } + if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && r.requiredPermissions != null && r.requiredPermissions.length > 0) { for (int i = 0; i < r.requiredPermissions.length; i++) { diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 801559620457..84a948217c9a 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -63,6 +63,7 @@ final class BroadcastRecord extends Binder { final String resolvedType; // the resolved data type final String[] requiredPermissions; // permissions the caller has required final String[] excludedPermissions; // permissions to exclude + final String[] excludedPackages; // packages to exclude final int appOp; // an app op that is associated with this broadcast final BroadcastOptions options; // BroadcastOptions supplied by caller final List receivers; // contains BroadcastFilter and ResolveInfo @@ -147,6 +148,10 @@ final class BroadcastRecord extends Binder { pw.print(prefix); pw.print("excludedPermissions="); pw.print(Arrays.toString(excludedPermissions)); } + if (excludedPackages != null && excludedPackages.length > 0) { + pw.print(prefix); pw.print("excludedPackages="); + pw.print(Arrays.toString(excludedPackages)); + } if (options != null) { pw.print(prefix); pw.print("options="); pw.println(options.toBundle()); } @@ -245,7 +250,8 @@ final class BroadcastRecord extends Binder { Intent _intent, ProcessRecord _callerApp, String _callerPackage, @Nullable String _callerFeatureId, int _callingPid, int _callingUid, boolean _callerInstantApp, String _resolvedType, - String[] _requiredPermissions, String[] _excludedPermissions, int _appOp, + String[] _requiredPermissions, String[] _excludedPermissions, + String[] _excludedPackages, int _appOp, BroadcastOptions _options, List _receivers, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId, boolean allowBackgroundActivityStarts, @@ -265,6 +271,7 @@ final class BroadcastRecord extends Binder { resolvedType = _resolvedType; requiredPermissions = _requiredPermissions; excludedPermissions = _excludedPermissions; + excludedPackages = _excludedPackages; appOp = _appOp; options = _options; receivers = _receivers; @@ -306,6 +313,7 @@ final class BroadcastRecord extends Binder { resolvedType = from.resolvedType; requiredPermissions = from.requiredPermissions; excludedPermissions = from.excludedPermissions; + excludedPackages = from.excludedPackages; appOp = from.appOp; options = from.options; receivers = from.receivers; @@ -363,9 +371,10 @@ final class BroadcastRecord extends Binder { // build a new BroadcastRecord around that single-target list BroadcastRecord split = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, - requiredPermissions, excludedPermissions, appOp, options, splitReceivers, resultTo, - resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId, - allowBackgroundActivityStarts, mBackgroundActivityStartsToken, timeoutExempt); + requiredPermissions, excludedPermissions, excludedPackages, appOp, options, + splitReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, + initialSticky, userId, allowBackgroundActivityStarts, + mBackgroundActivityStartsToken, timeoutExempt); split.splitToken = this.splitToken; return split; diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java index 756209824614..35f91ba1169b 100644 --- a/services/core/java/com/android/server/am/PreBootBroadcaster.java +++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java @@ -124,7 +124,7 @@ public abstract class PreBootBroadcaster extends IIntentReceiver.Stub { REASON_PRE_BOOT_COMPLETED, ""); synchronized (mService) { mService.broadcastIntentLocked(null, null, null, mIntent, null, this, 0, null, null, - null, null, AppOpsManager.OP_NONE, bOptions.toBundle(), true, + null, null, null, AppOpsManager.OP_NONE, bOptions.toBundle(), true, false, ActivityManagerService.MY_PID, Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index c465be149ac2..6f7dab9779e5 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -2994,8 +2994,8 @@ class UserController implements Handler.Callback { synchronized (mService) { return mService.broadcastIntentLocked(null, null, null, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, null, - appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid, - realCallingPid, userId); + null, appOp, bOptions, ordered, sticky, callingPid, callingUid, + realCallingUid, realCallingPid, userId); } } diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java index 4d025c981ce9..28a919115f56 100644 --- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java +++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java @@ -423,6 +423,7 @@ public final class AppHibernationService extends SystemService { null /* resultExtras */, requiredPermissions, null /* excludedPermissions */, + null /* excludedPackages */, OP_NONE, null /* bOptions */, false /* serialized */, @@ -441,6 +442,7 @@ public final class AppHibernationService extends SystemService { null /* resultExtras */, requiredPermissions, null /* excludedPermissions */, + null /* excludedPackages */, OP_NONE, null /* bOptions */, false /* serialized */, diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 5b282ced73b5..c3fc8e0a7535 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -186,7 +186,7 @@ public class Vpn { private static final boolean LOGD = true; private static final String ANDROID_KEYSTORE_PROVIDER = "AndroidKeyStore"; /** Key containing prefix of vpn app excluded list */ - @VisibleForTesting static final String VPN_APP_EXCLUDED = "VPN_APP_EXCLUDED_"; + @VisibleForTesting static final String VPN_APP_EXCLUDED = "VPNAPPEXCLUDED_"; // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on // the device idle allowlist during service launch and VPN bootstrap. @@ -1182,20 +1182,9 @@ public class Vpn { cleanupVpnStateLocked(); } else if (mVpnRunner != null) { if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { - mAppOpsManager.finishOp( - AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null); - // The underlying network, NetworkCapabilities and LinkProperties are not - // necessary to send to VPN app since the purpose of this event is to notify - // VPN app that VPN is deactivated by the user. - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. - if (SdkLevel.isAtLeastT()) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, - -1 /* errorClass */, -1 /* errorCode*/, mPackage, - getSessionKeyLocked(), makeVpnProfileStateLocked(), - null /* underlyingNetwork */, null /* nc */, null /* lp */); - } + notifyVpnManagerVpnStopped(mPackage, mOwnerUID); } + // cleanupVpnStateLocked() is called from mVpnRunner.exit() mVpnRunner.exit(); } @@ -4043,7 +4032,25 @@ public class Vpn { // To stop the VPN profile, the caller must be the current prepared package and must be // running an Ikev2VpnProfile. if (isCurrentIkev2VpnLocked(packageName)) { - prepareInternal(VpnConfig.LEGACY_VPN); + notifyVpnManagerVpnStopped(packageName, mOwnerUID); + + mVpnRunner.exit(); + } + } + + private synchronized void notifyVpnManagerVpnStopped(String packageName, int ownerUID) { + mAppOpsManager.finishOp( + AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, ownerUID, packageName, null); + // The underlying network, NetworkCapabilities and LinkProperties are not + // necessary to send to VPN app since the purpose of this event is to notify + // VPN app that VPN is deactivated by the user. + // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from + // ConnectivityServiceTest. + if (SdkLevel.isAtLeastT()) { + sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, + -1 /* errorClass */, -1 /* errorCode*/, packageName, + getSessionKeyLocked(), makeVpnProfileStateLocked(), + null /* underlyingNetwork */, null /* nc */, null /* lp */); } } @@ -4085,6 +4092,20 @@ public class Vpn { @NonNull List<String> excludedApps) { enforceNotRestrictedUser(); if (!storeAppExclusionList(packageName, excludedApps)) return false; + + updateAppExclusionList(excludedApps); + + return true; + } + + /** + * Triggers an update of the VPN network's excluded UIDs if a VPN is running. + */ + public synchronized void refreshPlatformVpnAppExclusionList() { + updateAppExclusionList(getAppExclusionList(mPackage)); + } + + private synchronized void updateAppExclusionList(@NonNull List<String> excludedApps) { // Re-build and update NetworkCapabilities via NetworkAgent. if (mNetworkAgent != null) { // Only update the platform VPN @@ -4097,8 +4118,6 @@ public class Vpn { mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); } } - - return true; } /** diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index a59219265e2c..59fae9e64c5f 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -200,7 +200,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } private void handleMediaProjectionStoppedLocked(IBinder appToken) { - VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); + VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); if (device != null) { Slog.i(TAG, "Virtual display device released because media projection stopped: " + device.mName); diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS index 426f002ad236..7302f6e38af2 100644 --- a/services/core/java/com/android/server/dreams/OWNERS +++ b/services/core/java/com/android/server/dreams/OWNERS @@ -1,3 +1,4 @@ +brycelee@google.com dsandler@android.com michaelwr@google.com roosa@google.com diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 39d501be6c89..d162ce29d7d3 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15962,7 +15962,7 @@ public class PackageManagerService extends IPackageManager.Stub final BroadcastOptions bOptions = getTemporaryAppAllowlistBroadcastOptions( REASON_LOCKED_BOOT_COMPLETED); am.broadcastIntentWithFeature(null, null, lockedBcIntent, null, null, 0, null, null, - requiredPermissions, null, android.app.AppOpsManager.OP_NONE, + requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, bOptions.toBundle(), false, false, userId); // Deliver BOOT_COMPLETED only if user is unlocked @@ -15973,7 +15973,7 @@ public class PackageManagerService extends IPackageManager.Stub bcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); } am.broadcastIntentWithFeature(null, null, bcIntent, null, null, 0, null, null, - requiredPermissions, null, android.app.AppOpsManager.OP_NONE, + requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, bOptions.toBundle(), false, false, userId); } } catch (RemoteException e) { @@ -22869,7 +22869,7 @@ public class PackageManagerService extends IPackageManager.Stub intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); try { am.broadcastIntentWithFeature(null, null, intent, null, null, - 0, null, null, null, null, android.app.AppOpsManager.OP_NONE, + 0, null, null, null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId); } catch (RemoteException e) { } @@ -28766,8 +28766,8 @@ public class PackageManagerService extends IPackageManager.Stub }; try { am.broadcastIntentWithFeature(null, null, intent, null, null, 0, null, null, - requiredPermissions, null, android.app.AppOpsManager.OP_NONE, null, false, - false, UserHandle.USER_ALL); + requiredPermissions, null, null, android.app.AppOpsManager.OP_NONE, null, + false, false, UserHandle.USER_ALL); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java index 1ca7bcd32741..479701e91472 100644 --- a/services/core/java/com/android/server/pm/UserDataPreparer.java +++ b/services/core/java/com/android/server/pm/UserDataPreparer.java @@ -125,8 +125,11 @@ class UserDataPreparer { flags | StorageManager.FLAG_STORAGE_DE, false); } else { try { - Log.e(TAG, "prepareUserData failed", e); - RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed"); + Log.wtf(TAG, "prepareUserData failed for user " + userId, e); + if (userId == UserHandle.USER_SYSTEM) { + RecoverySystem.rebootPromptAndWipeUserData(mContext, + "prepareUserData failed for system user"); + } } catch (IOException e2) { throw new RuntimeException("error rebooting into recovery", e2); } diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index eb2de6012745..0e6d5e5ed463 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -312,4 +312,12 @@ public abstract class UserManagerInternal { */ public abstract void setDefaultCrossProfileIntentFilters( @UserIdInt int parentUserId, @UserIdInt int profileUserId); + + /** + * Returns {@code true} if the system should ignore errors when preparing + * the storage directories for the user with ID {@code userId}. This will + * return {@code false} for all new users; it will only return {@code true} + * for users that already existed on-disk from an older version of Android. + */ + public abstract boolean shouldIgnorePrepareStorageErrors(int userId); } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 374a5c266108..af3dafc0dc15 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -204,6 +204,8 @@ public class UserManagerService extends IUserManager.Stub { private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions"; private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL = "lastRequestQuietModeEnabledCall"; + private static final String TAG_IGNORE_PREPARE_STORAGE_ERRORS = + "ignorePrepareStorageErrors"; private static final String ATTR_KEY = "key"; private static final String ATTR_VALUE_TYPE = "type"; private static final String ATTR_MULTIPLE = "m"; @@ -313,6 +315,14 @@ public class UserManagerService extends IUserManager.Stub { private long mLastRequestQuietModeEnabledMillis; + /** + * {@code true} if the system should ignore errors when preparing the + * storage directories for this user. This is {@code false} for all new + * users; it will only be {@code true} for users that already existed + * on-disk from an older version of Android. + */ + private boolean mIgnorePrepareStorageErrors; + void setLastRequestQuietModeEnabledMillis(long millis) { mLastRequestQuietModeEnabledMillis = millis; } @@ -321,6 +331,14 @@ public class UserManagerService extends IUserManager.Stub { return mLastRequestQuietModeEnabledMillis; } + boolean getIgnorePrepareStorageErrors() { + return mIgnorePrepareStorageErrors; + } + + void setIgnorePrepareStorageErrors() { + mIgnorePrepareStorageErrors = true; + } + void clearSeedAccountData() { seedAccountName = null; seedAccountType = null; @@ -3180,6 +3198,10 @@ public class UserManagerService extends IUserManager.Stub { serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL); } + serializer.startTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS); + serializer.text(String.valueOf(userData.getIgnorePrepareStorageErrors())); + serializer.endTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS); + serializer.endTag(null, TAG_USER); serializer.endDocument(); @@ -3289,6 +3311,7 @@ public class UserManagerService extends IUserManager.Stub { Bundle legacyLocalRestrictions = null; RestrictionsSet localRestrictions = null; Bundle globalRestrictions = null; + boolean ignorePrepareStorageErrors = true; // default is true for old users final TypedXmlPullParser parser = Xml.resolvePullParser(is); int type; @@ -3367,6 +3390,11 @@ public class UserManagerService extends IUserManager.Stub { if (type == XmlPullParser.TEXT) { lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText()); } + } else if (TAG_IGNORE_PREPARE_STORAGE_ERRORS.equals(tag)) { + type = parser.next(); + if (type == XmlPullParser.TEXT) { + ignorePrepareStorageErrors = Boolean.parseBoolean(parser.getText()); + } } } } @@ -3394,6 +3422,9 @@ public class UserManagerService extends IUserManager.Stub { userData.persistSeedData = persistSeedData; userData.seedAccountOptions = seedAccountOptions; userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp); + if (ignorePrepareStorageErrors) { + userData.setIgnorePrepareStorageErrors(); + } synchronized (mRestrictionsLock) { if (baseRestrictions != null) { @@ -5238,6 +5269,9 @@ public class UserManagerService extends IUserManager.Stub { pw.println(); } } + + pw.println(" Ignore errors preparing storage: " + + userData.getIgnorePrepareStorageErrors()); } } @@ -5727,6 +5761,14 @@ public class UserManagerService extends IUserManager.Stub { UserManagerService.this.setDefaultCrossProfileIntentFilters( profileUserId, userTypeDetails, restrictions, parentUserId); } + + @Override + public boolean shouldIgnorePrepareStorageErrors(int userId) { + synchronized (mUsersLock) { + UserData userData = mUsers.get(userId); + return userData != null && userData.getIgnorePrepareStorageErrors(); + } + } } /** diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index b184d5c62008..42c6dd43ebce 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4193,17 +4193,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { - if (mImeLayeringTarget != null && mImeInputTarget != null - && mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) { - // Do not change parent if the window hasn't requested IME. - return null; - } // Attach it to app if the target is part of an app and such app is covering the entire // screen. If it's not covering the entire screen the IME might extend beyond the apps // bounds. if (shouldImeAttachedToApp()) { + if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) { + // Do not change parent if the window hasn't requested IME. + return null; + } return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); } + // Otherwise, we just attach it to where the display area policy put it. return mImeWindowsContainer.getParent() != null ? mImeWindowsContainer.getParent().getSurfaceControl() : null; diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 5124841bcbbb..10ae152c3365 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -265,12 +265,14 @@ class InsetsPolicy { return state; } } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { - // During switching tasks with gestural navigation, before the next IME input target - // starts the input, we should adjust and freeze the last IME visibility of the window - // in case delivering obsoleted IME insets state during transitioning. + // During switching tasks with gestural navigation, if the IME is attached to + // one app window on that time, even the next app window is behind the IME window, + // conceptually the window should not receive the IME insets if the next window is + // not eligible IME requester and ready to show IME on top of it. + final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp(); final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME); - if (originalImeSource != null) { + if (shouldImeAttachedToApp && originalImeSource != null) { final boolean imeVisibility = w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME); final InsetsState state = copyState ? new InsetsState(originalState) diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index eeac230489f9..027f3aebc502 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -68,6 +68,7 @@ class RemoteAnimationController implements DeathRecipient { final ArrayList<NonAppWindowAnimationAdapter> mPendingNonAppAnimations = new ArrayList<>(); private final Handler mHandler; private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable"); + private boolean mIsFinishing; private FinishedCallback mFinishedCallback; private boolean mCanceled; @@ -246,6 +247,7 @@ class RemoteAnimationController implements DeathRecipient { mPendingAnimations.size()); mHandler.removeCallbacks(mTimeoutRunnable); synchronized (mService.mGlobalLock) { + mIsFinishing = true; unlinkToDeathOfRunner(); releaseFinishedCallback(); mService.openSurfaceTransaction(); @@ -290,6 +292,7 @@ class RemoteAnimationController implements DeathRecipient { throw e; } finally { mService.closeSurfaceTransaction("RemoteAnimationController#finished"); + mIsFinishing = false; } } setRunningRemoteAnimation(false); @@ -501,6 +504,9 @@ class RemoteAnimationController implements DeathRecipient { @Override public void onAnimationCancelled(SurfaceControl animationLeash) { + if (mIsFinishing) { + return; + } if (mRecord.mAdapter == this) { mRecord.mAdapter = null; } else { diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java index 2d4aef682d62..66d02308bf0b 100644 --- a/services/core/java/com/android/server/wm/SafeActivityOptions.java +++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java @@ -25,7 +25,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -248,8 +250,25 @@ public class SafeActivityOptions { } // Check if the caller is allowed to launch on the specified display area. final WindowContainerToken daToken = options.getLaunchTaskDisplayArea(); - final TaskDisplayArea taskDisplayArea = daToken != null + TaskDisplayArea taskDisplayArea = daToken != null ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null; + + // If we do not have a task display area token, check if the launch task display area + // feature id is specified. + if (taskDisplayArea == null) { + final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId(); + if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) { + final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY + ? DEFAULT_DISPLAY : options.getLaunchDisplayId(); + final DisplayContent dc = supervisor.mRootWindowContainer + .getDisplayContent(launchDisplayId); + if (dc != null) { + taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda -> + tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null); + } + } + } + if (aInfo != null && taskDisplayArea != null && !supervisor.isCallerAllowedToLaunchOnTaskDisplayArea(callingPid, callingUid, taskDisplayArea, aInfo)) { diff --git a/services/core/java/com/android/server/wm/SplashScreenExceptionList.java b/services/core/java/com/android/server/wm/SplashScreenExceptionList.java index e815a0e2682a..92a538c23598 100644 --- a/services/core/java/com/android/server/wm/SplashScreenExceptionList.java +++ b/services/core/java/com/android/server/wm/SplashScreenExceptionList.java @@ -81,7 +81,7 @@ class SplashScreenExceptionList { @SuppressWarnings("AndroidFrameworkCompatChange") // Target sdk check public boolean isException(@NonNull String packageName, int targetSdk, @Nullable Supplier<ApplicationInfo> infoSupplier) { - if (targetSdk >= Build.VERSION_CODES.S) { + if (targetSdk > Build.VERSION_CODES.S_V2) { return false; } diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index b8ceb4a4f421..24a745b3896e 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -35,6 +35,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT; import static android.util.DisplayMetrics.DENSITY_DEFAULT; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; import static com.android.server.wm.ActivityStarter.Request; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; @@ -293,7 +294,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { TaskDisplayArea taskDisplayArea = suggestedDisplayArea; // If launch task display area is set in options we should just use it. We assume the // suggestedDisplayArea has the right one in this case. - if (options == null || options.getLaunchTaskDisplayArea() == null) { + if (options == null || (options.getLaunchTaskDisplayArea() == null + && options.getLaunchTaskDisplayAreaFeatureId() == FEATURE_UNDEFINED)) { final int activityType = mSupervisor.mRootWindowContainer.resolveActivityType(root, options, task); display.forAllTaskDisplayAreas(displayArea -> { @@ -377,7 +379,22 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { if (optionLaunchTaskDisplayAreaToken != null) { taskDisplayArea = (TaskDisplayArea) WindowContainer.fromBinder( optionLaunchTaskDisplayAreaToken.asBinder()); - if (DEBUG) appendLog("display-area-from-option=" + taskDisplayArea); + if (DEBUG) appendLog("display-area-token-from-option=" + taskDisplayArea); + } + + if (taskDisplayArea == null && options != null) { + final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId(); + if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) { + final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY + ? DEFAULT_DISPLAY : options.getLaunchDisplayId(); + final DisplayContent dc = mSupervisor.mRootWindowContainer + .getDisplayContent(launchDisplayId); + if (dc != null) { + taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda -> + tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null); + if (DEBUG) appendLog("display-area-feature-from-option=" + taskDisplayArea); + } + } } // If task display area is not specified in options - try display id diff --git a/services/net/java/android/net/ConnectivityModuleConnector.java b/services/net/java/android/net/ConnectivityModuleConnector.java index c6b15c17bd3c..6bf6349bc4b3 100644 --- a/services/net/java/android/net/ConnectivityModuleConnector.java +++ b/services/net/java/android/net/ConnectivityModuleConnector.java @@ -25,7 +25,6 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.net.util.SharedLog; import android.os.Build; import android.os.Environment; import android.os.IBinder; @@ -35,13 +34,13 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.text.format.DateUtils; import android.util.ArraySet; +import android.util.Log; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.io.File; -import java.io.PrintWriter; /** * Class used to communicate to the various networking mainline modules running in the network stack @@ -73,8 +72,6 @@ public class ConnectivityModuleConnector { private static ConnectivityModuleConnector sInstance; private Context mContext; - @GuardedBy("mLog") - private final SharedLog mLog = new SharedLog(TAG); @GuardedBy("mHealthListeners") private final ArraySet<ConnectivityModuleHealthListener> mHealthListeners = new ArraySet<>(); @NonNull @@ -384,38 +381,19 @@ public class ConnectivityModuleConnector { } private void log(@NonNull String message) { - Slog.d(TAG, message); - synchronized (mLog) { - mLog.log(message); - } + Log.d(TAG, message); } private void logWtf(@NonNull String message, @Nullable Throwable e) { Slog.wtf(TAG, message, e); - synchronized (mLog) { - mLog.e(message); - } + Log.e(TAG, message, e); } private void loge(@NonNull String message, @Nullable Throwable e) { - Slog.e(TAG, message, e); - synchronized (mLog) { - mLog.e(message); - } + Log.e(TAG, message, e); } private void logi(@NonNull String message) { - Slog.i(TAG, message); - synchronized (mLog) { - mLog.i(message); - } - } - - /** - * Dump ConnectivityModuleConnector logs to the specified {@link PrintWriter}. - */ - public void dump(PrintWriter pw) { - // dump is thread-safe on SharedLog - mLog.dump(null, pw, null); + Log.i(TAG, message); } } diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java index 865e3b8cc109..b7eb5cd61329 100644 --- a/services/net/java/android/net/NetworkStackClient.java +++ b/services/net/java/android/net/NetworkStackClient.java @@ -25,19 +25,18 @@ import android.content.Context; import android.net.dhcp.DhcpServingParamsParcel; import android.net.dhcp.IDhcpServerCallbacks; import android.net.ip.IIpClientCallbacks; -import android.net.util.SharedLog; import android.os.Binder; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.util.Log; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import java.io.PrintWriter; import java.util.ArrayList; /** @@ -61,9 +60,6 @@ public class NetworkStackClient { @GuardedBy("mPendingNetStackRequests") private INetworkStackConnector mConnector; - @GuardedBy("mLog") - private final SharedLog mLog = new SharedLog(TAG); - private volatile boolean mWasSystemServerInitialized = false; private interface NetworkStackCallback { @@ -237,34 +233,23 @@ public class NetworkStackClient { } /** - * Log a message in the local log. + * Log a debug message. */ private void log(@NonNull String message) { - synchronized (mLog) { - mLog.log(message); - } + Log.d(TAG, message); } private void logWtf(@NonNull String message, @Nullable Throwable e) { Slog.wtf(TAG, message); - synchronized (mLog) { - mLog.e(message, e); - } + Log.e(TAG, message, e); } private void loge(@NonNull String message, @Nullable Throwable e) { - synchronized (mLog) { - mLog.e(message, e); - } + Log.e(TAG, message, e); } - /** - * Log a message in the local and system logs. - */ private void logi(@NonNull String message) { - synchronized (mLog) { - mLog.i(message); - } + Log.i(TAG, message); } /** @@ -320,22 +305,4 @@ public class NetworkStackClient { request.onNetworkStackConnected(connector); } - - /** - * Dump NetworkStackClient logs to the specified {@link PrintWriter}. - */ - public void dump(PrintWriter pw) { - // dump is thread-safe on SharedLog - mLog.dump(null, pw, null); - // dump connectivity module connector logs. - ConnectivityModuleConnector.getInstance().dump(pw); - - final int requestsQueueLength; - synchronized (mPendingNetStackRequests) { - requestsQueueLength = mPendingNetStackRequests.size(); - } - - pw.println(); - pw.println("pendingNetStackRequests length: " + requestsQueueLength); - } } diff --git a/services/smartspace/OWNERS b/services/smartspace/OWNERS index 19ef9d774e6a..4d9a633d7547 100644 --- a/services/smartspace/OWNERS +++ b/services/smartspace/OWNERS @@ -1,2 +1 @@ -srazdan@google.com -alexmang@google.com
\ No newline at end of file +include /core/java/android/service/smartspace/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java index e9b5b6243089..f44104e10967 100644 --- a/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java +++ b/services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest.java @@ -185,6 +185,7 @@ public class BroadcastRecordTest { null /* resolvedType */, null /* requiredPermissions */, null /* excludedPermissions */, + null /* excludedPackages */, 0 /* appOp */, null /* options */, new ArrayList<>(receivers), // Make a copy to not affect the original list. diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java index 1c49e6e64dd8..70853b6881d9 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -298,7 +298,7 @@ public final class AppHibernationServiceTest { ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mIActivityManager, times(2)).broadcastIntentWithFeature(any(), any(), intentArgumentCaptor.capture(), any(), any(), anyInt(), any(), any(), any(), any(), - anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1)); + any(), anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1)); List<Intent> capturedIntents = intentArgumentCaptor.getAllValues(); assertEquals(capturedIntents.get(0).getAction(), Intent.ACTION_LOCKED_BOOT_COMPLETED); assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 32cee44ce6ff..0d9c923c674f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2528,7 +2528,9 @@ public class ActivityRecordTests extends WindowTestsBase { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, "splash_screen_exception_list", DEFAULT_COMPONENT_PACKAGE_NAME, false); testLegacySplashScreen(Build.VERSION_CODES.R, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN); - testLegacySplashScreen(Build.VERSION_CODES.S, 0); + testLegacySplashScreen(Build.VERSION_CODES.S, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN); + testLegacySplashScreen(Build.VERSION_CODES.S_V2, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN); + testLegacySplashScreen(Build.VERSION_CODES.S_V2 + 1, 0); } finally { try { DeviceConfig.setProperties(properties); @@ -3065,11 +3067,11 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen - mDisplayContent.updateImeInputAndControlTarget(app); - assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.getInsetsState().addSource(imeSource); app.getInsetsState().setSourceVisible(ITYPE_IME, true); + mDisplayContent.updateImeInputAndControlTarget(app); + assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 9c0c213c3efe..f3c1ec5b200e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1075,21 +1075,6 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } - @UseTestDisplay(addWindows = W_ACTIVITY) - @Test - public void testComputeImeParent_inputTargetNotUpdate() throws Exception { - WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1"); - WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2"); - doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); - mDisplayContent.setImeLayeringTarget(app1); - mDisplayContent.setImeInputTarget(app1); - assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent()); - mDisplayContent.setImeLayeringTarget(app2); - // Expect null means no change IME parent when the IME layering target not yet - // request IME to be the input target. - assertNull(mDisplayContent.computeImeParent()); - } - @Test public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { final DisplayContent dc = createNewDisplay(); diff --git a/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java b/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java index 3714d9984a0c..b78675d73f6c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java @@ -80,13 +80,19 @@ public class SplashScreenExceptionListTest { public void packageFromDeviceConfigIgnored() { setExceptionListAndWaitForCallback("com.test.nosplashscreen1,com.test.nosplashscreen2"); - assertIsException("com.test.nosplashscreen1", null); - assertIsException("com.test.nosplashscreen2", null); - - assertIsNotException("com.test.nosplashscreen1", VERSION_CODES.S, null); - assertIsNotException("com.test.nosplashscreen2", VERSION_CODES.S, null); - assertIsNotException("com.test.splashscreen", VERSION_CODES.S, null); - assertIsNotException("com.test.splashscreen", VERSION_CODES.R, null); + // In list, up to SC-V2 included + assertIsException("com.test.nosplashscreen1", VERSION_CODES.R); + assertIsException("com.test.nosplashscreen1", VERSION_CODES.S); + assertIsException("com.test.nosplashscreen1", VERSION_CODES.S_V2); + + // In list, after SC-V2 + assertIsNotException("com.test.nosplashscreen2", VERSION_CODES.S_V2 + 1); + assertIsNotException("com.test.nosplashscreen2", VERSION_CODES.CUR_DEVELOPMENT); + + // Not in list, up to SC-V2 included + assertIsNotException("com.test.splashscreen", VERSION_CODES.R); + assertIsNotException("com.test.splashscreen", VERSION_CODES.S); + assertIsNotException("com.test.splashscreen", VERSION_CODES.S_V2); } private void setExceptionListAndWaitForCallback(String commaSeparatedList) { @@ -123,16 +129,26 @@ public class SplashScreenExceptionListTest { metaData.putBoolean("android.splashscreen.exception_opt_out", true); assertIsNotException(packageName, VERSION_CODES.R, activityInfo); assertIsNotException(packageName, VERSION_CODES.S, activityInfo); + assertIsNotException(packageName, VERSION_CODES.S_V2, activityInfo); - // Exception Pre S + // Exception up to T metaData.putBoolean("android.splashscreen.exception_opt_out", false); - assertIsException(packageName, activityInfo); - assertIsNotException(packageName, VERSION_CODES.S, activityInfo); + assertIsException(packageName, VERSION_CODES.R, activityInfo); + assertIsException(packageName, VERSION_CODES.S, activityInfo); + assertIsException(packageName, VERSION_CODES.S_V2, activityInfo); + + // No Exception after T + assertIsNotException(packageName, VERSION_CODES.S_V2 + 1, activityInfo); + assertIsNotException(packageName, VERSION_CODES.CUR_DEVELOPMENT, activityInfo); // Edge Cases activityInfo.metaData = null; - assertIsException(packageName, activityInfo); - assertIsException(packageName, null); + assertIsException(packageName, VERSION_CODES.R, activityInfo); + assertIsException(packageName, VERSION_CODES.R); + } + + private void assertIsNotException(String packageName, int targetSdk) { + assertIsNotException(packageName, targetSdk, null); } private void assertIsNotException(String packageName, int targetSdk, @@ -142,10 +158,14 @@ public class SplashScreenExceptionListTest { mList.isException(packageName, targetSdk, () -> activityInfo)); } - private void assertIsException(String packageName, + private void assertIsException(String packageName, int targetSdk) { + assertIsException(packageName, targetSdk, null); + } + + private void assertIsException(String packageName, int targetSdk, ApplicationInfo activityInfo) { assertTrue(String.format("%s (sdk=%d) should have been considered as an exception", - packageName, VERSION_CODES.R), - mList.isException(packageName, VERSION_CODES.R, () -> activityInfo)); + packageName, targetSdk), + mList.isException(packageName, targetSdk, () -> activityInfo)); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 168c250a8c93..159d48283085 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -196,6 +196,28 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { } @Test + public void testUsesOptionsDisplayAreaFeatureIdIfSet() { + final TestDisplayContent freeformDisplay = createNewDisplayContent( + WINDOWING_MODE_FREEFORM); + final TestDisplayContent fullscreenDisplay = createNewDisplayContent( + WINDOWING_MODE_FULLSCREEN); + + mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea(); + ActivityRecord source = createSourceActivity(freeformDisplay); + + ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchDisplayId(fullscreenDisplay.mDisplayId); + options.setLaunchTaskDisplayAreaFeatureId( + fullscreenDisplay.getDefaultTaskDisplayArea().mFeatureId); + + assertEquals(RESULT_CONTINUE, + new CalculateRequestBuilder().setSource(source).setOptions(options).calculate()); + + assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(), + mResult.mPreferredTaskDisplayArea); + } + + @Test public void testUsesSourcesDisplayAreaIdPriorToTaskIfSet() { final TestDisplayContent freeformDisplay = createNewDisplayContent( WINDOWING_MODE_FREEFORM); @@ -453,7 +475,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { } @Test - public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayArea() { + public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayAreaToken() { final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay, mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST); final Task launchRoot = createTask(secondaryDisplayArea, WINDOWING_MODE_FULLSCREEN, @@ -475,6 +497,52 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { } @Test + public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayAreaFeatureId() { + final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay, + mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST); + final Task launchRoot = createTask(secondaryDisplayArea, WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD); + launchRoot.mCreatedByOrganizer = true; + + secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN }, + new int[] { ACTIVITY_TYPE_STANDARD }); + + ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchTaskDisplayAreaFeatureId( + mDefaultDisplay.getDefaultTaskDisplayArea().mFeatureId); + + assertEquals(RESULT_CONTINUE, + new CalculateRequestBuilder().setOptions(options).calculate()); + + assertEquals( + mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea); + } + + @Test + public void testUsesOptionsDisplayAreaFeatureIdDisplayIdNotSet() { + final TestDisplayContent secondaryDisplay = createNewDisplayContent( + WINDOWING_MODE_FULLSCREEN); + final TaskDisplayArea tdaOnSecondaryDisplay = createTaskDisplayArea(secondaryDisplay, + mWm, "TestTaskDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST); + + final TaskDisplayArea tdaOnDefaultDisplay = createTaskDisplayArea(mDefaultDisplay, + mWm, "TestTaskDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST); + + mCurrent.mPreferredTaskDisplayArea = tdaOnSecondaryDisplay; + ActivityRecord source = createSourceActivity(tdaOnSecondaryDisplay, + WINDOWING_MODE_FULLSCREEN); + + ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchTaskDisplayAreaFeatureId(tdaOnSecondaryDisplay.mFeatureId); + + assertEquals(RESULT_CONTINUE, + new CalculateRequestBuilder().setSource(source).setOptions(options).calculate()); + // Display id wasn't specified in ActivityOptions - the activity should be placed on the + // default display, into the TaskDisplayArea with the same feature id. + assertEquals(tdaOnDefaultDisplay, mResult.mPreferredTaskDisplayArea); + } + + @Test public void testRecalculateFreeformInitialBoundsWithOverrideDisplayArea() { final TestDisplayContent freeformDisplay = createNewDisplayContent( WINDOWING_MODE_FREEFORM); @@ -1822,6 +1890,13 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { return new ActivityBuilder(mAtm).setTask(rootTask).build(); } + private ActivityRecord createSourceActivity(TaskDisplayArea taskDisplayArea, + int windowingMode) { + final Task rootTask = taskDisplayArea.createRootTask(windowingMode, ACTIVITY_TYPE_STANDARD, + true); + return new ActivityBuilder(mAtm).setTask(rootTask).build(); + } + private void addFreeformTaskTo(TestDisplayContent display, Rect bounds) { final Task rootTask = display.getDefaultTaskDisplayArea() .createRootTask(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true); 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 03b818843aa2..7d501356d469 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -931,47 +931,6 @@ public class WindowStateTests extends WindowTestsBase { @UseTestDisplay(addWindows = { W_ACTIVITY }) @Test - public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { - final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW, - ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2"); - final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow"); - spyOn(imeWindow); - doReturn(true).when(imeWindow).isVisible(); - mDisplayContent.mInputMethodWindow = imeWindow; - - final InsetsStateController controller = mDisplayContent.getInsetsStateController(); - controller.getImeSourceProvider().setWindow(imeWindow, null, null); - - // Simulate app2 in multi-window mode is going to background to switch to the fullscreen - // app which requests IME with updating all windows Insets State when IME is above app. - app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true; - mDisplayContent.setImeLayeringTarget(app); - mDisplayContent.setImeInputTarget(app); - assertTrue(mDisplayContent.shouldImeAttachedToApp()); - controller.getImeSourceProvider().scheduleShowImePostLayout(app); - controller.getImeSourceProvider().getSource().setVisible(true); - controller.updateAboveInsetsState(imeWindow, false); - - // Expect app windows behind IME can receive IME insets visible, - // but not for app2 in background. - assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); - assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); - - // Simulate app plays closing transition to app2. - // And app2 is now IME layering target but not yet to be the IME input target. - mDisplayContent.setImeLayeringTarget(app2); - app.mActivityRecord.commitVisibility(false, false); - assertTrue(app.mActivityRecord.mLastImeShown); - assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); - - // Verify the IME insets is still visible on app, but not for app2 during task switching. - assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); - assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); - } - - @UseTestDisplay(addWindows = {W_ACTIVITY}) - @Test public void testUpdateImeControlTargetWhenLeavingMultiWindow() { WindowState app = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken, "app"); diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index af1d56aef310..610190ea0e23 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -175,7 +175,11 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser // Delay for debouncing USB disconnects. // We often get rapid connect/disconnect events when enabling USB functions, // which need debouncing. - private static final int UPDATE_DELAY = 1000; + private static final int DEVICE_STATE_UPDATE_DELAY_EXT = 3000; + private static final int DEVICE_STATE_UPDATE_DELAY = 1000; + + // Delay for debouncing USB disconnects on Type-C ports in host mode + private static final int HOST_STATE_UPDATE_DELAY = 1000; // Timeout for entering USB request mode. // Request is cancelled if host does not configure device within 10 seconds. @@ -637,7 +641,9 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser msg.arg1 = connected; msg.arg2 = configured; // debounce disconnects to avoid problems bringing up USB tethering - sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0); + sendMessageDelayed(msg, + (connected == 0) ? (mScreenLocked ? DEVICE_STATE_UPDATE_DELAY + : DEVICE_STATE_UPDATE_DELAY_EXT) : 0); } public void updateHostState(UsbPort port, UsbPortStatus status) { @@ -652,7 +658,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser removeMessages(MSG_UPDATE_PORT_STATE); Message msg = obtainMessage(MSG_UPDATE_PORT_STATE, args); // debounce rapid transitions of connect/disconnect on type-c ports - sendMessageDelayed(msg, UPDATE_DELAY); + sendMessageDelayed(msg, HOST_STATE_UPDATE_DELAY); } private void setAdbEnabled(boolean enable) { diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java index 85d59a216f25..9dfb0cc289ee 100644 --- a/telephony/common/android/telephony/LocationAccessPolicy.java +++ b/telephony/common/android/telephony/LocationAccessPolicy.java @@ -361,7 +361,10 @@ public final class LocationAccessPolicy { return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context, pid, uid); } - private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) { + /** + * @return Whether location is enabled for the given user. + */ + public static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) { LocationManager locationManager = context.getSystemService(LocationManager.class); if (locationManager == null) { Log.w(TAG, "Couldn't get location manager, denying location access"); @@ -370,6 +373,14 @@ public final class LocationAccessPolicy { return locationManager.isLocationEnabledForUser(UserHandle.of(userId)); } + /** + * @return An array of packages that are always allowed to access location. + */ + public static @NonNull String[] getLocationBypassPackages(@NonNull Context context) { + return context.getResources().getStringArray( + com.android.internal.R.array.config_serviceStateLocationAllowedPackages); + } + private static boolean checkInteractAcrossUsersFull( @NonNull Context context, int pid, int uid) { return checkManifestPermission(context, pid, uid, diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java index b5d97abdd3eb..c2a986465b02 100644 --- a/telephony/java/android/telephony/AccessNetworkUtils.java +++ b/telephony/java/android/telephony/AccessNetworkUtils.java @@ -4,8 +4,8 @@ import static android.telephony.ServiceState.DUPLEX_MODE_FDD; import static android.telephony.ServiceState.DUPLEX_MODE_TDD; import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN; -import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.EutranBand; +import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.GeranBand; import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.NgranArfcnFrequency; @@ -13,7 +13,6 @@ import android.telephony.AccessNetworkConstants.NgranBands; import android.telephony.AccessNetworkConstants.UtranBand; import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency; import android.telephony.ServiceState.DuplexMode; -import android.util.Log; import java.util.Arrays; import java.util.HashSet; @@ -232,6 +231,108 @@ public class AccessNetworkUtils { } /** + * Gets the NR Operating band for a given downlink NRARFCN. + * + * <p>See 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 and + * Table 5.2-2 NR operating bands in FR2 + * + * @param nrarfcn The downlink NRARFCN + * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists + */ + public static int getOperatingBandForNrarfcn(int nrarfcn) { + if (nrarfcn >= 422000 && nrarfcn <= 434000) { + return NgranBands.BAND_1; + } else if (nrarfcn >= 386000 && nrarfcn <= 398000) { + return NgranBands.BAND_2; + } else if (nrarfcn >= 361000 && nrarfcn <= 376000) { + return NgranBands.BAND_3; + } else if (nrarfcn >= 173800 && nrarfcn <= 178800) { + return NgranBands.BAND_5; + } else if (nrarfcn >= 524000 && nrarfcn <= 538000) { + return NgranBands.BAND_7; + } else if (nrarfcn >= 185000 && nrarfcn <= 192000) { + return NgranBands.BAND_8; + } else if (nrarfcn >= 145800 && nrarfcn <= 149200) { + return NgranBands.BAND_12; + } else if (nrarfcn >= 151600 && nrarfcn <= 153600) { + return NgranBands.BAND_14; + } else if (nrarfcn >= 172000 && nrarfcn <= 175000) { + return NgranBands.BAND_18; + } else if (nrarfcn >= 158200 && nrarfcn <= 164200) { + return NgranBands.BAND_20; + } else if (nrarfcn >= 386000 && nrarfcn <= 399000) { + return NgranBands.BAND_25; + } else if (nrarfcn >= 171800 && nrarfcn <= 178800) { + return NgranBands.BAND_26; + } else if (nrarfcn >= 151600 && nrarfcn <= 160600) { + return NgranBands.BAND_28; + } else if (nrarfcn >= 143400 && nrarfcn <= 145600) { + return NgranBands.BAND_29; + } else if (nrarfcn >= 470000 && nrarfcn <= 472000) { + return NgranBands.BAND_30; + } else if (nrarfcn >= 402000 && nrarfcn <= 405000) { + return NgranBands.BAND_34; + } else if (nrarfcn >= 514000 && nrarfcn <= 524000) { + return NgranBands.BAND_38; + } else if (nrarfcn >= 376000 && nrarfcn <= 384000) { + return NgranBands.BAND_39; + } else if (nrarfcn >= 460000 && nrarfcn <= 480000) { + return NgranBands.BAND_40; + } else if (nrarfcn >= 499200 && nrarfcn <= 537999) { + return NgranBands.BAND_41; + } else if (nrarfcn >= 743334 && nrarfcn <= 795000) { + return NgranBands.BAND_46; + } else if (nrarfcn >= 636667 && nrarfcn <= 646666) { + return NgranBands.BAND_48; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_50; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_51; + } else if (nrarfcn >= 496700 && nrarfcn <= 499000) { + return NgranBands.BAND_53; + } else if (nrarfcn >= 422000 && nrarfcn <= 440000) { + return NgranBands.BAND_65; // BAND_66 has the same channels + } else if (nrarfcn >= 399000 && nrarfcn <= 404000) { + return NgranBands.BAND_70; + } else if (nrarfcn >= 123400 && nrarfcn <= 130400) { + return NgranBands.BAND_71; + } else if (nrarfcn >= 295000 && nrarfcn <= 303600) { + return NgranBands.BAND_74; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_75; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_76; + } else if (nrarfcn >= 620000 && nrarfcn <= 680000) { + return NgranBands.BAND_77; + } else if (nrarfcn >= 620000 && nrarfcn <= 653333) { + return NgranBands.BAND_78; + } else if (nrarfcn >= 693334 && nrarfcn <= 733333) { + return NgranBands.BAND_79; + } else if (nrarfcn >= 499200 && nrarfcn <= 538000) { + return NgranBands.BAND_90; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_91; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_92; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_93; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_94; + } else if (nrarfcn >= 795000 && nrarfcn <= 875000) { + return NgranBands.BAND_96; + } else if (nrarfcn >= 2054166 && nrarfcn <= 2104165) { + return NgranBands.BAND_257; + } else if (nrarfcn >= 2016667 && nrarfcn <= 2070832) { + return NgranBands.BAND_258; + } else if (nrarfcn >= 2229166 && nrarfcn <= 2279165) { + return NgranBands.BAND_260; + } else if (nrarfcn >= 2070833 && nrarfcn <= 2084999) { + return NgranBands.BAND_261; + } + return INVALID_BAND; + } + + /** * Gets the GERAN Operating band for a given ARFCN. * * <p>See 3GPP TS 45.005 clause 2 for calculation. |