Merge "cleanupOrphanPA's feature framework (2/2)*"
diff --git a/Android.bp b/Android.bp
index b0a1f93..287f271 100644
--- a/Android.bp
+++ b/Android.bp
@@ -298,6 +298,7 @@
         "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 2182f0b..23464f8 100644
--- a/apct-tests/perftests/core/Android.bp
+++ b/apct-tests/perftests/core/Android.bp
@@ -43,12 +43,13 @@
         "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/CharsetUtf8PerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/CharsetUtf8PerfTest.java
index f31e9c1..b753006 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/CharsetUtf8PerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/CharsetUtf8PerfTest.java
@@ -37,9 +37,7 @@
 public class CharsetUtf8PerfTest {
     @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
-    private final int mNoOfBytes = 0x100; // 4MB
-
-    private void makeUnicodeRange(int startingCodePoint, int endingCodePoint, int repeated) {
+    private void makeUnicodeRange(int startingCodePoint, int endingCodePoint) {
         StringBuilder builder = new StringBuilder();
         for (int codePoint = startingCodePoint; codePoint <= endingCodePoint; codePoint++) {
             if (codePoint < Character.MIN_SURROGATE || codePoint > Character.MAX_SURROGATE) {
@@ -48,35 +46,30 @@
         }
 
         String str = builder.toString();
-        StringBuilder builder2 = new StringBuilder();
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
-            for (int i = 0; i < repeated; i++) {
-                builder2.append(str);
-            }
+            StringBuilder builder2 = new StringBuilder();
+            builder2.append(str);
         }
     }
 
     @Test
     public void time_ascii() {
-        makeUnicodeRange(0, 0x7f, mNoOfBytes / 0x80);
+        makeUnicodeRange(0, 0x7f);
     }
 
     @Test
     public void time_bmp2() {
-        makeUnicodeRange(0x0080, 0x07ff, mNoOfBytes / 2 / 0x780);
+        makeUnicodeRange(0x0080, 0x07ff);
     }
 
     @Test
     public void time_bmp3() {
-        makeUnicodeRange(
-                0x0800,
-                0xffff,
-                mNoOfBytes / 3 / 0xf000 /* 0x10000 - 0x0800 - no of surrogate code points */);
+        makeUnicodeRange(0x0800, 0xffff);
     }
 
     @Test
     public void time_supplementary() {
-        makeUnicodeRange(0x10000, 0x10ffff, mNoOfBytes / 4 / 0x100000);
+        makeUnicodeRange(0x10000, 0x10ffff);
     }
 }
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 03c9d43..adcd571 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 @@
     }
 
     @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 0000000..694d609
--- /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 0000000..bdbbcb0
--- /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 0000000..42dc581
--- /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 0000000..1ec22d2
--- /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 0000000..96e7cb2
--- /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 0000000..c25b0ce
--- /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 0000000..eeccb5b
--- /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 0000000..34fb88b
--- /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 0000000..6854c0d
--- /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 0000000..79ff646
--- /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 0000000..8dbf9f5
--- /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 0000000..02194b1
--- /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 0000000..b0d1ee4
--- /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 0000000..d2e657a
--- /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 0000000..2bb25ac
--- /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 0000000..1efc188
--- /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 0000000..b01948a
--- /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 0000000..f256555
--- /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 0000000..8274512
--- /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 0000000..2ea834d
--- /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>&amp;&amp;++</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("&amp;");
+        }
+        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/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java b/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java
index 2700fff..76656bd 100644
--- a/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java
+++ b/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java
@@ -52,21 +52,45 @@
         while (state.keepRunning()) {
             os.reset();
             final BufferedOutputStream bos = new BufferedOutputStream(os, BUFFER_SIZE);
-            final DataOutput out = new DataOutputStream(bos);
-            doWrite(out);
-            bos.flush();
+            final DataOutputStream out = new DataOutputStream(bos);
+            try {
+                doWrite(out);
+                out.flush();
+            } finally {
+                out.close();
+            }
         }
     }
 
     @Test
-    public void timeWrite_Local() throws IOException {
+    public void timeWrite_LocalUsing4ByteSequences() throws IOException {
         final ByteArrayOutputStream os = new ByteArrayOutputStream(OUTPUT_SIZE);
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             os.reset();
-            final FastDataOutput out = new FastDataOutput(os, BUFFER_SIZE);
-            doWrite(out);
-            out.flush();
+            final FastDataOutput out = FastDataOutput.obtainUsing4ByteSequences(os);
+            try {
+                doWrite(out);
+                out.flush();
+            } finally {
+                out.release();
+            }
+        }
+    }
+
+    @Test
+    public void timeWrite_LocalUsing3ByteSequences() throws IOException {
+        final ByteArrayOutputStream os = new ByteArrayOutputStream(OUTPUT_SIZE);
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            os.reset();
+            final FastDataOutput out = FastDataOutput.obtainUsing3ByteSequences(os);
+            try {
+                doWrite(out);
+                out.flush();
+            } finally {
+                out.release();
+            }
         }
     }
 
@@ -77,19 +101,42 @@
         while (state.keepRunning()) {
             is.reset();
             final BufferedInputStream bis = new BufferedInputStream(is, BUFFER_SIZE);
-            final DataInput in = new DataInputStream(bis);
-            doRead(in);
+            final DataInputStream in = new DataInputStream(bis);
+            try {
+                doRead(in);
+            } finally {
+                in.close();
+            }
         }
     }
 
     @Test
-    public void timeRead_Local() throws Exception {
+    public void timeRead_LocalUsing4ByteSequences() throws Exception {
         final ByteArrayInputStream is = new ByteArrayInputStream(doWrite());
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             is.reset();
-            final DataInput in = new FastDataInput(is, BUFFER_SIZE);
-            doRead(in);
+            final FastDataInput in = FastDataInput.obtainUsing4ByteSequences(is);
+            try {
+                doRead(in);
+            } finally {
+                in.release();
+            }
+        }
+    }
+
+    @Test
+    public void timeRead_LocalUsing3ByteSequences() throws Exception {
+        final ByteArrayInputStream is = new ByteArrayInputStream(doWrite());
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            is.reset();
+            final FastDataInput in = FastDataInput.obtainUsing3ByteSequences(is);
+            try {
+                doRead(in);
+            } finally {
+                in.release();
+            }
         }
     }
 
diff --git a/config/boot-image-profile-extra.txt b/config/boot-image-profile-extra.txt
new file mode 100644
index 0000000..e3b187e
--- /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/current.txt b/core/api/current.txt
index dc19496..e513bba 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29758,7 +29758,7 @@
     method @Deprecated public static void changeDebugPort(int);
     method public static void dumpHprofData(String) throws java.io.IOException;
     method public static boolean dumpService(String, java.io.FileDescriptor, String[]);
-    method public static void enableEmulatorTraceOutput();
+    method @Deprecated public static void enableEmulatorTraceOutput();
     method public static int getBinderDeathObjectCount();
     method public static int getBinderLocalObjectCount();
     method public static int getBinderProxyObjectCount();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index abc2b74..cf3f07f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -230,6 +230,7 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 bfbb910..51ecd4c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -149,6 +149,7 @@
     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 6a877f9..d7ff7e9 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4366,8 +4366,8 @@
         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 0ff9f66..a92cbf3 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -21,6 +21,7 @@
 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 @@
             "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 @@
     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 @@
         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 @@
     }
 
     /** @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 @@
         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 24046c0..52228e5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1185,7 +1185,7 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
 
     @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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 df95f8f..f2c808b 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -138,7 +138,7 @@
     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 19ef9d7..4d9a633 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 402007d..de9d491 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -37,6 +37,7 @@
 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 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 @@
     }
 
     /**
+     * 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 3a02004..18a46cf 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -494,8 +494,10 @@
     /** @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 22c838c..76591ca 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3836,7 +3836,7 @@
      * {@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 @@
      *
      * @hide
      */
+    @SystemApi
+    @SuppressLint("ActionValue")
     public static final String EXTRA_USER_HANDLE =
             "android.intent.extra.user_handle";
 
@@ -6824,6 +6826,7 @@
      *
      * @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 a411eee..61325bc 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -168,7 +168,7 @@
      * 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 d06bc1d..3e41d63 100644
--- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
+++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
@@ -122,6 +122,9 @@
     }
 
     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 @@
     }
 
     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 59db8f4..a7c7ce2 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -350,7 +350,7 @@
     }
 
     /**
-     * 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 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/Debug.java b/core/java/android/os/Debug.java
index b4930fa..399f11b 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1155,6 +1155,8 @@
      * consequences.
      *
      * To temporarily enable tracing, use {@link #startNativeTracing()}.
+     *
+     * @deprecated Please use other tracing method in this class.
      */
     public static void enableEmulatorTraceOutput() {
         Log.w(TAG, "Unimplemented");
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 6411f42..9649d38 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -33,6 +33,7 @@
 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;
@@ -247,6 +248,7 @@
     private ArrayMap<Class, Object> mClassCookies;
 
     private RuntimeException mStack;
+    private boolean mRecycled = false;
 
     /** @hide */
     @TestApi
@@ -528,6 +530,7 @@
         if (res == null) {
             res = new Parcel(0);
         } else {
+            res.mRecycled = false;
             if (DEBUG_RECYCLE) {
                 res.mStack = new RuntimeException();
             }
@@ -556,7 +559,15 @@
      * the object after this call.
      */
     public final void recycle() {
-        if (DEBUG_RECYCLE) mStack = null;
+        if (mRecycled) {
+            Log.w(TAG, "Recycle called on unowned Parcel. (recycle twice?)", mStack);
+        }
+        mRecycled = true;
+
+        // We try to reset the entire object here, but in order to be
+        // able to print a stack when a Parcel is recycled twice, that
+        // is cleared in obtain instead.
+
         mClassCookies = null;
         freeBuffer();
 
@@ -4848,28 +4859,36 @@
         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.
@@ -4877,7 +4896,7 @@
                     (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 "
@@ -4924,8 +4943,9 @@
                     + "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;
@@ -5076,12 +5096,17 @@
         }
     }
 
-    // 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) {
@@ -5105,6 +5130,7 @@
         if (res == null) {
             res = new Parcel(obj);
         } else {
+            res.mRecycled = false;
             if (DEBUG_RECYCLE) {
                 res.mStack = new RuntimeException();
             }
@@ -5153,7 +5179,8 @@
     @Override
     protected void finalize() throws Throwable {
         if (DEBUG_RECYCLE) {
-            if (mStack != null) {
+            // we could always have this log on, but it's spammy
+            if (!mRecycled) {
                 Log.w(TAG, "Client did not call Parcel.recycle()", mStack);
             }
         }
diff --git a/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
index cb521c8..4564c30 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 49f4bf7..d34b45b 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 fe012da..6efb975 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 19ef9d7..d3acd3d3 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/java/android/util/CharsetUtils.java b/core/java/android/util/CharsetUtils.java
index fa14667..3b08c3b 100644
--- a/core/java/android/util/CharsetUtils.java
+++ b/core/java/android/util/CharsetUtils.java
@@ -26,6 +26,12 @@
  * <p>
  * These methods purposefully accept only non-movable byte array addresses to
  * avoid extra JNI overhead.
+ * <p>
+ * Callers are cautioned that there is a long-standing ART bug that emits
+ * non-standard 4-byte sequences, as described by {@code kUtfUse4ByteSequence}
+ * in {@code art/runtime/jni/jni_internal.cc}. If precise modified UTF-8
+ * encoding is required, use {@link com.android.internal.util.ModifiedUtf8}
+ * instead.
  *
  * @hide
  */
@@ -33,6 +39,12 @@
     /**
      * Attempt to encode the given string as modified UTF-8 into the destination
      * byte array without making any new allocations.
+     * <p>
+     * Callers are cautioned that there is a long-standing ART bug that emits
+     * non-standard 4-byte sequences, as described by
+     * {@code kUtfUse4ByteSequence} in {@code art/runtime/jni/jni_internal.cc}.
+     * If precise modified UTF-8 encoding is required, use
+     * {@link com.android.internal.util.ModifiedUtf8} instead.
      *
      * @param src string value to be encoded
      * @param dest destination byte array to encode into
@@ -50,6 +62,12 @@
     /**
      * Attempt to encode the given string as modified UTF-8 into the destination
      * byte array without making any new allocations.
+     * <p>
+     * Callers are cautioned that there is a long-standing ART bug that emits
+     * non-standard 4-byte sequences, as described by
+     * {@code kUtfUse4ByteSequence} in {@code art/runtime/jni/jni_internal.cc}.
+     * If precise modified UTF-8 encoding is required, use
+     * {@link com.android.internal.util.ModifiedUtf8} instead.
      *
      * @param src string value to be encoded
      * @param srcLen exact length of string to be encoded
@@ -66,6 +84,12 @@
 
     /**
      * Attempt to decode a modified UTF-8 string from the source byte array.
+     * <p>
+     * Callers are cautioned that there is a long-standing ART bug that emits
+     * non-standard 4-byte sequences, as described by
+     * {@code kUtfUse4ByteSequence} in {@code art/runtime/jni/jni_internal.cc}.
+     * If precise modified UTF-8 encoding is required, use
+     * {@link com.android.internal.util.ModifiedUtf8} instead.
      *
      * @param src source byte array to decode from
      * @param srcOff offset into source where decoding should begin
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index b5fe4f5..f1e91d0 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -66,6 +66,10 @@
  * <p>When calling the log methods that take a Throwable parameter,
  * if any of the throwables in the cause chain is an <code>UnknownHostException</code>,
  * then the stack trace is not logged.
+ *
+ * <p>Note: The return value from the logging functions in this class may vary between Android
+ * releases due to changes in the logging implementation. For the methods that return an integer,
+ * a positive value may be considered as a successful invocation.
  */
 public final class Log {
     /** @hide */
@@ -134,6 +138,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int v(@Nullable String tag, @NonNull String msg) {
         return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
@@ -144,7 +149,8 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
-     * @param tr An exception to log
+     * @param tr An exception to log.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int v(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
         return printlns(LOG_ID_MAIN, VERBOSE, tag, msg, tr);
@@ -155,6 +161,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int d(@Nullable String tag, @NonNull String msg) {
         return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
@@ -165,7 +172,8 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
-     * @param tr An exception to log
+     * @param tr An exception to log.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int d(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
         return printlns(LOG_ID_MAIN, DEBUG, tag, msg, tr);
@@ -176,6 +184,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int i(@Nullable String tag, @NonNull String msg) {
         return println_native(LOG_ID_MAIN, INFO, tag, msg);
@@ -186,7 +195,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
-     * @param tr An exception to log
+     * @param tr An exception to log.
      */
     public static int i(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
         return printlns(LOG_ID_MAIN, INFO, tag, msg, tr);
@@ -197,6 +206,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int w(@Nullable String tag, @NonNull String msg) {
         return println_native(LOG_ID_MAIN, WARN, tag, msg);
@@ -207,7 +217,8 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
-     * @param tr An exception to log
+     * @param tr An exception to log.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int w(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
         return printlns(LOG_ID_MAIN, WARN, tag, msg, tr);
@@ -239,7 +250,8 @@
      * Send a {@link #WARN} log message and log the exception.
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
-     * @param tr An exception to log
+     * @param tr An exception to log.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int w(@Nullable String tag, @Nullable Throwable tr) {
         return printlns(LOG_ID_MAIN, WARN, tag, "", tr);
@@ -250,6 +262,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int e(@Nullable String tag, @NonNull String msg) {
         return println_native(LOG_ID_MAIN, ERROR, tag, msg);
@@ -260,7 +273,8 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
-     * @param tr An exception to log
+     * @param tr An exception to log.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int e(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
         return printlns(LOG_ID_MAIN, ERROR, tag, msg, tr);
@@ -274,6 +288,7 @@
      * immediately with an error dialog.
      * @param tag Used to identify the source of a log message.
      * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int wtf(@Nullable String tag, @Nullable String msg) {
         return wtf(LOG_ID_MAIN, tag, msg, null, false, false);
@@ -293,6 +308,7 @@
      * Similar to {@link #wtf(String, String)}, with an exception to log.
      * @param tag Used to identify the source of a log message.
      * @param tr An exception to log.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int wtf(@Nullable String tag, @NonNull Throwable tr) {
         return wtf(LOG_ID_MAIN, tag, tr.getMessage(), tr, false, false);
@@ -304,6 +320,7 @@
      * @param tag Used to identify the source of a log message.
      * @param msg The message you would like logged.
      * @param tr An exception to log.  May be null.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int wtf(@Nullable String tag, @Nullable String msg, @Nullable Throwable tr) {
         return wtf(LOG_ID_MAIN, tag, msg, tr, false, false);
@@ -348,7 +365,7 @@
 
      * <p>If any of the throwables in the cause chain is an <code>UnknownHostException</code>,
      * this returns an empty string.
-     * @param tr An exception to log
+     * @param tr An exception to log.
      */
     @NonNull
     public static String getStackTraceString(@Nullable Throwable tr) {
@@ -379,7 +396,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param msg The message you would like logged.
-     * @return The number of bytes written.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      */
     public static int println(@Level int priority, @Nullable String tag, @NonNull String msg) {
         return println_native(LOG_ID_MAIN, priority, tag, msg);
@@ -391,7 +408,16 @@
     /** @hide */ public static final int LOG_ID_SYSTEM = 3;
     /** @hide */ public static final int LOG_ID_CRASH = 4;
 
-    /** @hide */
+    /**
+     * Low-level logging call.
+     * @param bufID The buffer ID to receive the message.
+     * @param priority The priority of the message.
+     * @param tag Used to identify the source of a log message.  It usually identifies
+     *        the class or activity where the log call occurs.
+     * @param msg The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
+     * @hide
+     */
     @UnsupportedAppUsage
     public static native int println_native(int bufID, int priority, String tag, String msg);
 
@@ -407,6 +433,7 @@
      * @param tag Used to identify the source of a log message.  It usually identifies
      *        the class or activity where the log call occurs.
      * @param message The message you would like logged.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      * @hide
      */
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@@ -425,6 +452,7 @@
      * Helper function for long messages. Uses the LineBreakBufferedWriter to break
      * up long messages and stacktraces along newlines, but tries to write in large
      * chunks. This is to avoid truncation.
+     * @return A positive value if the message was loggable (see {@link #isLoggable}).
      * @hide
      */
     public static int printlns(int bufID, int priority, @Nullable String tag, @NonNull String msg,
diff --git a/core/java/android/util/TEST_MAPPING b/core/java/android/util/TEST_MAPPING
new file mode 100644
index 0000000..0ae1c15
--- /dev/null
+++ b/core/java/android/util/TEST_MAPPING
@@ -0,0 +1,28 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.util.CharsetUtilsTest"
+        },
+        {
+          "include-filter": "com.android.internal.util.FastDataTest"
+        }
+      ],
+      "file_patterns": ["CharsetUtils|FastData"]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.util.XmlTest"
+        },
+        {
+          "include-filter": "android.util.BinaryXmlTest"
+        }
+      ],
+      "file_patterns": ["Xml"]
+    }
+  ]
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ffa577a..271d7ba 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12810,6 +12810,10 @@
 
     /**
      * Set if view is a heading for a section of content for accessibility purposes.
+     * <p>
+     * Users of some accessibility services can choose to navigate between headings
+     * instead of between paragraphs, words, etc. Apps that provide headings on
+     * sections of text can help the text navigation experience.
      *
      * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
      *
diff --git a/core/java/com/android/internal/util/BinaryXmlPullParser.java b/core/java/com/android/internal/util/BinaryXmlPullParser.java
index 57552f3..d3abac9 100644
--- a/core/java/com/android/internal/util/BinaryXmlPullParser.java
+++ b/core/java/com/android/internal/util/BinaryXmlPullParser.java
@@ -73,12 +73,6 @@
  * </ul>
  */
 public final class BinaryXmlPullParser implements TypedXmlPullParser {
-    /**
-     * Default buffer size, which matches {@code FastXmlSerializer}. This should
-     * be kept in sync with {@link BinaryXmlPullParser}.
-     */
-    private static final int BUFFER_SIZE = 32_768;
-
     private FastDataInput mIn;
 
     private int mCurrentToken = START_DOCUMENT;
@@ -100,7 +94,12 @@
             throw new UnsupportedOperationException();
         }
 
-        mIn = new FastDataInput(is, BUFFER_SIZE);
+        if (mIn != null) {
+            mIn.release();
+            mIn = null;
+        }
+
+        mIn = FastDataInput.obtainUsing4ByteSequences(is);
 
         mCurrentToken = START_DOCUMENT;
         mCurrentDepth = 0;
diff --git a/core/java/com/android/internal/util/BinaryXmlSerializer.java b/core/java/com/android/internal/util/BinaryXmlSerializer.java
index 9df4bdb..485430a 100644
--- a/core/java/com/android/internal/util/BinaryXmlSerializer.java
+++ b/core/java/com/android/internal/util/BinaryXmlSerializer.java
@@ -91,12 +91,6 @@
     static final int TYPE_BOOLEAN_TRUE = 12 << 4;
     static final int TYPE_BOOLEAN_FALSE = 13 << 4;
 
-    /**
-     * Default buffer size, which matches {@code FastXmlSerializer}. This should
-     * be kept in sync with {@link BinaryXmlPullParser}.
-     */
-    private static final int BUFFER_SIZE = 32_768;
-
     private FastDataOutput mOut;
 
     /**
@@ -124,7 +118,7 @@
             throw new UnsupportedOperationException();
         }
 
-        mOut = new FastDataOutput(os, BUFFER_SIZE);
+        mOut = FastDataOutput.obtainUsing4ByteSequences(os);
         mOut.write(PROTOCOL_MAGIC_VERSION_0);
 
         mTagCount = 0;
@@ -138,7 +132,9 @@
 
     @Override
     public void flush() throws IOException {
-        mOut.flush();
+        if (mOut != null) {
+            mOut.flush();
+        }
     }
 
     @Override
@@ -157,6 +153,9 @@
     public void endDocument() throws IOException {
         mOut.writeByte(END_DOCUMENT | TYPE_NULL);
         flush();
+
+        mOut.release();
+        mOut = null;
     }
 
     @Override
diff --git a/core/java/com/android/internal/util/FastDataInput.java b/core/java/com/android/internal/util/FastDataInput.java
index f8d241b..5117034 100644
--- a/core/java/com/android/internal/util/FastDataInput.java
+++ b/core/java/com/android/internal/util/FastDataInput.java
@@ -30,6 +30,7 @@
 import java.io.InputStream;
 import java.util.Arrays;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Optimized implementation of {@link DataInput} which buffers data in memory
@@ -41,13 +42,18 @@
 public class FastDataInput implements DataInput, Closeable {
     private static final int MAX_UNSIGNED_SHORT = 65_535;
 
+    private static final int DEFAULT_BUFFER_SIZE = 32_768;
+
+    private static AtomicReference<FastDataInput> sInCache = new AtomicReference<>();
+
     private final VMRuntime mRuntime;
-    private final InputStream mIn;
 
     private final byte[] mBuffer;
     private final long mBufferPtr;
     private final int mBufferCap;
+    private final boolean mUse4ByteSequence;
 
+    private InputStream mIn;
     private int mBufferPos;
     private int mBufferLim;
 
@@ -57,7 +63,18 @@
     private int mStringRefCount = 0;
     private String[] mStringRefs = new String[32];
 
+    /**
+     * @deprecated callers must specify {@code use4ByteSequence} so they make a
+     *             clear choice about working around a long-standing ART bug, as
+     *             described by the {@code kUtfUse4ByteSequence} comments in
+     *             {@code art/runtime/jni/jni_internal.cc}.
+     */
+    @Deprecated
     public FastDataInput(@NonNull InputStream in, int bufferSize) {
+        this(in, bufferSize, true /* use4ByteSequence */);
+    }
+
+    public FastDataInput(@NonNull InputStream in, int bufferSize, boolean use4ByteSequence) {
         mRuntime = VMRuntime.getRuntime();
         mIn = Objects.requireNonNull(in);
         if (bufferSize < 8) {
@@ -67,6 +84,64 @@
         mBuffer = (byte[]) mRuntime.newNonMovableArray(byte.class, bufferSize);
         mBufferPtr = mRuntime.addressOf(mBuffer);
         mBufferCap = mBuffer.length;
+        mUse4ByteSequence = use4ByteSequence;
+    }
+
+    /**
+     * Obtain a {@link FastDataInput} configured with the given
+     * {@link InputStream} and which encodes large code-points using 3-byte
+     * sequences.
+     * <p>
+     * This <em>is</em> compatible with the {@link DataInput} API contract,
+     * which specifies that large code-points must be encoded with 3-byte
+     * sequences.
+     */
+    public static FastDataInput obtainUsing3ByteSequences(@NonNull InputStream in) {
+        return new FastDataInput(in, DEFAULT_BUFFER_SIZE, false /* use4ByteSequence */);
+    }
+
+    /**
+     * Obtain a {@link FastDataInput} configured with the given
+     * {@link InputStream} and which decodes large code-points using 4-byte
+     * sequences.
+     * <p>
+     * This <em>is not</em> compatible with the {@link DataInput} API contract,
+     * which specifies that large code-points must be encoded with 3-byte
+     * sequences.
+     */
+    public static FastDataInput obtainUsing4ByteSequences(@NonNull InputStream in) {
+        FastDataInput instance = sInCache.getAndSet(null);
+        if (instance != null) {
+            instance.setInput(in);
+            return instance;
+        }
+        return new FastDataInput(in, DEFAULT_BUFFER_SIZE, true /* use4ByteSequence */);
+    }
+
+    /**
+     * Release a {@link FastDataInput} to potentially be recycled. You must not
+     * interact with the object after releasing it.
+     */
+    public void release() {
+        mIn = null;
+        mBufferPos = 0;
+        mBufferLim = 0;
+        mStringRefCount = 0;
+
+        if (mBufferCap == DEFAULT_BUFFER_SIZE && mUse4ByteSequence) {
+            // Try to return to the cache.
+            sInCache.compareAndSet(null, this);
+        }
+    }
+
+    /**
+     * Re-initializes the object for the new input.
+     */
+    private void setInput(@NonNull InputStream in) {
+        mIn = Objects.requireNonNull(in);
+        mBufferPos = 0;
+        mBufferLim = 0;
+        mStringRefCount = 0;
     }
 
     private void fill(int need) throws IOException {
@@ -90,6 +165,7 @@
     @Override
     public void close() throws IOException {
         mIn.close();
+        release();
     }
 
     @Override
@@ -126,6 +202,14 @@
 
     @Override
     public String readUTF() throws IOException {
+        if (mUse4ByteSequence) {
+            return readUTFUsing4ByteSequences();
+        } else {
+            return readUTFUsing3ByteSequences();
+        }
+    }
+
+    private String readUTFUsing4ByteSequences() throws IOException {
         // Attempt to read directly from buffer space if there's enough room,
         // otherwise fall back to chunking into place
         final int len = readUnsignedShort();
@@ -141,6 +225,22 @@
         }
     }
 
+    private String readUTFUsing3ByteSequences() throws IOException {
+        // Attempt to read directly from buffer space if there's enough room,
+        // otherwise fall back to chunking into place
+        final int len = readUnsignedShort();
+        if (mBufferCap > len) {
+            if (mBufferLim - mBufferPos < len) fill(len);
+            final String res = ModifiedUtf8.decode(mBuffer, new char[len], mBufferPos, len);
+            mBufferPos += len;
+            return res;
+        } else {
+            final byte[] tmp = (byte[]) mRuntime.newNonMovableArray(byte.class, len + 1);
+            readFully(tmp, 0, len);
+            return ModifiedUtf8.decode(tmp, new char[len], 0, len);
+        }
+    }
+
     /**
      * Read a {@link String} value with the additional signal that the given
      * value is a candidate for being canonicalized, similar to
diff --git a/core/java/com/android/internal/util/FastDataOutput.java b/core/java/com/android/internal/util/FastDataOutput.java
index cf5b296..c9e8f8f 100644
--- a/core/java/com/android/internal/util/FastDataOutput.java
+++ b/core/java/com/android/internal/util/FastDataOutput.java
@@ -30,6 +30,7 @@
 import java.io.OutputStream;
 import java.util.HashMap;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Optimized implementation of {@link DataOutput} which buffers data in memory
@@ -41,23 +42,38 @@
 public class FastDataOutput implements DataOutput, Flushable, Closeable {
     private static final int MAX_UNSIGNED_SHORT = 65_535;
 
+    private static final int DEFAULT_BUFFER_SIZE = 32_768;
+
+    private static AtomicReference<FastDataOutput> sOutCache = new AtomicReference<>();
+
     private final VMRuntime mRuntime;
-    private final OutputStream mOut;
 
     private final byte[] mBuffer;
     private final long mBufferPtr;
     private final int mBufferCap;
+    private final boolean mUse4ByteSequence;
 
+    private OutputStream mOut;
     private int mBufferPos;
 
     /**
      * Values that have been "interned" by {@link #writeInternedUTF(String)}.
      */
-    private HashMap<String, Short> mStringRefs = new HashMap<>();
+    private final HashMap<String, Short> mStringRefs = new HashMap<>();
 
+    /**
+     * @deprecated callers must specify {@code use4ByteSequence} so they make a
+     *             clear choice about working around a long-standing ART bug, as
+     *             described by the {@code kUtfUse4ByteSequence} comments in
+     *             {@code art/runtime/jni/jni_internal.cc}.
+     */
+    @Deprecated
     public FastDataOutput(@NonNull OutputStream out, int bufferSize) {
+        this(out, bufferSize, true /* use4ByteSequence */);
+    }
+
+    public FastDataOutput(@NonNull OutputStream out, int bufferSize, boolean use4ByteSequence) {
         mRuntime = VMRuntime.getRuntime();
-        mOut = Objects.requireNonNull(out);
         if (bufferSize < 8) {
             throw new IllegalArgumentException();
         }
@@ -65,6 +81,68 @@
         mBuffer = (byte[]) mRuntime.newNonMovableArray(byte.class, bufferSize);
         mBufferPtr = mRuntime.addressOf(mBuffer);
         mBufferCap = mBuffer.length;
+        mUse4ByteSequence = use4ByteSequence;
+
+        setOutput(out);
+    }
+
+    /**
+     * Obtain a {@link FastDataOutput} configured with the given
+     * {@link OutputStream} and which encodes large code-points using 3-byte
+     * sequences.
+     * <p>
+     * This <em>is</em> compatible with the {@link DataOutput} API contract,
+     * which specifies that large code-points must be encoded with 3-byte
+     * sequences.
+     */
+    public static FastDataOutput obtainUsing3ByteSequences(@NonNull OutputStream out) {
+        return new FastDataOutput(out, DEFAULT_BUFFER_SIZE, false /* use4ByteSequence */);
+    }
+
+    /**
+     * Obtain a {@link FastDataOutput} configured with the given
+     * {@link OutputStream} and which encodes large code-points using 4-byte
+     * sequences.
+     * <p>
+     * This <em>is not</em> compatible with the {@link DataOutput} API contract,
+     * which specifies that large code-points must be encoded with 3-byte
+     * sequences.
+     */
+    public static FastDataOutput obtainUsing4ByteSequences(@NonNull OutputStream out) {
+        FastDataOutput instance = sOutCache.getAndSet(null);
+        if (instance != null) {
+            instance.setOutput(out);
+            return instance;
+        }
+        return new FastDataOutput(out, DEFAULT_BUFFER_SIZE, true /* use4ByteSequence */);
+    }
+
+    /**
+     * Release a {@link FastDataOutput} to potentially be recycled. You must not
+     * interact with the object after releasing it.
+     */
+    public void release() {
+        if (mBufferPos > 0) {
+            throw new IllegalStateException("Lingering data, call flush() before releasing.");
+        }
+
+        mOut = null;
+        mBufferPos = 0;
+        mStringRefs.clear();
+
+        if (mBufferCap == DEFAULT_BUFFER_SIZE && mUse4ByteSequence) {
+            // Try to return to the cache.
+            sOutCache.compareAndSet(null, this);
+        }
+    }
+
+    /**
+     * Re-initializes the object for the new output.
+     */
+    private void setOutput(@NonNull OutputStream out) {
+        mOut = Objects.requireNonNull(out);
+        mBufferPos = 0;
+        mStringRefs.clear();
     }
 
     private void drain() throws IOException {
@@ -83,6 +161,7 @@
     @Override
     public void close() throws IOException {
         mOut.close();
+        release();
     }
 
     @Override
@@ -109,6 +188,14 @@
 
     @Override
     public void writeUTF(String s) throws IOException {
+        if (mUse4ByteSequence) {
+            writeUTFUsing4ByteSequences(s);
+        } else {
+            writeUTFUsing3ByteSequences(s);
+        }
+    }
+
+    private void writeUTFUsing4ByteSequences(String s) throws IOException {
         // Attempt to write directly to buffer space if there's enough room,
         // otherwise fall back to chunking into place
         if (mBufferCap - mBufferPos < 2 + s.length()) drain();
@@ -136,6 +223,27 @@
         }
     }
 
+    private void writeUTFUsing3ByteSequences(String s) throws IOException {
+        final int len = (int) ModifiedUtf8.countBytes(s, false);
+        if (len > MAX_UNSIGNED_SHORT) {
+            throw new IOException("Modified UTF-8 length too large: " + len);
+        }
+
+        // Attempt to write directly to buffer space if there's enough room,
+        // otherwise fall back to chunking into place
+        if (mBufferCap >= 2 + len) {
+            if (mBufferCap - mBufferPos < 2 + len) drain();
+            writeShort(len);
+            ModifiedUtf8.encode(mBuffer, mBufferPos, s);
+            mBufferPos += len;
+        } else {
+            final byte[] tmp = (byte[]) mRuntime.newNonMovableArray(byte.class, len + 1);
+            ModifiedUtf8.encode(tmp, 0, s);
+            writeShort(len);
+            write(tmp, 0, len);
+        }
+    }
+
     /**
      * Write a {@link String} value with the additional signal that the given
      * value is a candidate for being canonicalized, similar to
diff --git a/core/java/com/android/internal/util/ModifiedUtf8.java b/core/java/com/android/internal/util/ModifiedUtf8.java
new file mode 100644
index 0000000..a144c00
--- /dev/null
+++ b/core/java/com/android/internal/util/ModifiedUtf8.java
@@ -0,0 +1,110 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.io.UTFDataFormatException;
+
+public class ModifiedUtf8 {
+    /**
+     * Decodes a byte array containing <i>modified UTF-8</i> bytes into a string.
+     *
+     * <p>Note that although this method decodes the (supposedly impossible) zero byte to U+0000,
+     * that's what the RI does too.
+     */
+    public static String decode(byte[] in, char[] out, int offset, int utfSize)
+            throws UTFDataFormatException {
+        int count = 0, s = 0, a;
+        while (count < utfSize) {
+            if ((out[s] = (char) in[offset + count++]) < '\u0080') {
+                s++;
+            } else if (((a = out[s]) & 0xe0) == 0xc0) {
+                if (count >= utfSize) {
+                    throw new UTFDataFormatException("bad second byte at " + count);
+                }
+                int b = in[offset + count++];
+                if ((b & 0xC0) != 0x80) {
+                    throw new UTFDataFormatException("bad second byte at " + (count - 1));
+                }
+                out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+            } else if ((a & 0xf0) == 0xe0) {
+                if (count + 1 >= utfSize) {
+                    throw new UTFDataFormatException("bad third byte at " + (count + 1));
+                }
+                int b = in[offset + count++];
+                int c = in[offset + count++];
+                if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
+                    throw new UTFDataFormatException("bad second or third byte at " + (count - 2));
+                }
+                out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+            } else {
+                throw new UTFDataFormatException("bad byte at " + (count - 1));
+            }
+        }
+        return new String(out, 0, s);
+    }
+
+    /**
+     * Returns the number of bytes the modified UTF-8 representation of 's' would take. Note
+     * that this is just the space for the bytes representing the characters, not the length
+     * which precedes those bytes, because different callers represent the length differently,
+     * as two, four, or even eight bytes. If {@code shortLength} is true, we'll throw an
+     * exception if the string is too long for its length to be represented by a short.
+     */
+    public static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {
+        long result = 0;
+        final int length = s.length();
+        for (int i = 0; i < length; ++i) {
+            char ch = s.charAt(i);
+            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+                ++result;
+            } else if (ch <= 2047) {
+                result += 2;
+            } else {
+                result += 3;
+            }
+            if (shortLength && result > 65535) {
+                throw new UTFDataFormatException("String more than 65535 UTF bytes long");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Encodes the <i>modified UTF-8</i> bytes corresponding to string {@code s} into the
+     * byte array {@code dst}, starting at the given {@code offset}.
+     */
+    public static void encode(byte[] dst, int offset, String s) {
+        final int length = s.length();
+        for (int i = 0; i < length; i++) {
+            char ch = s.charAt(i);
+            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+                dst[offset++] = (byte) ch;
+            } else if (ch <= 2047) {
+                dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6)));
+                dst[offset++] = (byte) (0x80 | (0x3f & ch));
+            } else {
+                dst[offset++] = (byte) (0xe0 | (0x0f & (ch >> 12)));
+                dst[offset++] = (byte) (0x80 | (0x3f & (ch >> 6)));
+                dst[offset++] = (byte) (0x80 | (0x3f & ch));
+            }
+        }
+    }
+
+    private ModifiedUtf8() {
+    }
+}
diff --git a/core/java/com/android/internal/util/TEST_MAPPING b/core/java/com/android/internal/util/TEST_MAPPING
index 5881c51..41d59bb 100644
--- a/core/java/com/android/internal/util/TEST_MAPPING
+++ b/core/java/com/android/internal/util/TEST_MAPPING
@@ -1,7 +1,20 @@
 {
   "presubmit": [
     {
-       "name": "ScreenshotHelperTests"
+      "name": "ScreenshotHelperTests",
+      "file_patterns": ["ScreenshotHelper"]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.util.XmlTest"
+        },
+        {
+          "include-filter": "android.util.BinaryXmlTest"
+        }
+      ],
+      "file_patterns": ["Xml"]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 682dbc31..a60368b 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -50,6 +50,7 @@
         "android_util_XmlBlock.cpp",
         "android_util_jar_StrictJarFile.cpp",
         "com_android_internal_util_VirtualRefBasePtr.cpp",
+        "core_jni_helpers.cpp",
         ":deviceproductinfoconstants_aidl",
     ],
 
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 361988c..5915808 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -44,6 +44,7 @@
 per-file EphemeralStorage* = file:platform/system/libhwbinder:/OWNERS
 
 per-file *Zygote* = file:/ZYGOTE_OWNERS
+per-file core_jni_helpers.* = file:/ZYGOTE_OWNERS
 per-file fd_utils.* = file:/ZYGOTE_OWNERS
 per-file Android.bp = file:platform/build/soong:/OWNERS
 per-file android_animation_* = file:/core/java/android/animation/OWNERS
diff --git a/core/jni/TEST_MAPPING b/core/jni/TEST_MAPPING
new file mode 100644
index 0000000..004c30e
--- /dev/null
+++ b/core/jni/TEST_MAPPING
@@ -0,0 +1,16 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.util.CharsetUtilsTest"
+        },
+        {
+          "include-filter": "com.android.internal.util.FastDataTest"
+        }
+      ],
+      "file_patterns": ["CharsetUtils|FastData"]
+    }
+  ]
+}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index d0504fb..af0800a 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -332,7 +332,7 @@
     virtual int handleEvent(int fd, int events, void* data) {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
         sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
-        ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
+        ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
 
         ssize_t n;
         ASensorEvent buffer[16];
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 0d530f6..bb4ab39 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -549,10 +549,15 @@
        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/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index ce772cf..c9d8ac0 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -102,7 +102,7 @@
                                                uint32_t count, VsyncEventData vsyncEventData) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
+    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
     if (receiverObj.get()) {
         ALOGV("receiver %p ~ Invoking vsync handler.", this);
         env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
@@ -118,7 +118,7 @@
                                                  bool connected) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
+    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
     if (receiverObj.get()) {
         ALOGV("receiver %p ~ Invoking hotplug handler.", this);
         env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchHotplug,
@@ -133,7 +133,7 @@
                                                      int32_t modeId, nsecs_t) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
+    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
     if (receiverObj.get()) {
         ALOGV("receiver %p ~ Invoking mode changed handler.", this);
         env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchModeChanged,
@@ -148,7 +148,7 @@
         nsecs_t timestamp, PhysicalDisplayId displayId, std::vector<FrameRateOverride> overrides) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
 
-    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
+    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
     if (receiverObj.get()) {
         ALOGV("receiver %p ~ Invoking FrameRateOverride handler.", this);
         const auto frameRateOverrideClass =
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 7d0f60a..9f2fd71 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -328,7 +328,7 @@
             if (!skipCallbacks && !mBatchedInputEventPending && mInputConsumer.hasPendingBatch()) {
                 // There is a pending batch.  Come back later.
                 if (!receiverObj.get()) {
-                    receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
+                    receiverObj.reset(GetReferent(env, mReceiverWeakGlobal));
                     if (!receiverObj.get()) {
                         ALOGW("channel '%s' ~ Receiver object was finalized "
                               "without being disposed.",
@@ -357,7 +357,7 @@
 
         if (!skipCallbacks) {
             if (!receiverObj.get()) {
-                receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
+                receiverObj.reset(GetReferent(env, mReceiverWeakGlobal));
                 if (!receiverObj.get()) {
                     ALOGW("channel '%s' ~ Receiver object was finalized "
                             "without being disposed.", getInputChannelName().c_str());
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 16366a4..7ce54af 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -202,7 +202,7 @@
         ALOGD("channel '%s' ~ Receiving finished signals.", getInputChannelName().c_str());
     }
 
-    ScopedLocalRef<jobject> senderObj(env, jniGetReferent(env, mSenderWeakGlobal));
+    ScopedLocalRef<jobject> senderObj(env, GetReferent(env, mSenderWeakGlobal));
     if (!senderObj.get()) {
         ALOGW("channel '%s' ~ Sender object was finalized without being disposed.",
               getInputChannelName().c_str());
diff --git a/core/jni/android_view_InputQueue.cpp b/core/jni/android_view_InputQueue.cpp
index 70a9be7..244b895 100644
--- a/core/jni/android_view_InputQueue.cpp
+++ b/core/jni/android_view_InputQueue.cpp
@@ -135,7 +135,7 @@
     switch(message.what) {
     case MSG_FINISH_INPUT:
         JNIEnv* env = AndroidRuntime::getJNIEnv();
-        ScopedLocalRef<jobject> inputQueueObj(env, jniGetReferent(env, mInputQueueWeakGlobal));
+        ScopedLocalRef<jobject> inputQueueObj(env, GetReferent(env, mInputQueueWeakGlobal));
         if (!inputQueueObj.get()) {
             ALOGW("InputQueue was finalized without being disposed");
             return;
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index ef6fd7d..be82879 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -36,7 +36,6 @@
 #include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <linux/fs.h>
 
 #include <memory>
 
@@ -254,16 +253,6 @@
         return INSTALL_FAILED_CONTAINER_ERROR;
     }
 
-    // If a filesystem like f2fs supports per-file compression, set the compression bit before data
-    // writes
-    unsigned int flags;
-    if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
-        ALOGE("Failed to call FS_IOC_GETFLAGS on %s: %s\n", localTmpFileName, strerror(errno));
-    } else if ((flags & FS_COMPR_FL) == 0) {
-        flags |= FS_COMPR_FL;
-        ioctl(fd, FS_IOC_SETFLAGS, &flags);
-    }
-
     if (!zipFile->uncompressEntry(zipEntry, fd)) {
         ALOGE("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
         close(fd);
diff --git a/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp b/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp
index 83e2f2b..2279856 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/jni/core_jni_helpers.cpp b/core/jni/core_jni_helpers.cpp
new file mode 100644
index 0000000..b65053b
--- /dev/null
+++ b/core/jni/core_jni_helpers.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+namespace {
+
+jmethodID gGetReferent = nullptr;
+
+} // namespace
+
+jobject GetReferent(JNIEnv* env, jobject ref) {
+    if (gGetReferent == nullptr) {
+        jclass clazz = FindClassOrDie(env, "java/lang/ref/Reference");
+        gGetReferent = GetMethodIDOrDie(env, clazz, "get", "()Ljava/lang/Object;");
+    }
+    return env->CallObjectMethod(ref, gGetReferent);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h
index 5268049..b85a425 100644
--- a/core/jni/core_jni_helpers.h
+++ b/core/jni/core_jni_helpers.h
@@ -90,11 +90,10 @@
     return res;
 }
 
-static inline jobject jniGetReferent(JNIEnv* env, jobject ref) {
-    jclass cls = FindClassOrDie(env, "java/lang/ref/Reference");
-    jmethodID get = GetMethodIDOrDie(env, cls, "get", "()Ljava/lang/Object;");
-    return env->CallObjectMethod(ref, get);
-}
+/**
+ * Returns the result of invoking java.lang.ref.Reference.get() on a Reference object.
+ */
+jobject GetReferent(JNIEnv* env, jobject ref);
 
 /**
  * Read the specified field from jobject, and convert to std::string.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5a5d7e8..02453a4 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 62001d9..7a48342 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 cd7f99f..4ece840 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 5c95721..89797e8 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 dab4f1b..8519ddf 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/core/tests/coretests/src/android/util/XmlTest.java b/core/tests/coretests/src/android/util/XmlTest.java
index 4e10ea9..1cd4d13 100644
--- a/core/tests/coretests/src/android/util/XmlTest.java
+++ b/core/tests/coretests/src/android/util/XmlTest.java
@@ -224,7 +224,7 @@
         doVerifyRead(in);
     }
 
-    private static final String TEST_STRING = "com.example";
+    private static final String TEST_STRING = "com☃example😀typical☃package😀name";
     private static final String TEST_STRING_EMPTY = "";
     private static final byte[] TEST_BYTES = new byte[] { 0, 1, 2, 3, 4, 3, 2, 1, 0 };
     private static final byte[] TEST_BYTES_EMPTY = new byte[0];
diff --git a/core/tests/coretests/src/com/android/internal/util/FastDataTest.java b/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
index 81fb39f..04dfd6e 100644
--- a/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
@@ -23,10 +23,13 @@
 import android.annotation.NonNull;
 import android.util.ExceptionUtils;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
+import libcore.util.HexEncoding;
 
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -38,22 +41,34 @@
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.function.Consumer;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
 public class FastDataTest {
+    private final boolean use4ByteSequence;
+
     private static final String TEST_SHORT_STRING = "a";
-    private static final String TEST_LONG_STRING = "com☃example☃typical☃package☃name";
+    private static final String TEST_LONG_STRING = "com☃example😀typical☃package😀name";
     private static final byte[] TEST_BYTES = TEST_LONG_STRING.getBytes(StandardCharsets.UTF_16LE);
 
+    @Parameters(name = "use4ByteSequence={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {true}, {false} });
+    }
+
+    public FastDataTest(boolean use4ByteSequence) {
+        this.use4ByteSequence = use4ByteSequence;
+    }
+
     @Test
     public void testEndOfFile_Int() throws Exception {
         try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
-                new byte[] { 1 }), 1000)) {
+                new byte[] { 1 }), 1000, use4ByteSequence)) {
             assertThrows(EOFException.class, () -> in.readInt());
         }
         try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
-                new byte[] { 1, 1, 1, 1 }), 1000)) {
+                new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
             assertEquals(1, in.readByte());
             assertThrows(EOFException.class, () -> in.readInt());
         }
@@ -62,11 +77,11 @@
     @Test
     public void testEndOfFile_String() throws Exception {
         try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
-                new byte[] { 1 }), 1000)) {
+                new byte[] { 1 }), 1000, use4ByteSequence)) {
             assertThrows(EOFException.class, () -> in.readUTF());
         }
         try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
-                new byte[] { 1, 1, 1, 1 }), 1000)) {
+                new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
             assertThrows(EOFException.class, () -> in.readUTF());
         }
     }
@@ -74,12 +89,12 @@
     @Test
     public void testEndOfFile_Bytes_Small() throws Exception {
         try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
-                new byte[] { 1, 1, 1, 1 }), 1000)) {
+                new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
             final byte[] tmp = new byte[10];
             assertThrows(EOFException.class, () -> in.readFully(tmp));
         }
         try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
-                new byte[] { 1, 1, 1, 1 }), 1000)) {
+                new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
             final byte[] tmp = new byte[10_000];
             assertThrows(EOFException.class, () -> in.readFully(tmp));
         }
@@ -88,7 +103,8 @@
     @Test
     public void testUTF_Bounds() throws Exception {
         final char[] buf = new char[65_534];
-        try (FastDataOutput out = new FastDataOutput(new ByteArrayOutputStream(), BOUNCE_SIZE)) {
+        try (FastDataOutput out = new FastDataOutput(new ByteArrayOutputStream(),
+                BOUNCE_SIZE, use4ByteSequence)) {
             // Writing simple string will fit fine
             Arrays.fill(buf, '!');
             final String simple = new String(buf);
@@ -100,11 +116,15 @@
             final String complex = new String(buf);
             assertThrows(IOException.class, () -> out.writeUTF(complex));
             assertThrows(IOException.class, () -> out.writeInternedUTF(complex));
+
+            out.flush();
         }
     }
 
     @Test
     public void testTranscode() throws Exception {
+        Assume.assumeFalse(use4ByteSequence);
+
         // Verify that upstream data can be read by fast
         {
             final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
@@ -113,20 +133,22 @@
             out.flush();
 
             final FastDataInput in = new FastDataInput(
-                    new ByteArrayInputStream(outStream.toByteArray()), BOUNCE_SIZE);
-            doTransodeRead(in);
+                    new ByteArrayInputStream(outStream.toByteArray()),
+                    BOUNCE_SIZE, use4ByteSequence);
+            doTranscodeRead(in);
         }
 
         // Verify that fast data can be read by upstream
         {
             final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-            final FastDataOutput out = new FastDataOutput(outStream, BOUNCE_SIZE);
+            final FastDataOutput out = new FastDataOutput(outStream,
+                    BOUNCE_SIZE, use4ByteSequence);
             doTranscodeWrite(out);
             out.flush();
 
             final DataInputStream in = new DataInputStream(
                     new ByteArrayInputStream(outStream.toByteArray()));
-            doTransodeRead(in);
+            doTranscodeRead(in);
         }
     }
 
@@ -144,7 +166,7 @@
         out.writeDouble(32d);
     }
 
-    private static void doTransodeRead(DataInput in) throws IOException {
+    private static void doTranscodeRead(DataInput in) throws IOException {
         assertEquals(true, in.readBoolean());
         assertEquals(false, in.readBoolean());
         assertEquals(1, in.readByte());
@@ -225,10 +247,12 @@
         doBounce((out) -> {
             out.writeUTF("");
             out.writeUTF("☃");
+            out.writeUTF("😀");
             out.writeUTF("example");
         }, (in) -> {
             assertEquals("", in.readUTF());
             assertEquals("☃", in.readUTF());
+            assertEquals("😀", in.readUTF());
             assertEquals("example", in.readUTF());
         });
     }
@@ -263,6 +287,35 @@
         }, 1);
     }
 
+    /**
+     * Verify that we encode every valid code-point identically to RI when
+     * running in 3-byte mode.
+     */
+    @Test
+    public void testBounce_UTF_Exhaustive() throws Exception {
+        Assume.assumeFalse(use4ByteSequence);
+
+        final ByteArrayOutputStream slowStream = new ByteArrayOutputStream();
+        final DataOutput slowData = new DataOutputStream(slowStream);
+
+        final ByteArrayOutputStream fastStream = new ByteArrayOutputStream();
+        final FastDataOutput fastData = FastDataOutput.obtainUsing3ByteSequences(fastStream);
+
+        for (int cp = Character.MIN_CODE_POINT; cp < Character.MAX_CODE_POINT; cp++) {
+            if (Character.isValidCodePoint(cp)) {
+                final String cpString = new String(Character.toChars(cp));
+                slowStream.reset();
+                slowData.writeUTF(cpString);
+                fastStream.reset();
+                fastData.writeUTF(cpString);
+                fastData.flush();
+                assertEquals("Bad encoding for code-point " + Integer.toHexString(cp),
+                        HexEncoding.encodeToString(slowStream.toByteArray()),
+                        HexEncoding.encodeToString(fastStream.toByteArray()));
+            }
+        }
+    }
+
     @Test
     public void testBounce_InternedUTF() throws Exception {
         doBounce((out) -> {
@@ -355,22 +408,24 @@
      * Verify that some common data can be written and read back, effectively
      * "bouncing" it through a serialized representation.
      */
-    private static void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
+    private void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
             @NonNull ThrowingConsumer<FastDataInput> in) throws Exception {
         doBounce(out, in, BOUNCE_REPEAT);
     }
 
-    private static void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
+    private void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
             @NonNull ThrowingConsumer<FastDataInput> in, int count) throws Exception {
         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-        final FastDataOutput outData = new FastDataOutput(outStream, BOUNCE_SIZE);
+        final FastDataOutput outData = new FastDataOutput(outStream,
+                BOUNCE_SIZE, use4ByteSequence);
         for (int i = 0; i < count; i++) {
             out.accept(outData);
         }
         outData.flush();
 
         final ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
-        final FastDataInput inData = new FastDataInput(inStream, BOUNCE_SIZE);
+        final FastDataInput inData = new FastDataInput(inStream,
+                BOUNCE_SIZE, use4ByteSequence);
         for (int i = 0; i < count; i++) {
             in.accept(inData);
         }
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 055e5ad..ad089b6 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -519,7 +519,7 @@
         ARGB_8888   (5),
 
         /**
-         * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
+         * Each pixel is stored on 8 bytes. Each channel (RGB and alpha
          * for translucency) is stored as a
          * {@link android.util.Half half-precision floating point value}.
          *
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index a743d30..ed87990 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -90,11 +90,36 @@
 
     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 @@
      */
 
     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/incident/libincident.map.txt b/libs/incident/libincident.map.txt
index f157763..f75ccea 100644
--- a/libs/incident/libincident.map.txt
+++ b/libs/incident/libincident.map.txt
@@ -1,15 +1,15 @@
 LIBINCIDENT {
     global:
-        AIncidentReportArgs_init; # apex # introduced=30
-        AIncidentReportArgs_clone; # apex # introduced=30
-        AIncidentReportArgs_delete; # apex # introduced=30
-        AIncidentReportArgs_setAll; # apex # introduced=30
-        AIncidentReportArgs_setPrivacyPolicy; # apex # introduced=30
-        AIncidentReportArgs_addSection; # apex # introduced=30
-        AIncidentReportArgs_setReceiverPackage; # apex # introduced=30
-        AIncidentReportArgs_setReceiverClass; # apex # introduced=30
-        AIncidentReportArgs_addHeader; # apex # introduced=30
-        AIncidentReportArgs_takeReport; # apex # introduced=30
+        AIncidentReportArgs_init; # systemapi # introduced=30
+        AIncidentReportArgs_clone; # systemapi # introduced=30
+        AIncidentReportArgs_delete; # systemapi # introduced=30
+        AIncidentReportArgs_setAll; # systemapi # introduced=30
+        AIncidentReportArgs_setPrivacyPolicy; # systemapi # introduced=30
+        AIncidentReportArgs_addSection; # systemapi # introduced=30
+        AIncidentReportArgs_setReceiverPackage; # systemapi # introduced=30
+        AIncidentReportArgs_setReceiverClass; # systemapi # introduced=30
+        AIncidentReportArgs_addHeader; # systemapi # introduced=30
+        AIncidentReportArgs_takeReport; # systemapi # introduced=30
     local:
         *;
 };
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index 132d71e..128be3c 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -55,6 +55,7 @@
 
     export_include_dirs: ["include"],
 
+    min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
         "com.android.os.statsd",
@@ -81,5 +82,5 @@
 
     proto: {
         type: "full",
-    }
+    },
 }
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index b27a00c..c495535 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1200,6 +1200,8 @@
         /**
          * 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 fe7f29e..d2523ef 100644
--- a/media/java/android/media/audiofx/HapticGenerator.java
+++ b/media/java/android/media/audiofx/HapticGenerator.java
@@ -91,7 +91,8 @@
     }
 
     /**
-     * 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/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java
index f6914ef..23d6e34 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java
@@ -22,8 +22,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java
index 096b2da..bfc5d0d 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java
@@ -18,9 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertThrows;
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
index fa4fef5..222b882 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
@@ -19,8 +19,8 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertFalse;
@@ -41,13 +41,6 @@
 import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
 import com.android.server.backup.testing.CryptoTestUtils;
 
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.crypto.SecretKey;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -59,6 +52,14 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.crypto.SecretKey;
+
+
 @RunWith(RobolectricTestRunner.class)
 public class EncryptedKvBackupTaskTest {
     private static final boolean INCREMENTAL = true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 89e10c4..fc70ba4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -20,15 +20,19 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
+import android.os.Build;
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import androidx.annotation.ChecksSdkIntAtLeast;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * CsipDeviceManager manages the set of remote CSIP Bluetooth devices.
@@ -126,32 +130,84 @@
         }
     }
 
+    @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
+    private static boolean isAtLeastT() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
+    }
+
     // Group devices by groupId
     @VisibleForTesting
     void onGroupIdChanged(int groupId) {
-        int firstMatchedIndex = -1;
-        CachedBluetoothDevice mainDevice = null;
+        if (!isValidGroupId(groupId)) {
+            log("onGroupIdChanged: groupId is invalid");
+            return;
+        }
+        log("onGroupIdChanged: mCachedDevices list =" + mCachedDevices.toString());
+        final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+        final CachedBluetoothDeviceManager deviceManager = mBtManager.getCachedDeviceManager();
+        final LeAudioProfile leAudioProfile = profileManager.getLeAudioProfile();
+        final BluetoothDevice mainBluetoothDevice = (leAudioProfile != null && isAtLeastT()) ?
+                leAudioProfile.getConnectedGroupLeadDevice(groupId) : null;
+        CachedBluetoothDevice newMainDevice =
+                mainBluetoothDevice != null ? deviceManager.findDevice(mainBluetoothDevice) : null;
+        if (newMainDevice != null) {
+            final CachedBluetoothDevice finalNewMainDevice = newMainDevice;
+            final List<CachedBluetoothDevice> memberDevices = mCachedDevices.stream()
+                    .filter(cachedDevice -> !cachedDevice.equals(finalNewMainDevice)
+                            && cachedDevice.getGroupId() == groupId)
+                    .collect(Collectors.toList());
+            if (memberDevices == null || memberDevices.isEmpty()) {
+                log("onGroupIdChanged: There is no member device in list.");
+                return;
+            }
+            log("onGroupIdChanged: removed from UI device =" + memberDevices
+                    + ", with groupId=" + groupId + " mainDevice= " + newMainDevice);
+            for (CachedBluetoothDevice memberDeviceItem : memberDevices) {
+                Set<CachedBluetoothDevice> memberSet = memberDeviceItem.getMemberDevice();
+                if (!memberSet.isEmpty()) {
+                    log("onGroupIdChanged: Transfer the member list into new main device.");
+                    for (CachedBluetoothDevice memberListItem : memberSet) {
+                        if (!memberListItem.equals(newMainDevice)) {
+                            newMainDevice.addMemberDevice(memberListItem);
+                        }
+                    }
+                    memberSet.clear();
+                }
 
-        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
-            final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
-            if (cachedDevice.getGroupId() != groupId) {
-                continue;
+                newMainDevice.addMemberDevice(memberDeviceItem);
+                mCachedDevices.remove(memberDeviceItem);
+                mBtManager.getEventManager().dispatchDeviceRemoved(memberDeviceItem);
             }
 
-            if (firstMatchedIndex == -1) {
-                // Found the first one
-                firstMatchedIndex = i;
-                mainDevice = cachedDevice;
-                continue;
+            if (!mCachedDevices.contains(newMainDevice)) {
+                mCachedDevices.add(newMainDevice);
+                mBtManager.getEventManager().dispatchDeviceAdded(newMainDevice);
             }
+        } else {
+            log("onGroupIdChanged: There is no main device from the LE profile.");
+            int firstMatchedIndex = -1;
 
-            log("onGroupIdChanged: removed from UI device =" + cachedDevice
-                    + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+            for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+                final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+                if (cachedDevice.getGroupId() != groupId) {
+                    continue;
+                }
 
-            mainDevice.addMemberDevice(cachedDevice);
-            mCachedDevices.remove(i);
-            mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
-            break;
+                if (firstMatchedIndex == -1) {
+                    // Found the first one
+                    firstMatchedIndex = i;
+                    newMainDevice = cachedDevice;
+                    continue;
+                }
+
+                log("onGroupIdChanged: removed from UI device =" + cachedDevice
+                        + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+
+                newMainDevice.addMemberDevice(cachedDevice);
+                mCachedDevices.remove(i);
+                mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+                break;
+            }
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index c323c4e..b6dcdc3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -21,6 +21,7 @@
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
 
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCodecConfig;
@@ -183,6 +184,37 @@
         return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
     }
 
+    /**
+     * Get Lead device for the group.
+     *
+     * Lead device is the device that can be used as an active device in the system.
+     * Active devices points to the Audio Device for the Le Audio group.
+     * This method returns the Lead devices for the connected LE Audio
+     * group and this device should be used in the setActiveDevice() method by other parts
+     * of the system, which wants to set to active a particular Le Audio group.
+     *
+     * Note: getActiveDevice() returns the Lead device for the currently active LE Audio group.
+     * Note: When Lead device gets disconnected while Le Audio group is active and has more devices
+     * in the group, then Lead device will not change. If Lead device gets disconnected, for the
+     * Le Audio group which is not active, a new Lead device will be chosen
+     *
+     * @param groupId The group id.
+     * @return group lead device.
+     *
+     * @hide
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public @Nullable BluetoothDevice getConnectedGroupLeadDevice(int groupId) {
+        if (DEBUG) {
+            Log.d(TAG,"getConnectedGroupLeadDevice");
+        }
+        if (mService == null) {
+            Log.e(TAG,"No service.");
+            return null;
+        }
+        return mService.getConnectedGroupLeadDevice(groupId);
+    }
+
     @Override
     public boolean isEnabled(BluetoothDevice device) {
         if (mService == null || device == null) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
index 5efce4d..30bbc2a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
@@ -21,9 +21,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index 95f7ef4..508dffc 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
index d6c8816..c190d07 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
@@ -22,7 +22,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
@@ -141,7 +141,7 @@
         dialog.show();
         dialog.cancel();
 
-        verifyZeroInteractions(successCallback);
+        verifyNoInteractions(successCallback);
         verify(cancelCallback, times(1))
                 .run();
     }
@@ -157,7 +157,7 @@
         dialog.show();
         dialog.getButton(Dialog.BUTTON_NEGATIVE).performClick();
 
-        verifyZeroInteractions(successCallback);
+        verifyNoInteractions(successCallback);
         verify(cancelCallback, times(1))
                 .run();
     }
@@ -178,7 +178,7 @@
 
         verify(successCallback, times(1))
                 .accept("test", oldUserIcon);
-        verifyZeroInteractions(cancelCallback);
+        verifyNoInteractions(cancelCallback);
     }
 
     @Test
@@ -196,7 +196,7 @@
 
         verify(successCallback, times(1))
                 .accept("test", null);
-        verifyZeroInteractions(cancelCallback);
+        verifyNoInteractions(cancelCallback);
     }
 
     @Test
@@ -217,7 +217,7 @@
 
         verify(successCallback, times(1))
                 .accept(expectedNewName, mCurrentIcon);
-        verifyZeroInteractions(cancelCallback);
+        verifyNoInteractions(cancelCallback);
     }
 
     @Test
@@ -236,7 +236,7 @@
 
         verify(successCallback, times(1))
                 .accept("test", newPhoto);
-        verifyZeroInteractions(cancelCallback);
+        verifyNoInteractions(cancelCallback);
     }
 
     @Test
@@ -255,7 +255,7 @@
 
         verify(successCallback, times(1))
                 .accept("test", newPhoto);
-        verifyZeroInteractions(cancelCallback);
+        verifyNoInteractions(cancelCallback);
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
index 0b3495d..ca0aa0d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
@@ -56,7 +56,7 @@
 
         mUpdatableListPrefDlgFragment = spy(UpdatableListPreferenceDialogFragment
                 .newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES));
-        mEntries = spy(new ArrayList<>());
+        mEntries = new ArrayList<>();
         mUpdatableListPrefDlgFragment.setEntries(mEntries);
         mUpdatableListPrefDlgFragment
                 .setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
diff --git a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
index 0ec8ed3..acb54f6 100644
--- a/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
+++ b/packages/StatementService/src/com/android/statementservice/domain/DomainVerificationReceiverV1.kt
@@ -67,6 +67,10 @@
             }
         }
 
+        //clear sp before enqueue unique work since policy is REPLACE
+        val deContext = context.createDeviceProtectedStorageContext()
+        val editor = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)?.edit()
+        editor?.clear()?.apply()
         WorkManager.getInstance(context)
             .beginUniqueWork(
                 "$PACKAGE_WORK_PREFIX_V1$packageName",
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
index 3a3aea9..36c81722 100644
--- a/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/CollectV1Worker.kt
@@ -41,9 +41,7 @@
                     Data.Builder()
                         .putInt(VERIFICATION_ID_KEY, verificationId)
                         .apply {
-                            if (DEBUG) {
-                                putString(PACKAGE_NAME_KEY, packageName)
-                            }
+                            putString(PACKAGE_NAME_KEY, packageName)
                         }
                         .build()
                 )
@@ -52,6 +50,18 @@
 
     override suspend fun doWork() = coroutineScope {
         if (!AndroidUtils.isReceiverV1Enabled(appContext)) {
+            //clear sp and commit here
+            val inputData = params.inputData
+            val packageName = inputData.getString(PACKAGE_NAME_KEY)
+            val deContext = appContext.createDeviceProtectedStorageContext()
+            val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+            val editor = sp?.edit()
+            editor?.clear()?.commit()
+            //delete sp file
+            val retOfDel = deContext?.deleteSharedPreferences(packageName)
+            if (DEBUG) {
+                Log.d(TAG, "delete sp for $packageName return $retOfDel")
+            }
             return@coroutineScope Result.success()
         }
 
@@ -59,7 +69,10 @@
         val verificationId = inputData.getInt(VERIFICATION_ID_KEY, -1)
         val successfulHosts = mutableListOf<String>()
         val failedHosts = mutableListOf<String>()
-        inputData.keyValueMap.entries.forEach { (key, _) ->
+        val packageName = inputData.getString(PACKAGE_NAME_KEY)
+        val deContext = appContext.createDeviceProtectedStorageContext()
+        val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+        sp?.all?.entries?.forEach { (key, _) ->
             when {
                 key.startsWith(SingleV1RequestWorker.HOST_SUCCESS_PREFIX) ->
                     successfulHosts += key.removePrefix(SingleV1RequestWorker.HOST_SUCCESS_PREFIX)
@@ -69,7 +82,6 @@
         }
 
         if (DEBUG) {
-            val packageName = inputData.getString(PACKAGE_NAME_KEY)
             Log.d(
                 TAG, "Domain verification v1 request for $packageName: " +
                         "success = $successfulHosts, failed = $failedHosts"
@@ -84,6 +96,15 @@
 
         appContext.packageManager.verifyIntentFilter(verificationId, resultCode, failedHosts)
 
+        //clear sp and commit here
+        val editor = sp?.edit()
+        editor?.clear()?.commit()
+        //delete sp file
+        val retOfDel = deContext?.deleteSharedPreferences(packageName)
+        if (DEBUG) {
+            Log.d(TAG, "delete sp for $packageName return $retOfDel")
+        }
+
         Result.success()
     }
 }
diff --git a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
index cd8a182..7a198cb 100644
--- a/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
+++ b/packages/StatementService/src/com/android/statementservice/domain/worker/SingleV1RequestWorker.kt
@@ -71,16 +71,18 @@
 
         // Coerce failure results into success so that final collection task gets a chance to run
         when (result) {
-            is Result.Success -> Result.success(
-                Data.Builder()
-                    .putInt("$HOST_SUCCESS_PREFIX$host", status.value)
-                    .build()
-            )
-            is Result.Failure -> Result.success(
-                Data.Builder()
-                    .putInt("$HOST_FAILURE_PREFIX$host", status.value)
-                    .build()
-            )
+            is Result.Success -> {
+                val deContext = appContext.createDeviceProtectedStorageContext()
+                val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+                sp?.edit()?.putInt("$HOST_SUCCESS_PREFIX$host", status.value)?.apply()
+                Result.success()
+            }
+            is Result.Failure -> {
+                val deContext = appContext.createDeviceProtectedStorageContext()
+                val sp = deContext?.getSharedPreferences(packageName, Context.MODE_PRIVATE)
+                sp?.edit()?.putInt("$HOST_FAILURE_PREFIX$host", status.value)?.apply()
+                Result.success()
+            }
             else -> result
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index a617850..f8f784f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -112,7 +112,7 @@
                                     if (DEBUG) Log.d(mTag, "requesting AudioFocus");
                                     int focusGain = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
                                     if (mCmd.looping) {
-                                        focusGain = AudioManager.AUDIOFOCUS_GAIN;
+                                        focusGain = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT;
                                     }
                                     mNotificationRampTimeMs = audioManager.getFocusRampTimeMs(
                                             focusGain, mCmd.attributes);
diff --git a/rs/OWNERS b/rs/OWNERS
index 61853d3..fd03660 100644
--- a/rs/OWNERS
+++ b/rs/OWNERS
@@ -1,5 +1,2 @@
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-miaowang@google.com
-yangni@google.com
+# Bug component: 43047
+include platform/frameworks/rs:/RS_OWNERS  # RenderScript team
diff --git a/services/accessibility/OWNERS b/services/accessibility/OWNERS
index a31cfae..2b9f179 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 7cbe218..0f67033 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.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,10 @@
     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;
+    // Target dirty segment ratio to aim to
+    private static final int DEFAULT_TARGET_DIRTY_RATIO = 80;
 
     private volatile int mLifetimePercentThreshold;
     private volatile int mMinSegmentsThreshold;
@@ -361,6 +366,8 @@
     private volatile float mSegmentReclaimWeight;
     private volatile float mLowBatteryLevel;
     private volatile boolean mChargingRequired;
+    private volatile int mMinGCSleepTime;
+    private volatile int mTargetDirtyRatio;
     private volatile boolean mNeedGC;
 
     private volatile boolean mPassedLifetimeThresh;
@@ -2611,6 +2618,10 @@
                 "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);
+            mTargetDirtyRatio = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "target_dirty_ratio", DEFAULT_TARGET_DIRTY_RATIO);
 
             // If we use the smart idle maintenance, we need to turn off GC in the traditional idle
             // maintenance to avoid the conflict
@@ -2728,6 +2739,14 @@
         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 +2754,6 @@
                     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 +2761,12 @@
                             ", min segment threshold: " + mMinSegmentsThreshold +
                             ", dirty reclaim rate: " + mDirtyReclaimRate +
                             ", segment reclaim weight: " + mSegmentReclaimWeight +
-                            ", period: " + sSmartIdleMaintPeriod);
+                            ", period(min): " + sSmartIdleMaintPeriod +
+                            ", min gc sleep time(ms): " + mMinGCSleepTime +
+                            ", target dirty ratio: " + mTargetDirtyRatio);
                 mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
-                                      mSegmentReclaimWeight, sSmartIdleMaintPeriod);
+                                      mSegmentReclaimWeight, sSmartIdleMaintPeriod,
+                                      mMinGCSleepTime, mTargetDirtyRatio);
             } else {
                 Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
             }
@@ -3274,11 +3289,21 @@
                     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 724d17b..c751e1ed 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2357,9 +2357,8 @@
             return;
         }
 
-        if (VDBG) {
-            log("notifyActiveDataSubIdChanged: activeDataSubId=" + activeDataSubId);
-        }
+        log("notifyActiveDataSubIdChanged: activeDataSubId=" + activeDataSubId);
+        mLocalLog.log("notifyActiveDataSubIdChanged: activeDataSubId=" + activeDataSubId);
 
         mActiveDataSubId = activeDataSubId;
         synchronized (mRecords) {
@@ -3065,42 +3064,88 @@
             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 d3ef6be..c9a420e 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.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 @@
             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 @@
 
         // 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 @@
                 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 @@
                 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 @@
         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 683b730..09b601c 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 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 @@
         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 @@
                             | 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 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 @@
                     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 @@
             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 @@
             @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 @@
             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 @@
             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 @@
             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 @@
                 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 @@
             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 @@
                     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 @@
                         | 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 @@
                             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 @@
                     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 @@
                 }
 
                 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 ea28117..827c5c4 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.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 @@
     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 @@
         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 @@
                     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 @@
                 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 @@
         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 2da4107..6daf709 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.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 @@
                 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 @@
             }
         }
 
+        // 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 8015596..84a9482 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 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 @@
             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 @@
             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 @@
         resolvedType = _resolvedType;
         requiredPermissions = _requiredPermissions;
         excludedPermissions = _excludedPermissions;
+        excludedPackages = _excludedPackages;
         appOp = _appOp;
         options = _options;
         receivers = _receivers;
@@ -306,6 +313,7 @@
         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 @@
         // 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 7562098..35f91ba 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 @@
                 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 c465be1..6f7dab9 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 @@
             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 4d025c9..28a9191 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 @@
                     null /* resultExtras */,
                     requiredPermissions,
                     null /* excludedPermissions */,
+                    null /* excludedPackages */,
                     OP_NONE,
                     null /* bOptions */,
                     false /* serialized */,
@@ -441,6 +442,7 @@
                     null /* resultExtras */,
                     requiredPermissions,
                     null /* excludedPermissions */,
+                    null /* excludedPackages */,
                     OP_NONE,
                     null /* bOptions */,
                     false /* serialized */,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 6ce7b1a..e03f3c11 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -642,6 +642,9 @@
                     audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET;
                 }
                 break;
+            case BluetoothProfile.LE_AUDIO_BROADCAST:
+                audioDevice = AudioSystem.DEVICE_OUT_BLE_BROADCAST;
+                break;
             default: throw new IllegalArgumentException("Invalid profile " + d.mInfo.getProfile());
         }
         return new BtDeviceInfo(d, device, state, audioDevice, codec);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index a3c6f0a..282714a 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -363,6 +363,7 @@
                     }
                     break;
                 case BluetoothProfile.LE_AUDIO:
+                case BluetoothProfile.LE_AUDIO_BROADCAST:
                     if (switchToUnavailable) {
                         makeLeAudioDeviceUnavailable(address, btInfo.mAudioSystemDevice);
                     } else if (switchToAvailable) {
@@ -814,7 +815,10 @@
                 disconnectHearingAid();
                 break;
             case BluetoothProfile.LE_AUDIO:
-                disconnectLeAudio();
+                disconnectLeAudioUnicast();
+                break;
+            case BluetoothProfile.LE_AUDIO_BROADCAST:
+                disconnectLeAudioBroadcast();
                 break;
             default:
                 // Not a valid profile to disconnect
@@ -824,28 +828,39 @@
         }
     }
 
-     /*package*/ void disconnectLeAudio() {
+     /*package*/ void disconnectLeAudio(int device) {
+        if (device != AudioSystem.DEVICE_OUT_BLE_HEADSET ||
+                    device != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
+            Log.e(TAG, "disconnectLeAudio: Can't disconnect not LE Audio device " + device);
+            return;
+        }
+
         synchronized (mDevicesLock) {
             final ArraySet<String> toRemove = new ArraySet<>();
-            // Disconnect ALL DEVICE_OUT_BLE_HEADSET devices
+            // Disconnect ALL DEVICE_OUT_BLE_HEADSET or DEVICE_OUT_BLE_BROADCAST devices
             mConnectedDevices.values().forEach(deviceInfo -> {
-                if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+                if (deviceInfo.mDeviceType == device) {
                     toRemove.add(deviceInfo.mDeviceAddress);
                 }
             });
             new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
                     .record();
             if (toRemove.size() > 0) {
-                final int delay = checkSendBecomingNoisyIntentInt(
-                        AudioSystem.DEVICE_OUT_BLE_HEADSET, 0, AudioSystem.DEVICE_NONE);
                 toRemove.stream().forEach(deviceAddress ->
-                        makeLeAudioDeviceUnavailable(deviceAddress,
-                            AudioSystem.DEVICE_OUT_BLE_HEADSET)
+                        makeLeAudioDeviceUnavailable(deviceAddress, device)
                 );
             }
         }
     }
 
+    /*package*/ void disconnectLeAudioUnicast() {
+        disconnectLeAudio(AudioSystem.DEVICE_OUT_BLE_HEADSET);
+    }
+
+    /*package*/ void disconnectLeAudioBroadcast() {
+        disconnectLeAudio(AudioSystem.DEVICE_OUT_BLE_BROADCAST);
+    }
+
     // must be called before removing the device from mConnectedDevices
     // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
     // from AudioSystem
@@ -875,7 +890,9 @@
         int delay;
         synchronized (mDevicesLock) {
             if (!info.mSupprNoisy
-                    && ((info.mProfile == BluetoothProfile.LE_AUDIO && info.mIsLeOutput)
+                    && (((info.mProfile == BluetoothProfile.LE_AUDIO
+                        || info.mProfile == BluetoothProfile.LE_AUDIO_BROADCAST)
+                        && info.mIsLeOutput)
                         || info.mProfile == BluetoothProfile.HEARING_AID
                         || info.mProfile == BluetoothProfile.A2DP)) {
                 @AudioService.ConnectionState int asState =
@@ -1110,8 +1127,7 @@
             return;
         }
 
-        final int leAudioVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType,
-                                    AudioSystem.DEVICE_OUT_BLE_HEADSET);
+        final int leAudioVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType, device);
         final int maxIndex = mDeviceBroker.getMaxVssVolumeForStream(streamType);
         mDeviceBroker.postSetLeAudioVolumeIndex(leAudioVolIndex, maxIndex, streamType);
         mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
@@ -1163,6 +1179,7 @@
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_LINE);
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_BLE_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_BLE_BROADCAST);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 1cc0443..490f844 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2998,7 +2998,8 @@
                 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
             }
 
-            if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+            if ((device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+                    || device == AudioSystem.DEVICE_OUT_BLE_BROADCAST)
                     && streamType == getBluetoothContextualVolumeStream()
                     && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
@@ -3644,7 +3645,8 @@
                 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
             }
 
-            if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+            if ((device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+                    || device == AudioSystem.DEVICE_OUT_BLE_BROADCAST)
                     && streamType == getBluetoothContextualVolumeStream()
                     && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
@@ -6336,6 +6338,7 @@
             BluetoothProfile.A2DP,
             BluetoothProfile.A2DP_SINK,
             BluetoothProfile.LE_AUDIO,
+            BluetoothProfile.LE_AUDIO_BROADCAST,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BtProfile {}
@@ -6357,6 +6360,7 @@
         final int profile = info.getProfile();
         if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK
                 && profile != BluetoothProfile.LE_AUDIO
+                && profile != BluetoothProfile.LE_AUDIO_BROADCAST
                 && profile != BluetoothProfile.HEARING_AID) {
             throw new IllegalArgumentException("Illegal BluetoothProfile profile for device "
                     + previousDevice + " -> " + newDevice + ". Got: " + profile);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 5b282ce..774fe5b 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 @@
     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.
@@ -1095,7 +1095,7 @@
         // Except for Settings and VpnDialogs, the caller should be matched one of oldPackage or
         // newPackage. Otherwise, non VPN owner might get the VPN always-on status of the VPN owner.
         // See b/191382886.
-        if (mContext.checkCallingOrSelfPermission(CONTROL_VPN) != PERMISSION_GRANTED) {
+        if (!hasControlVpnPermission()) {
             if (oldPackage != null) {
                 verifyCallingUidAndPackage(oldPackage);
             }
@@ -1182,20 +1182,9 @@
                 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();
             }
@@ -2056,6 +2045,10 @@
                 "Unauthorized Caller");
     }
 
+    private boolean hasControlVpnPermission() {
+        return mContext.checkCallingOrSelfPermission(CONTROL_VPN) == PERMISSION_GRANTED;
+    }
+
     private class Connection implements ServiceConnection {
         private IBinder mService;
 
@@ -3348,7 +3341,7 @@
 
                 // TODO(b/230548427): Remove SDK check once VPN related stuff are
                 //  decoupled from ConnectivityServiceTest.
-                if (SdkLevel.isAtLeastT() && category != null) {
+                if (SdkLevel.isAtLeastT() && category != null && isVpnApp(mPackage)) {
                     sendEventToVpnManagerApp(category, errorClass, errorCode,
                             getPackage(), mSessionKey, makeVpnProfileStateLocked(),
                             mActiveNetwork,
@@ -3857,8 +3850,10 @@
             Binder.restoreCallingIdentity(token);
         }
 
-        // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop.
-        // This mirrors the prepareAndAuthorize that is used by VpnService.
+        // If package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop.
+        if (hasControlVpnPermission()) {
+            setPackageAuthorization(packageName, VpnManager.TYPE_VPN_PLATFORM);
+        }
 
         // Return whether the app is already pre-consented
         return isVpnProfilePreConsented(mContext, packageName);
@@ -4043,7 +4038,25 @@
         // 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 +4098,20 @@
             @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 +4124,6 @@
                 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 a592192..59fae9e 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 @@
     }
 
     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 426f002..7302f6e 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/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 601a572..4631570 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -116,9 +116,9 @@
     // 256-bit synthetic password
     private static final byte SYNTHETIC_PASSWORD_LENGTH = 256 / 8;
 
-    private static final int PASSWORD_SCRYPT_N = 11;
-    private static final int PASSWORD_SCRYPT_R = 3;
-    private static final int PASSWORD_SCRYPT_P = 1;
+    private static final int PASSWORD_SCRYPT_LOG_N = 11;
+    private static final int PASSWORD_SCRYPT_LOG_R = 3;
+    private static final int PASSWORD_SCRYPT_LOG_P = 1;
     private static final int PASSWORD_SALT_LENGTH = 16;
     private static final int PASSWORD_TOKEN_LENGTH = 32;
     private static final String TAG = "SyntheticPasswordManager";
@@ -186,7 +186,11 @@
             mVersion = version;
         }
 
-        private byte[] derivePassword(byte[] personalization) {
+        /**
+         * Derives a subkey from the synthetic password. For v3 and later synthetic passwords the
+         * subkeys are 256-bit; for v1 and v2 they are 512-bit.
+         */
+        private byte[] deriveSubkey(byte[] personalization) {
             if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) {
                 return (new SP800Derive(mSyntheticPassword))
                     .withContext(personalization, PERSONALISATION_CONTEXT);
@@ -197,28 +201,28 @@
         }
 
         public byte[] deriveKeyStorePassword() {
-            return bytesToHex(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD));
+            return bytesToHex(deriveSubkey(PERSONALIZATION_KEY_STORE_PASSWORD));
         }
 
         public byte[] deriveGkPassword() {
-            return derivePassword(PERSONALIZATION_SP_GK_AUTH);
+            return deriveSubkey(PERSONALIZATION_SP_GK_AUTH);
         }
 
         public byte[] deriveDiskEncryptionKey() {
-            return derivePassword(PERSONALIZATION_FBE_KEY);
+            return deriveSubkey(PERSONALIZATION_FBE_KEY);
         }
 
         public byte[] deriveVendorAuthSecret() {
-            return derivePassword(PERSONALIZATION_AUTHSECRET_KEY);
+            return deriveSubkey(PERSONALIZATION_AUTHSECRET_KEY);
         }
 
         public byte[] derivePasswordHashFactor() {
-            return derivePassword(PERSONALIZATION_PASSWORD_HASH);
+            return deriveSubkey(PERSONALIZATION_PASSWORD_HASH);
         }
 
         /** Derives key used to encrypt password metrics */
         public byte[] deriveMetricsKey() {
-            return derivePassword(PERSONALIZATION_PASSWORD_METRICS);
+            return deriveSubkey(PERSONALIZATION_PASSWORD_METRICS);
         }
 
         /**
@@ -268,9 +272,8 @@
          * AuthenticationToken.mSyntheticPassword for details on what each block means.
          */
         private void recreate(byte[] escrowSplit0, byte[] escrowSplit1) {
-            mSyntheticPassword = String.valueOf(HexEncoding.encode(
-                    SyntheticPasswordCrypto.personalisedHash(
-                            PERSONALIZATION_SP_SPLIT, escrowSplit0, escrowSplit1))).getBytes();
+            mSyntheticPassword = bytesToHex(SyntheticPasswordCrypto.personalisedHash(
+                    PERSONALIZATION_SP_SPLIT, escrowSplit0, escrowSplit1));
         }
 
         /**
@@ -304,9 +307,9 @@
     }
 
     static class PasswordData {
-        byte scryptN;
-        byte scryptR;
-        byte scryptP;
+        byte scryptLogN;
+        byte scryptLogR;
+        byte scryptLogP;
         public int credentialType;
         byte[] salt;
         // For GateKeeper-based credential, this is the password handle returned by GK,
@@ -315,9 +318,9 @@
 
         public static PasswordData create(int passwordType) {
             PasswordData result = new PasswordData();
-            result.scryptN = PASSWORD_SCRYPT_N;
-            result.scryptR = PASSWORD_SCRYPT_R;
-            result.scryptP = PASSWORD_SCRYPT_P;
+            result.scryptLogN = PASSWORD_SCRYPT_LOG_N;
+            result.scryptLogR = PASSWORD_SCRYPT_LOG_R;
+            result.scryptLogP = PASSWORD_SCRYPT_LOG_P;
             result.credentialType = passwordType;
             result.salt = secureRandom(PASSWORD_SALT_LENGTH);
             return result;
@@ -329,9 +332,9 @@
             buffer.put(data, 0, data.length);
             buffer.flip();
             result.credentialType = buffer.getInt();
-            result.scryptN = buffer.get();
-            result.scryptR = buffer.get();
-            result.scryptP = buffer.get();
+            result.scryptLogN = buffer.get();
+            result.scryptLogR = buffer.get();
+            result.scryptLogP = buffer.get();
             int saltLen = buffer.getInt();
             result.salt = new byte[saltLen];
             buffer.get(result.salt);
@@ -351,9 +354,9 @@
                     + Integer.BYTES + salt.length + Integer.BYTES +
                     (passwordHandle != null ? passwordHandle.length : 0));
             buffer.putInt(credentialType);
-            buffer.put(scryptN);
-            buffer.put(scryptR);
-            buffer.put(scryptP);
+            buffer.put(scryptLogN);
+            buffer.put(scryptLogR);
+            buffer.put(scryptLogP);
             buffer.putInt(salt.length);
             buffer.put(salt);
             if (passwordHandle != null && passwordHandle.length > 0) {
@@ -1369,8 +1372,8 @@
 
     private byte[] computePasswordToken(LockscreenCredential credential, PasswordData data) {
         final byte[] password = credential.isNone() ? DEFAULT_PASSWORD : credential.getCredential();
-        return scrypt(password, data.salt, 1 << data.scryptN, 1 << data.scryptR, 1 << data.scryptP,
-                PASSWORD_TOKEN_LENGTH);
+        return scrypt(password, data.salt, 1 << data.scryptLogN, 1 << data.scryptLogR,
+                1 << data.scryptLogP, PASSWORD_TOKEN_LENGTH);
     }
 
     private byte[] passwordTokenToGkInput(byte[] token) {
@@ -1411,18 +1414,9 @@
         return result;
     }
 
-    protected static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes();
-    private static byte[] bytesToHex(byte[] bytes) {
-        if (bytes == null) {
-            return "null".getBytes();
-        }
-        byte[] hexBytes = new byte[bytes.length * 2];
-        for ( int j = 0; j < bytes.length; j++ ) {
-            int v = bytes[j] & 0xFF;
-            hexBytes[j * 2] = HEX_ARRAY[v >>> 4];
-            hexBytes[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
-        }
-        return hexBytes;
+    @VisibleForTesting
+    static byte[] bytesToHex(byte[] bytes) {
+        return HexEncoding.encodeToString(bytes).getBytes();
     }
 
     /**
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 3858d7a..5d80a8f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -4049,6 +4049,14 @@
                 }
                 fout.decreaseIndent();
 
+                fout.println("Network to interfaces:");
+                fout.increaseIndent();
+                for (int i = 0; i < mNetworkToIfaces.size(); ++i) {
+                    final int key = mNetworkToIfaces.keyAt(i);
+                    fout.println(key + ": " + mNetworkToIfaces.get(key));
+                }
+                fout.decreaseIndent();
+
                 fout.println();
                 mStatLogger.dump(fout);
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 39d501b..d162ce2 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 @@
             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 @@
                     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 @@
             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 @@
             };
             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 1ca7bcd..479701e 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 @@
                     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 eb2de60..0e6d5e5 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 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 374a5c2..af3dafc 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 @@
     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 @@
 
         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 @@
             return mLastRequestQuietModeEnabledMillis;
         }
 
+        boolean getIgnorePrepareStorageErrors() {
+            return mIgnorePrepareStorageErrors;
+        }
+
+        void setIgnorePrepareStorageErrors() {
+            mIgnorePrepareStorageErrors = true;
+        }
+
         void clearSeedAccountData() {
             seedAccountName = null;
             seedAccountType = null;
@@ -3180,6 +3198,10 @@
             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 @@
         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 @@
                     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 @@
         userData.persistSeedData = persistSeedData;
         userData.seedAccountOptions = seedAccountOptions;
         userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp);
+        if (ignorePrepareStorageErrors) {
+            userData.setIgnorePrepareStorageErrors();
+        }
 
         synchronized (mRestrictionsLock) {
             if (baseRestrictions != null) {
@@ -5238,6 +5269,9 @@
                             pw.println();
                         }
                     }
+
+                    pw.println("    Ignore errors preparing storage: "
+                            + userData.getIgnorePrepareStorageErrors());
                 }
             }
 
@@ -5727,6 +5761,14 @@
             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/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 290f4ae..336c27d 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -5689,16 +5689,21 @@
                     appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
                             resolvedAttributionSource, skipCurrentFinish);
                 }
-
-                if (next == null || next.getNext() == null) {
-                    return;
-                }
-
                 RegisteredAttribution registered =
                         sRunningAttributionSources.remove(current.getToken());
                 if (registered != null) {
                     registered.unregister();
                 }
+
+                if (next == null || next.getNext() == null) {
+                    if (next != null) {
+                        registered = sRunningAttributionSources.remove(next.getToken());
+                        if (registered != null) {
+                            registered.unregister();
+                        }
+                    }
+                    return;
+                }
                 current = next;
             }
         }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b184d5c..42c6dd43 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 @@
      */
     @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 5124841..10ae152 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 @@
                 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 eeac230..027f3ae 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 @@
     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 @@
                 mPendingAnimations.size());
         mHandler.removeCallbacks(mTimeoutRunnable);
         synchronized (mService.mGlobalLock) {
+            mIsFinishing = true;
             unlinkToDeathOfRunner();
             releaseFinishedCallback();
             mService.openSurfaceTransaction();
@@ -290,6 +292,7 @@
                 throw e;
             } finally {
                 mService.closeSurfaceTransaction("RemoteAnimationController#finished");
+                mIsFinishing = false;
             }
         }
         setRunningRemoteAnimation(false);
@@ -501,6 +504,9 @@
 
         @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 2d4aef6..66d0230 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.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 @@
         }
         // 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 e815a0e..92a538c 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 @@
     @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 b8ceb4a..24a745b 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.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 @@
         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 @@
         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 c6b15c1..6bf6349 100644
--- a/services/net/java/android/net/ConnectivityModuleConnector.java
+++ b/services/net/java/android/net/ConnectivityModuleConnector.java
@@ -25,7 +25,6 @@
 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.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 @@
     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 @@
     }
 
     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 865e3b8..b7eb5cd 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -25,19 +25,18 @@
 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 @@
     @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 @@
     }
 
     /**
-     * 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 @@
 
         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/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 7d17109..edcf357 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -43,23 +43,23 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.intThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.argThat;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.intThat;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 import static org.robolectric.shadow.api.Shadow.extract;
@@ -2185,7 +2185,7 @@
         task.waitCancel();
         reset(transportMock.transport);
         taskFinished.block();
-        verifyZeroInteractions(transportMock.transport);
+        verifyNoInteractions(transportMock.transport);
     }
 
     @Test
diff --git a/services/smartspace/OWNERS b/services/smartspace/OWNERS
index 19ef9d7..4d9a633 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 e9b5b62..f44104e 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 @@
                 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 1c49e6e..70853b6 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 @@
         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/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index c0a38b8..09d3b48 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -461,18 +461,18 @@
     @Test
     public void testPasswordData_serializeDeserialize() {
         PasswordData data = new PasswordData();
-        data.scryptN = 11;
-        data.scryptR = 22;
-        data.scryptP = 33;
+        data.scryptLogN = 11;
+        data.scryptLogR = 22;
+        data.scryptLogP = 33;
         data.credentialType = CREDENTIAL_TYPE_PASSWORD;
         data.salt = PAYLOAD;
         data.passwordHandle = PAYLOAD2;
 
         PasswordData deserialized = PasswordData.fromBytes(data.toBytes());
 
-        assertEquals(11, deserialized.scryptN);
-        assertEquals(22, deserialized.scryptR);
-        assertEquals(33, deserialized.scryptP);
+        assertEquals(11, deserialized.scryptLogN);
+        assertEquals(22, deserialized.scryptLogR);
+        assertEquals(33, deserialized.scryptLogP);
         assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.credentialType);
         assertArrayEquals(PAYLOAD, deserialized.salt);
         assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
@@ -484,9 +484,9 @@
         // wire format.
         byte[] serialized = new byte[] {
                 0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD_OR_PIN */
-                11, /* scryptN */
-                22, /* scryptR */
-                33, /* scryptP */
+                11, /* scryptLogN */
+                22, /* scryptLogR */
+                33, /* scryptLogP */
                 0, 0, 0, 5, /* salt.length */
                 1, 2, -1, -2, 55, /* salt */
                 0, 0, 0, 6, /* passwordHandle.length */
@@ -494,9 +494,9 @@
         };
         PasswordData deserialized = PasswordData.fromBytes(serialized);
 
-        assertEquals(11, deserialized.scryptN);
-        assertEquals(22, deserialized.scryptR);
-        assertEquals(33, deserialized.scryptP);
+        assertEquals(11, deserialized.scryptLogN);
+        assertEquals(22, deserialized.scryptLogR);
+        assertEquals(33, deserialized.scryptLogP);
         assertEquals(CREDENTIAL_TYPE_PASSWORD_OR_PIN, deserialized.credentialType);
         assertArrayEquals(PAYLOAD, deserialized.salt);
         assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
@@ -567,6 +567,13 @@
         }
     }
 
+    @Test
+    public void testHexEncodingIsUppercase() {
+        final byte[] raw = new byte[] { (byte)0xAB, (byte)0xCD, (byte)0xEF };
+        final byte[] expected = new byte[] { 'A', 'B', 'C', 'D', 'E', 'F' };
+        assertArrayEquals(expected, SyntheticPasswordManager.bytesToHex(raw));
+    }
+
     // b/62213311
     //TODO: add non-migration work profile case, and unify/un-unify transition.
     //TODO: test token after user resets password
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 32cee44..0d9c923 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 @@
             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 @@
 
         // 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 9c0c213c..f3c1ec5 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 @@
         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 3714d99..b78675d 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 void packageFromDeviceConfigIgnored() {
         setExceptionListAndWaitForCallback("com.test.nosplashscreen1,com.test.nosplashscreen2");
 
-        assertIsException("com.test.nosplashscreen1", null);
-        assertIsException("com.test.nosplashscreen2", 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);
 
-        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, 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 @@
         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 @@
                 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 168c250..159d482 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 @@
     }
 
     @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 @@
     }
 
     @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 @@
     }
 
     @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 @@
         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 03b8188..7d50135 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 @@
 
     @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 af1d56a..610190e 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 @@
     // 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 @@
             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 @@
             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 85d59a2..d4b6c91 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -316,9 +316,11 @@
             return LocationPermissionResult.ALLOWED;
         }
 
-        // Check the system-wide requirements. If the location main switch is off or
-        // the app's profile isn't in foreground, return a soft denial.
-        if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid)) {
+        // Check the system-wide requirements. If the location main switch is off and the caller is
+        // not in the allowlist of apps that always have loation access or the app's profile
+        // isn't in the foreground, return a soft denial.
+        if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid,
+                query.callingPackage)) {
             return LocationPermissionResult.DENIED_SOFT;
         }
 
@@ -344,15 +346,16 @@
         return LocationPermissionResult.ALLOWED;
     }
 
-
     private static boolean checkManifestPermission(Context context, int pid, int uid,
             String permissionToCheck) {
         return context.checkPermission(permissionToCheck, pid, uid)
                 == PackageManager.PERMISSION_GRANTED;
     }
 
-    private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid) {
-        if (!isLocationModeEnabled(context, UserHandle.getUserHandleForUid(uid).getIdentifier())) {
+    private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid,
+            @NonNull String callingPackage) {
+        if (!isLocationModeEnabled(context, UserHandle.getUserHandleForUid(uid).getIdentifier())
+                && !isLocationBypassAllowed(context, callingPackage)) {
             if (DBG) Log.w(TAG, "Location disabled, failed, (" + uid + ")");
             return false;
         }
@@ -361,7 +364,10 @@
         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 +376,24 @@
         return locationManager.isLocationEnabledForUser(UserHandle.of(userId));
     }
 
+    private static boolean isLocationBypassAllowed(@NonNull Context context,
+            @NonNull String callingPackage) {
+        for (String bypassPackage : getLocationBypassPackages(context)) {
+            if (callingPackage.equals(bypassPackage)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @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 b5d97ab..c2a9864 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_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.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 @@
     }
 
     /**
+     * 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.
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 417fd49..a22e43e 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -49,7 +49,7 @@
     private static final String TAG = "CellSignalStrengthNr";
 
     // Lifted from Default carrier configs and max range of SSRSRP
-    // Boundaries: [-140 dB, -44 dB]
+    // Boundaries: [-156 dB, -31 dB]
     private int[] mSsRsrpThresholds = new int[] {
             -110, /* SIGNAL_STRENGTH_POOR */
             -90, /* SIGNAL_STRENGTH_MODERATE */
@@ -173,14 +173,14 @@
      */
     public CellSignalStrengthNr(int csiRsrp, int csiRsrq, int csiSinr, int csiCqiTableIndex,
             List<Byte> csiCqiReport, int ssRsrp, int ssRsrq, int ssSinr) {
-        mCsiRsrp = inRangeOrUnavailable(csiRsrp, -140, -44);
+        mCsiRsrp = inRangeOrUnavailable(csiRsrp, -156, -31);
         mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3);
         mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23);
         mCsiCqiTableIndex = inRangeOrUnavailable(csiCqiTableIndex, 1, 3);
         mCsiCqiReport = csiCqiReport.stream()
-                .map(cqi -> new Integer(inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 0, 15)))
+                .map(cqi -> inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 0, 15))
                 .collect(Collectors.toList());
-        mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44);
+        mSsRsrp = inRangeOrUnavailable(ssRsrp, -156, -31);
         mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20);
         mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40);
         updateLevel(null, null);
@@ -212,8 +212,8 @@
     }
 
     /**
-     * Reference: 3GPP TS 38.215.
-     * Range: -140 dBm to -44 dBm.
+     * Reference: 3GPP TS 38.133 10.1.6.1.
+     * Range: -156 dBm to -31 dBm.
      * @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
      * value.
      */
@@ -242,8 +242,8 @@
     }
 
     /**
-     * Reference: 3GPP TS 38.215.
-     * Range: -140 dBm to -44 dBm.
+     * Reference: 3GPP TS 38.133 10.1.6.1.
+     * Range: -156 dBm to -31 dBm.
      * @return CSI reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
      * value.
      */
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d2858ec..f254980 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3040,8 +3040,9 @@
      * @param callback Callback will be triggered once it succeeds or failed.
      *                 Pass null if don't care about the result.
      *
+     * @throws IllegalStateException when subscription manager service is not available.
+     * @throws SecurityException when clients do not have MODIFY_PHONE_STATE permission.
      * @hide
-     *
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -3051,7 +3052,9 @@
         if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
         try {
             ISub iSub = TelephonyManager.getSubscriptionService();
-            if (iSub == null) return;
+            if (iSub == null) {
+                throw new IllegalStateException("subscription manager service is null.");
+            }
 
             ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
                 @Override
@@ -3071,7 +3074,8 @@
             };
             iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
         } catch (RemoteException ex) {
-            // ignore it
+            loge("setPreferredDataSubscriptionId RemoteException=" + ex);
+            ex.rethrowFromSystemServer();
         }
     }
 
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a710e38..7fc8871 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1134,10 +1134,7 @@
             return false;
         }
         // DEFAULT can handle HIPRI.
-        if (hasApnType(type)) {
-            return true;
-        }
-        return false;
+        return hasApnType(type);
     }
 
     // Check whether the types of two APN same (even only one type of each APN is same).