Merge "Fix hardware TvInputService binding issue"
diff --git a/Android.bp b/Android.bp
index d976b91..fc713ff 100644
--- a/Android.bp
+++ b/Android.bp
@@ -294,6 +294,7 @@
     srcs: [
         ":framework-non-updatable-sources",
         "core/java/**/*.logtags",
+        ":apex-info-list",
     ],
     aidl: {
         generate_get_transaction_name: true,
@@ -432,11 +433,8 @@
         "core/java/android/util/LocalLog.java",
         "core/java/com/android/internal/util/HexDump.java",
         "core/java/com/android/internal/util/IndentingPrintWriter.java",
-        "core/java/com/android/internal/util/IState.java",
         "core/java/com/android/internal/util/MessageUtils.java",
         "core/java/com/android/internal/util/RingBufferIndices.java",
-        "core/java/com/android/internal/util/State.java",
-        "core/java/com/android/internal/util/StateMachine.java",
         "core/java/com/android/internal/util/WakeupMessage.java",
         "core/java/com/android/internal/util/TokenBucket.java",
     ],
diff --git a/ApiDocs.bp b/ApiDocs.bp
index a926ddc..8af2e02 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -112,7 +112,6 @@
 }
 
 // Defaults module for doc-stubs targets that use module source code as input.
-// This is the default/normal.
 stubs_defaults {
     name: "framework-doc-stubs-sources-default",
     defaults: ["framework-doc-stubs-default"],
@@ -147,12 +146,6 @@
 }
 
 droidstubs {
-    name: "framework-doc-stubs",
-    defaults: ["framework-doc-stubs-sources-default"],
-    args: metalava_framework_docs_args,
-}
-
-droidstubs {
     name: "framework-doc-system-stubs",
     defaults: ["framework-doc-stubs-sources-default"],
     args: metalava_framework_docs_args +
@@ -160,11 +153,8 @@
     api_levels_sdk_type: "system",
 }
 
-// Experimental target building doc stubs with module stub source code as input.
-// This is intended to eventually replace framework-doc-stubs, once all diffs
-// have been eliminated.
 droidstubs {
-    name: "framework-doc-stubs-module-stubs",
+    name: "framework-doc-stubs",
     defaults: ["framework-doc-stubs-default"],
     args: metalava_framework_docs_args,
     srcs: [
diff --git a/PACKAGE_MANAGER_OWNERS b/PACKAGE_MANAGER_OWNERS
new file mode 100644
index 0000000..e4549b4
--- /dev/null
+++ b/PACKAGE_MANAGER_OWNERS
@@ -0,0 +1,3 @@
+chiuwinson@google.com
+patb@google.com
+schfan@google.com
\ No newline at end of file
diff --git a/apex/blobstore/README.md b/apex/blobstore/README.md
new file mode 100644
index 0000000..69af436
--- /dev/null
+++ b/apex/blobstore/README.md
@@ -0,0 +1,125 @@
+<!--
+  Copyright (C) 2021 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
+-->
+
+# BlobStore Manager
+
+## Introduction
+* BlobStoreManager is a system service added in Android R release that facilitates sharing of
+  data blobs among apps.
+* Apps that would like to share data blobs with other apps can do so by contributing those
+  data blobs with the System and can choose how they would like the System to share the data blobs
+  with other apps.
+* Apps can access data blobs shared by other apps from the System using checksum of the data blobs
+  (plus some other data attributes. More details [below](#blob-handle)).
+* The APIs provided by the BlobStoreManager are meant to reduce storage and network usage by
+  reusing the data available on the device instead of downloading the same data again and having
+  multiple copies of the same data on disk.
+* It is not meant to provide access to the data which apps otherwise would not be able to access.
+  In other words, if an app’s only means of obtaining access to certain data is through
+  BlobStoreManager, then that use case is not really intended or supported.
+* For example, if earlier an app was downloading certain shared data from a server, then by using
+  BlobStoreManager, it can first check whether or not the data is already available on the device
+  before downloading.
+
+## Concepts
+### Blob handle
+Blob handle is the identifier of the data and it is what apps need to use for referring to the
+data blobs. Currently, this is made of following bits of information:
+* SHA256 checksum of data
+* Data label: A user readable string that indicates what the data blob is.
+  This is meant to be used when surfacing a list of blobs to the user.
+* Data expiry time: A timestamp after which the data blob should be considered invalid and not
+  allowed to be accessed by any app.
+* Data tag: An opaque string associated with the blob. System does not interpret this in any way or
+  use it for any purposes other than when checking whether two Blob handle identifiers are referring
+  to the same data blob. This is meant to be used by the apps, either for categorization for
+  data blobs or for adding additional identifiers. For example, an app can add tags like
+  *machine_learning* or *media* depending on the data blob if necessary.
+
+When comparing two Blob handles, the System will compare all the pieces of information above and
+only when two Blob handles are equal, the data blobs corresponding to those identifiers are
+considered equal.
+
+### Blob sharing session
+Session is a way to allow apps to contribute data over multiple time intervals. Each session is
+associated with a unique Identifier that is created and obtained by the apps by calling
+[BlobStoreManager#createSession](https://developer.android.com/reference/android/app/blob/BlobStoreManager#createSession(android.app.blob.BlobHandle)).
+Apps can save the Identifier associated with a session and use it to open and close it
+multiple times for contributing the data. For example, if an app is downloading
+some content over the network, it can start a Session and start contributing this data to the
+System immediately and if the network connection is lost for any reason, the app can close this
+session. When the download resumes, the app can reopen the session and start contributing again.
+Note that once the entire data is contributed, the app has no reason to hold on to the Session Id.
+
+### Blob commit
+Since a data blob can be contributed in a session over multiple time intervals, an app closing a
+session does not imply that the contribution is completed. So, *commit* is added as an explicit
+event / signal for the app to indicate that the contribution of the data blob is completed.
+At this point, the System can verify the data blob does indeed correspond to the Blob handle used
+by the app and prevent the app from making any further modifications to the data blob. Once the
+data blob is committed and verified by the System, it is available for other applications to access.
+
+### Access modes
+When an application contributes a data blob to the System, it can choose to specify how it would
+like the System to share this data blob with other applications. Access modes refer to the type of
+access that apps specified when contributing a data blob. As of Android S release, there are
+four access modes:
+* Allow specific packages: Apps can specify a specific set of applications that are allowed to
+  access their data blob.
+* Allow packages with the same signature: Apps can specify that only the applications that are
+  signed with the same certificate as them can access their data blob.
+* Allow public access: Apps can specify that any other app on the device can access their data blob.
+* Allow private access: Apps can specify that no other app can access their data blob unless they
+  happen to contribute the same data blob.
+  * Note that in this case, two apps might download the same data blob and contribute to the System
+    in which case we are not saving anything in terms of bandwidth usage, but we would still be
+    saving disk usage since we would be keeping only one copy of data on disk.
+
+### Lease
+Leasing a blob is a way to specify that an application is interested in using a data blob
+and would like the System to not delete this data blob. Applications can also access a blob
+without holding a lease on it, in which case the System can choose to delete the data blob at any
+time. So, if an application wants to make sure a data blob is available for access for a certain
+period, it is recommended that the application acquire a lease on the data blob. Applications can
+either specify upfront how long they would like to hold the lease for (which is called the lease
+expiry time), or they can acquire a lease without specifying a time period and release the lease
+when they are done with the data blob.
+
+## Sharing data blobs across users
+By default, data blobs are only accessible to applications in the user in which the data blob was
+contributed, but if an application holds the permission
+[ACCESS_BLOBS_ACROSS_USERS](https://developer.android.com/reference/android/Manifest.permission#ACCESS_BLOBS_ACROSS_USERS),
+then they are allowed to access blobs that are contributed by the applications in the other users.
+As of Android S, this permission is only available to following set of applications:
+* Apps signed with the platform certificate
+* Privileged applications
+* Applications holding the
+  [ASSISTANT](https://developer.android.com/reference/android/app/role/RoleManager#ROLE_ASSISTANT)
+  role
+* Development applications
+
+Note that the access modes that applications choose while committing the data blobs still apply
+when these data blobs are accessed across users. So for example, if *appA* contributed a
+data blob in *user0* and specified to share this data blob with only a specific set of
+applications [*appB*, *appC*], then *appD* on *user10* will not be able to access this data blob
+even if the app is granted the `ACCESS_BLOBS_ACROSS_USERS` permission.
+
+When apps that are allowed to access blobs across users
+(i.e. those holding the permission `ACCESS_BLOBS_ACROSS_USERS`) try to access a data blob,
+they can do so as if it is any other data blob. In other words, the applications don’t need to
+know where the data blob is contributed, because the System will automatically check and will
+allow access if this data blob is available either on the user in which the calling application
+is running in or other users.
\ No newline at end of file
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 4e46aa3..9564dde 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -41,6 +41,10 @@
     private IActivityManager mAm;
     private IPackageManager mPm;
 
+    Am() {
+        svcInit();
+    }
+
     /**
      * Command-line entry point.
      *
@@ -50,6 +54,20 @@
         (new Am()).run(args);
     }
 
+    private void svcInit() {
+        mAm = ActivityManager.getService();
+        if (mAm == null) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            return;
+        }
+
+        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+        if (mPm == null) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            return;
+        }
+    }
+
     @Override
     public void onShowUsage(PrintStream out) {
         try {
@@ -61,19 +79,6 @@
 
     @Override
     public void onRun() throws Exception {
-
-        mAm = ActivityManager.getService();
-        if (mAm == null) {
-            System.err.println(NO_SYSTEM_ERROR_CODE);
-            throw new AndroidException("Can't connect to activity manager; is the system running?");
-        }
-
-        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
-        if (mPm == null) {
-            System.err.println(NO_SYSTEM_ERROR_CODE);
-            throw new AndroidException("Can't connect to package manager; is the system running?");
-        }
-
         String op = nextArgRequired();
 
         if (op.equals("instrument")) {
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 1e72ddf..0b439df 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -545,6 +545,8 @@
                 mWm.setAnimationScales(oldAnims);
             }
         }
+        // Exit from here instead of going down the path of normal shutdown which is slow.
+        System.exit(0);
     }
 
     private static String readLogcat(long startTimeMs) {
diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS
index 69dfcc9..062ffd4 100644
--- a/cmds/idmap2/OWNERS
+++ b/cmds/idmap2/OWNERS
@@ -1,4 +1,4 @@
 set noparent
 toddke@google.com
-rtmitchell@google.com
-patb@google.com
\ No newline at end of file
+patb@google.com
+zyy@google.com
diff --git a/config/README.md b/config/README.md
new file mode 100644
index 0000000..450a5c6
--- /dev/null
+++ b/config/README.md
@@ -0,0 +1,13 @@
+# Configuration files for ART compiling the framework
+
+* boot-image-profile.txt: A list of methods from the boot classpath to be compiled by dex2oat.
+  The order in the file is not relevant.
+* boot-profile.txt: An ordered list of methods from the boot classpath to be compiled by
+  the JIT in the order provided in the file. Used by JIT zygote, when on-device
+  signing failed.
+* dirty-image-objects: List of objects in the boot image which are known to
+  become dirty. This helps binning objects in the image file.
+* preloaded-classes: classes that will be allocated in the boot image, and
+  initialized by the zygote.
+* preloaded-classes-denylist: Classes that should not be initialized in the
+  zygote, as they have app-specific behavior.
diff --git a/core/api/current.txt b/core/api/current.txt
index 0eba9d7..f21518c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -112,6 +112,7 @@
     field public static final String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
     field public static final String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
     field public static final String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
+    field public static final String NEARBY_WIFI_DEVICES = "android.permission.NEARBY_WIFI_DEVICES";
     field public static final String NFC = "android.permission.NFC";
     field public static final String NFC_PREFERRED_PAYMENT_INFO = "android.permission.NFC_PREFERRED_PAYMENT_INFO";
     field public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
@@ -8647,12 +8648,14 @@
     method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
     method public int getState();
+    method public int isCisCentralSupported();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
     method public boolean isEnabled();
     method public boolean isLe2MPhySupported();
     method public boolean isLeCodedPhySupported();
     method public boolean isLeExtendedAdvertisingSupported();
     method public boolean isLePeriodicAdvertisingSupported();
+    method public int isLePeriodicAdvertisingSyncTransferSenderSupported();
     method public boolean isMultipleAdvertisementSupported();
     method public boolean isOffloadedFilteringSupported();
     method public boolean isOffloadedScanBatchingSupported();
@@ -9122,8 +9125,10 @@
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]);
     field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
     field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
     field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
@@ -9142,11 +9147,14 @@
 
   public abstract class BluetoothGattCallback {
     ctor public BluetoothGattCallback();
-    method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
-    method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
+    method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
+    method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]);
+    method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
+    method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
-    method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
+    method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
+    method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]);
     method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
     method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
@@ -9163,20 +9171,20 @@
     method public int describeContents();
     method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
     method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
-    method public Float getFloatValue(int, int);
+    method @Deprecated public Float getFloatValue(int, int);
     method public int getInstanceId();
-    method public Integer getIntValue(int, int);
+    method @Deprecated public Integer getIntValue(int, int);
     method public int getPermissions();
     method public int getProperties();
     method public android.bluetooth.BluetoothGattService getService();
-    method public String getStringValue(int);
+    method @Deprecated public String getStringValue(int);
     method public java.util.UUID getUuid();
-    method public byte[] getValue();
+    method @Deprecated public byte[] getValue();
     method public int getWriteType();
-    method public boolean setValue(byte[]);
-    method public boolean setValue(int, int, int);
-    method public boolean setValue(int, int, int, int);
-    method public boolean setValue(String);
+    method @Deprecated public boolean setValue(byte[]);
+    method @Deprecated public boolean setValue(int, int, int);
+    method @Deprecated public boolean setValue(int, int, int, int);
+    method @Deprecated public boolean setValue(String);
     method public void setWriteType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
@@ -9216,8 +9224,8 @@
     method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
     method public int getPermissions();
     method public java.util.UUID getUuid();
-    method public byte[] getValue();
-    method public boolean setValue(byte[]);
+    method @Deprecated public byte[] getValue();
+    method @Deprecated public boolean setValue(byte[]);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
     field public static final byte[] DISABLE_NOTIFICATION_VALUE;
@@ -9505,7 +9513,12 @@
     field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
     field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
     field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
+    field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa
+    field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65
+    field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66
     field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
+    field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8
+    field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9
     field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
     field public static final int SUCCESS = 0; // 0x0
   }
@@ -31414,6 +31427,8 @@
     method @Nullable public double[] createDoubleArray();
     method @Nullable public float[] createFloatArray();
     method @Nullable public int[] createIntArray();
+    method @Nullable public <T extends android.os.IInterface> T[] createInterfaceArray(@NonNull java.util.function.IntFunction<T[]>, @NonNull java.util.function.Function<android.os.IBinder,T>);
+    method @Nullable public <T extends android.os.IInterface> java.util.ArrayList<T> createInterfaceArrayList(@NonNull java.util.function.Function<android.os.IBinder,T>);
     method @Nullable public long[] createLongArray();
     method @Nullable public String[] createStringArray();
     method @Nullable public java.util.ArrayList<java.lang.String> createStringArrayList();
@@ -31432,7 +31447,9 @@
     method @NonNull public static android.os.Parcel obtain();
     method @NonNull public static android.os.Parcel obtain(@NonNull android.os.IBinder);
     method @Nullable public Object[] readArray(@Nullable ClassLoader);
+    method @Nullable public <T> T[] readArray(@Nullable ClassLoader, @NonNull Class<T>);
     method @Nullable public java.util.ArrayList readArrayList(@Nullable ClassLoader);
+    method @Nullable public <T> java.util.ArrayList<T> readArrayList(@Nullable ClassLoader, @NonNull Class<? extends T>);
     method public void readBinderArray(@NonNull android.os.IBinder[]);
     method public void readBinderList(@NonNull java.util.List<android.os.IBinder>);
     method public boolean readBoolean();
@@ -31450,25 +31467,32 @@
     method public float readFloat();
     method public void readFloatArray(@NonNull float[]);
     method @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
+    method @Nullable public <K, V> java.util.HashMap<K,V> readHashMap(@Nullable ClassLoader, @NonNull Class<? extends K>, @NonNull Class<? extends V>);
     method public int readInt();
     method public void readIntArray(@NonNull int[]);
+    method public <T extends android.os.IInterface> void readInterfaceArray(@NonNull T[], @NonNull java.util.function.Function<android.os.IBinder,T>);
+    method public <T extends android.os.IInterface> void readInterfaceList(@NonNull java.util.List<T>, @NonNull java.util.function.Function<android.os.IBinder,T>);
     method public void readList(@NonNull java.util.List, @Nullable ClassLoader);
     method public <T> void readList(@NonNull java.util.List<? super T>, @Nullable ClassLoader, @NonNull Class<T>);
     method public long readLong();
     method public void readLongArray(@NonNull long[]);
     method public void readMap(@NonNull java.util.Map, @Nullable ClassLoader);
+    method public <K, V> void readMap(@NonNull java.util.Map<? super K,? super V>, @Nullable ClassLoader, @NonNull Class<K>, @NonNull Class<V>);
     method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
     method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>);
     method @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader);
+    method @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader, @NonNull Class<T>);
     method @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
     method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
     method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
     method @Nullable public android.os.PersistableBundle readPersistableBundle();
     method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
     method @Nullable public java.io.Serializable readSerializable();
+    method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
     method @NonNull public android.util.Size readSize();
     method @NonNull public android.util.SizeF readSizeF();
     method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
+    method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader, @NonNull Class<? extends T>);
     method @Nullable public android.util.SparseBooleanArray readSparseBooleanArray();
     method @Nullable public String readString();
     method public void readStringArray(@NonNull String[]);
@@ -31501,6 +31525,8 @@
     method public void writeFloatArray(@Nullable float[]);
     method public void writeInt(int);
     method public void writeIntArray(@Nullable int[]);
+    method public <T extends android.os.IInterface> void writeInterfaceArray(@Nullable T[]);
+    method public <T extends android.os.IInterface> void writeInterfaceList(@Nullable java.util.List<T>);
     method public void writeInterfaceToken(@NonNull String);
     method public void writeList(@Nullable java.util.List);
     method public void writeLong(long);
@@ -40678,6 +40704,7 @@
     method @NonNull public java.util.List<java.lang.Integer> getBands();
     method @NonNull public java.util.List<java.lang.String> getMccMncs();
     method public int getPriority();
+    method @NonNull public java.util.List<android.telephony.RadioAccessSpecifier> getRadioAccessSpecifiers();
     method public int getSubId();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.AvailableNetworkInfo> CREATOR;
@@ -40686,6 +40713,14 @@
     field public static final int PRIORITY_MED = 2; // 0x2
   }
 
+  public static final class AvailableNetworkInfo.Builder {
+    ctor public AvailableNetworkInfo.Builder(int);
+    method @NonNull public android.telephony.AvailableNetworkInfo build();
+    method @NonNull public android.telephony.AvailableNetworkInfo.Builder setMccMncs(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.telephony.AvailableNetworkInfo.Builder setPriority(int);
+    method @NonNull public android.telephony.AvailableNetworkInfo.Builder setRadioAccessSpecifiers(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
+  }
+
   public final class BarringInfo implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.telephony.BarringInfo.BarringServiceInfo getBarringServiceInfo(int);
@@ -40719,11 +40754,11 @@
   }
 
   public class CarrierConfigManager {
-    method @Nullable public android.os.PersistableBundle getConfig();
-    method @Nullable public android.os.PersistableBundle getConfigByComponentForSubId(@NonNull String, int);
-    method @Nullable public android.os.PersistableBundle getConfigForSubId(int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.os.PersistableBundle getConfig();
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.os.PersistableBundle getConfigByComponentForSubId(@NonNull String, int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.os.PersistableBundle getConfigForSubId(int);
     method public static boolean isConfigForIdentifiedCarrier(android.os.PersistableBundle);
-    method public void notifyConfigChangedForSubId(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyConfigChangedForSubId(int);
     field public static final String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
     field public static final int CARRIER_NR_AVAILABILITY_NSA = 1; // 0x1
     field public static final int CARRIER_NR_AVAILABILITY_SA = 2; // 0x2
@@ -40794,6 +40829,7 @@
     field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
     field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
     field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
+    field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_bool";
     field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
     field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int";
@@ -40855,6 +40891,8 @@
     field public static final String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final String KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL = "enhanced_4g_lte_on_by_default_bool";
     field public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT = "enhanced_4g_lte_title_variant_int";
+    field public static final String KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT = "esim_download_retry_backoff_timer_sec_int";
+    field public static final String KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT = "esim_max_download_retry_attempts_int";
     field public static final String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
     field public static final String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
     field public static final String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
@@ -40957,6 +40995,7 @@
     field public static final String KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL = "show_wfc_location_privacy_policy_bool";
     field public static final String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
     field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
+    field public static final String KEY_SMDP_SERVER_ADDRESS_STRING = "smdp_server_address_string";
     field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
     field public static final String KEY_SUPPORTS_CALL_COMPOSER_BOOL = "supports_call_composer_bool";
     field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_DTMF_BOOL = "supports_device_to_device_communication_using_dtmf_bool";
@@ -42729,7 +42768,7 @@
     method public boolean isEmergencyNumber(@NonNull String);
     method public boolean isHearingAidCompatibilitySupported();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isManualNetworkSelectionAllowed();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isModemEnabledForSlot(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isModemEnabledForSlot(int);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int isMultiSimSupported();
     method public boolean isNetworkRoaming();
     method public boolean isRadioInterfaceCapabilitySupported(@NonNull String);
@@ -47505,6 +47544,10 @@
     field public static final int KEYCODE_CUT = 277; // 0x115
     field public static final int KEYCODE_D = 32; // 0x20
     field public static final int KEYCODE_DEL = 67; // 0x43
+    field public static final int KEYCODE_DEMO_APP_1 = 301; // 0x12d
+    field public static final int KEYCODE_DEMO_APP_2 = 302; // 0x12e
+    field public static final int KEYCODE_DEMO_APP_3 = 303; // 0x12f
+    field public static final int KEYCODE_DEMO_APP_4 = 304; // 0x130
     field public static final int KEYCODE_DPAD_CENTER = 23; // 0x17
     field public static final int KEYCODE_DPAD_DOWN = 20; // 0x14
     field public static final int KEYCODE_DPAD_DOWN_LEFT = 269; // 0x10d
@@ -47536,6 +47579,10 @@
     field public static final int KEYCODE_F7 = 137; // 0x89
     field public static final int KEYCODE_F8 = 138; // 0x8a
     field public static final int KEYCODE_F9 = 139; // 0x8b
+    field public static final int KEYCODE_FEATURED_APP_1 = 297; // 0x129
+    field public static final int KEYCODE_FEATURED_APP_2 = 298; // 0x12a
+    field public static final int KEYCODE_FEATURED_APP_3 = 299; // 0x12b
+    field public static final int KEYCODE_FEATURED_APP_4 = 300; // 0x12c
     field public static final int KEYCODE_FOCUS = 80; // 0x50
     field public static final int KEYCODE_FORWARD = 125; // 0x7d
     field public static final int KEYCODE_FORWARD_DEL = 112; // 0x70
@@ -47701,6 +47748,14 @@
     field public static final int KEYCODE_U = 49; // 0x31
     field public static final int KEYCODE_UNKNOWN = 0; // 0x0
     field public static final int KEYCODE_V = 50; // 0x32
+    field public static final int KEYCODE_VIDEO_APP_1 = 289; // 0x121
+    field public static final int KEYCODE_VIDEO_APP_2 = 290; // 0x122
+    field public static final int KEYCODE_VIDEO_APP_3 = 291; // 0x123
+    field public static final int KEYCODE_VIDEO_APP_4 = 292; // 0x124
+    field public static final int KEYCODE_VIDEO_APP_5 = 293; // 0x125
+    field public static final int KEYCODE_VIDEO_APP_6 = 294; // 0x126
+    field public static final int KEYCODE_VIDEO_APP_7 = 295; // 0x127
+    field public static final int KEYCODE_VIDEO_APP_8 = 296; // 0x128
     field public static final int KEYCODE_VOICE_ASSIST = 231; // 0xe7
     field public static final int KEYCODE_VOLUME_DOWN = 25; // 0x19
     field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 49df45a..9af6c1b 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -113,6 +113,11 @@
   public class AudioManager {
     method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
     method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpSamplingRate(int);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpVolume(int);
     method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
     field public static final int FLAG_FROM_KEY = 4096; // 0x1000
   }
@@ -292,6 +297,10 @@
     method @Nullable public android.os.IBinder getOrThrow() throws android.os.StatsServiceManager.ServiceNotFoundException;
   }
 
+  public class SystemConfigManager {
+    method @NonNull public java.util.List<android.content.ComponentName> getEnabledComponentOverrides(@NonNull String);
+  }
+
 }
 
 package android.os.storage {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6f825ae..78e6a07 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -475,6 +475,8 @@
     field public static final String OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = "android:auto_revoke_permissions_if_unused";
     field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
     field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
+    field public static final String OPSTR_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
+    field public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
     field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final String OPSTR_GPS = "android:gps";
     field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
@@ -1935,6 +1937,22 @@
     field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
   }
 
+  public final class BluetoothActivityEnergyInfo implements android.os.Parcelable {
+    method public int getBluetoothStackState();
+    method public long getControllerEnergyUsed();
+    method public long getControllerIdleTimeMillis();
+    method public long getControllerRxTimeMillis();
+    method public long getControllerTxTimeMillis();
+    method public long getTimestampMillis();
+    method @NonNull public java.util.List<android.bluetooth.UidTraffic> getUidTraffic();
+    method public boolean isValid();
+    field public static final int BT_STACK_STATE_INVALID = 0; // 0x0
+    field public static final int BT_STACK_STATE_STATE_ACTIVE = 1; // 0x1
+    field public static final int BT_STACK_STATE_STATE_IDLE = 3; // 0x3
+    field public static final int BT_STACK_STATE_STATE_SCANNING = 2; // 0x2
+    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothActivityEnergyInfo> CREATOR;
+  }
+
   public final class BluetoothAdapter {
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean);
@@ -2234,6 +2252,13 @@
     method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]);
   }
 
+  public final class UidTraffic implements java.lang.Cloneable android.os.Parcelable {
+    method public long getRxBytes();
+    method public long getTxBytes();
+    method public int getUid();
+    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.UidTraffic> CREATOR;
+  }
+
 }
 
 package android.bluetooth.le {
@@ -8556,7 +8581,6 @@
   public class SystemConfigManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
-    method @NonNull public java.util.List<java.lang.String> getEnabledComponentOverrides(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public int[] getSystemPermissionUids(@NonNull String);
   }
 
@@ -9126,6 +9150,7 @@
     field public static final String NAMESPACE_BIOMETRICS = "biometrics";
     field public static final String NAMESPACE_BLOBSTORE = "blobstore";
     field public static final String NAMESPACE_BLUETOOTH = "bluetooth";
+    field public static final String NAMESPACE_CAPTIVEPORTALLOGIN = "captive_portal_login";
     field public static final String NAMESPACE_CLIPBOARD = "clipboard";
     field public static final String NAMESPACE_CONNECTIVITY = "connectivity";
     field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
@@ -9161,6 +9186,7 @@
     field public static final String NAMESPACE_SYSTEMUI = "systemui";
     field public static final String NAMESPACE_SYSTEM_TIME = "system_time";
     field public static final String NAMESPACE_TELEPHONY = "telephony";
+    field public static final String NAMESPACE_TETHERING = "tethering";
     field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
     field public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot";
   }
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6ccdf91..d0e659b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2748,7 +2748,7 @@
     method public static String actionToString(int);
     method public final void setDisplayId(int);
     field public static final int FLAG_IS_ACCESSIBILITY_EVENT = 2048; // 0x800
-    field public static final int LAST_KEYCODE = 288; // 0x120
+    field public static final int LAST_KEYCODE = 304; // 0x130
   }
 
   public final class KeyboardShortcutGroup implements android.os.Parcelable {
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 0d6a079..e6cdcc0 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -31,6 +31,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -86,6 +87,12 @@
         if (TextUtils.isEmpty(type)) {
             throw new IllegalArgumentException("the type must not be empty: " + type);
         }
+        if (name.length() > 200) {
+            throw new IllegalArgumentException("account name is longer than 200 characters");
+        }
+        if (type.length() > 200) {
+            throw new IllegalArgumentException("account type is longer than 200 characters");
+        }
         this.name = name;
         this.type = type;
         this.accessId = accessId;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index db5dcc5..af59ea1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -77,7 +77,6 @@
 import android.os.Looper;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
-import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager.ServiceNotFoundException;
@@ -8788,9 +8787,7 @@
      * the activity is visible after the screen is turned on when the lockscreen is up. In addition,
      * if this flag is set and the activity calls {@link
      * KeyguardManager#requestDismissKeyguard(Activity, KeyguardManager.KeyguardDismissCallback)}
-     * the screen will turn on. If the screen is off and device is not secured, this flag can turn
-     * screen on and dismiss keyguard to make this activity visible and resume, which can be used to
-     * replace {@link PowerManager#ACQUIRE_CAUSES_WAKEUP}
+     * the screen will turn on.
      *
      * @param turnScreenOn {@code true} to turn on the screen; {@code false} otherwise.
      *
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 6c3795d..bfff27a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -464,11 +464,7 @@
 
         @Override
         public int hashCode() {
-            return hashCode(authority, userId);
-        }
-
-        public static int hashCode(final String auth, final int userIdent) {
-            return ((auth != null) ? auth.hashCode() : 0) ^ userIdent;
+            return ((authority != null) ? authority.hashCode() : 0) ^ userId;
         }
     }
 
@@ -490,7 +486,7 @@
     // Note we never removes items from this map but that's okay because there are only so many
     // users and so many authorities.
     @GuardedBy("mGetProviderKeys")
-    final SparseArray<ProviderKey> mGetProviderKeys = new SparseArray<>();
+    final ArrayMap<ProviderKey, ProviderKey> mGetProviderKeys = new ArrayMap<>();
 
     final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
         = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
@@ -7020,11 +7016,11 @@
     }
 
     private ProviderKey getGetProviderKey(String auth, int userId) {
-        final int key = ProviderKey.hashCode(auth, userId);
+        final ProviderKey key = new ProviderKey(auth, userId);
         synchronized (mGetProviderKeys) {
             ProviderKey lock = mGetProviderKeys.get(key);
             if (lock == null) {
-                lock = new ProviderKey(auth, userId);
+                lock = key;
                 mGetProviderKeys.put(key, lock);
             }
             return lock;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d932a29..63f700b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1292,6 +1292,9 @@
     /** @hide */
     public static final int OP_UWB_RANGING = AppProtoEnums.APP_OP_UWB_RANGING;
 
+    /** @hide */
+    public static final int OP_NEARBY_WIFI_DEVICES = AppProtoEnums.APP_OP_NEARBY_WIFI_DEVICES;
+
     /**
      * Activity recognition being accessed by an activity recognition source, which
      * is a component that already has access since it is the one that detects
@@ -1310,9 +1313,23 @@
     public static final int OP_RECORD_INCOMING_PHONE_AUDIO =
             AppProtoEnums.APP_OP_RECORD_INCOMING_PHONE_AUDIO;
 
+    /**
+     * VPN app establishes a connection through the VpnService API.
+     *
+     * @hide
+     */
+    public static final int OP_ESTABLISH_VPN_SERVICE = AppProtoEnums.APP_OP_ESTABLISH_VPN_SERVICE;
+
+    /**
+     * VPN app establishes a connection through the VpnManager API.
+     *
+     * @hide
+     */
+    public static final int OP_ESTABLISH_VPN_MANAGER = AppProtoEnums.APP_OP_ESTABLISH_VPN_MANAGER;
+
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 116;
+    public static final int _NUM_OP = 119;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1731,6 +1748,8 @@
     public static final String OPSTR_MANAGE_MEDIA = "android:manage_media";
     /** @hide */
     public static final String OPSTR_UWB_RANGING = "android:uwb_ranging";
+    /** @hide */
+    public static final String OPSTR_NEARBY_WIFI_DEVICES = "android:nearby_wifi_devices";
 
     /**
      * Activity recognition being accessed by an activity recognition source, which
@@ -1749,6 +1768,22 @@
     public static final String OPSTR_RECORD_INCOMING_PHONE_AUDIO =
             "android:record_incoming_phone_audio";
 
+    /**
+     * VPN app establishes a connection through the VpnService API.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
+
+    /**
+     * VPN app establishes a connection through the VpnManager API.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String OPSTR_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
+
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1819,6 +1854,7 @@
             OP_BLUETOOTH_CONNECT,
             OP_BLUETOOTH_ADVERTISE,
             OP_UWB_RANGING,
+            OP_NEARBY_WIFI_DEVICES,
 
             // APPOP PERMISSIONS
             OP_ACCESS_NOTIFICATIONS,
@@ -1963,6 +1999,9 @@
             OP_ACTIVITY_RECOGNITION,            // OP_ACTIVITY_RECOGNITION_SOURCE
             OP_BLUETOOTH_ADVERTISE,             // OP_BLUETOOTH_ADVERTISE
             OP_RECORD_INCOMING_PHONE_AUDIO,     // OP_RECORD_INCOMING_PHONE_AUDIO
+            OP_NEARBY_WIFI_DEVICES,             // OP_NEARBY_WIFI_DEVICES
+            OP_ESTABLISH_VPN_SERVICE,           // OP_ESTABLISH_VPN_SERVICE
+            OP_ESTABLISH_VPN_MANAGER,           // OP_ESTABLISH_VPN_MANAGER
     };
 
     /**
@@ -2085,6 +2124,9 @@
             OPSTR_ACTIVITY_RECOGNITION_SOURCE,
             OPSTR_BLUETOOTH_ADVERTISE,
             OPSTR_RECORD_INCOMING_PHONE_AUDIO,
+            OPSTR_NEARBY_WIFI_DEVICES,
+            OPSTR_ESTABLISH_VPN_SERVICE,
+            OPSTR_ESTABLISH_VPN_MANAGER,
     };
 
     /**
@@ -2208,6 +2250,9 @@
             "ACTIVITY_RECOGNITION_SOURCE",
             "BLUETOOTH_ADVERTISE",
             "RECORD_INCOMING_PHONE_AUDIO",
+            "NEARBY_WIFI_DEVICES",
+            "ESTABLISH_VPN_SERVICE",
+            "ESTABLISH_VPN_MANAGER",
     };
 
     /**
@@ -2332,6 +2377,9 @@
             null, // no permission for OP_ACTIVITY_RECOGNITION_SOURCE,
             Manifest.permission.BLUETOOTH_ADVERTISE,
             null, // no permission for OP_RECORD_INCOMING_PHONE_AUDIO,
+            Manifest.permission.NEARBY_WIFI_DEVICES,
+            null, // no permission for OP_ESTABLISH_VPN_SERVICE
+            null, // no permission for OP_ESTABLISH_VPN_MANAGER
     };
 
     /**
@@ -2456,6 +2504,9 @@
             null, // ACTIVITY_RECOGNITION_SOURCE
             null, // BLUETOOTH_ADVERTISE
             null, // RECORD_INCOMING_PHONE_AUDIO
+            null, // NEARBY_WIFI_DEVICES
+            null, // ESTABLISH_VPN_SERVICE
+            null, // ESTABLISH_VPN_MANAGER
     };
 
     /**
@@ -2579,6 +2630,9 @@
             null, // ACTIVITY_RECOGNITION_SOURCE
             null, // BLUETOOTH_ADVERTISE
             null, // RECORD_INCOMING_PHONE_AUDIO
+            null, // NEARBY_WIFI_DEVICES
+            null, // ESTABLISH_VPN_SERVICE
+            null, // ESTABLISH_VPN_MANAGER
     };
 
     /**
@@ -2701,6 +2755,9 @@
             AppOpsManager.MODE_ALLOWED, // ACTIVITY_RECOGNITION_SOURCE
             AppOpsManager.MODE_ALLOWED, // BLUETOOTH_ADVERTISE
             AppOpsManager.MODE_ALLOWED, // RECORD_INCOMING_PHONE_AUDIO
+            AppOpsManager.MODE_ALLOWED, // NEARBY_WIFI_DEVICES
+            AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_SERVICE
+            AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_MANAGER
     };
 
     /**
@@ -2827,6 +2884,9 @@
             false, // ACTIVITY_RECOGNITION_SOURCE
             false, // BLUETOOTH_ADVERTISE
             false, // RECORD_INCOMING_PHONE_AUDIO
+            false, // NEARBY_WIFI_DEVICES
+            false, // OP_ESTABLISH_VPN_SERVICE
+            false, // OP_ESTABLISH_VPN_MANAGER
     };
 
     /**
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 08cd0b3..53b16d3 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -48,18 +48,19 @@
                                ClassLoader parent, String classLoaderName) {
         return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
                               librarySearchPath, libraryPermittedPath, parent, classLoaderName,
-                              null, null);
+                              null, null, null);
     }
 
     ClassLoader getClassLoaderWithSharedLibraries(
             String zip, int targetSdkVersion, boolean isBundled,
             String librarySearchPath, String libraryPermittedPath,
             ClassLoader parent, String classLoaderName,
-            List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries) {
+            List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries,
+            List<ClassLoader> sharedLibrariesLoadedAfterApp) {
         // For normal usage the cache key used is the same as the zip path.
         return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
                               libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries,
-                              nativeSharedLibraries);
+                              nativeSharedLibraries, sharedLibrariesLoadedAfterApp);
     }
 
     /**
@@ -71,7 +72,8 @@
      */
     ClassLoader getSharedLibraryClassLoaderWithSharedLibraries(String zip, int targetSdkVersion,
             boolean isBundled, String librarySearchPath, String libraryPermittedPath,
-            ClassLoader parent, String classLoaderName, List<ClassLoader> sharedLibraries) {
+            ClassLoader parent, String classLoaderName, List<ClassLoader> sharedLibraries,
+            List<ClassLoader> sharedLibrariesAfter) {
         ClassLoader loader = getCachedNonBootclasspathSystemLib(zip, parent, classLoaderName,
                 sharedLibraries);
         if (loader != null) {
@@ -86,14 +88,15 @@
         nativeSharedLibraries.add("ALL");
         return getClassLoaderWithSharedLibraries(zip, targetSdkVersion, isBundled,
               librarySearchPath, libraryPermittedPath, parent, classLoaderName, sharedLibraries,
-              nativeSharedLibraries);
+              nativeSharedLibraries, sharedLibrariesAfter);
     }
 
     private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                                        String librarySearchPath, String libraryPermittedPath,
                                        ClassLoader parent, String cacheKey,
                                        String classLoaderName, List<ClassLoader> sharedLibraries,
-                                       List<String> nativeSharedLibraries) {
+                                       List<String> nativeSharedLibraries,
+                                       List<ClassLoader> sharedLibrariesLoadedAfterApp) {
         /*
          * This is the parent we use if they pass "null" in.  In theory
          * this should be the "system" class loader; in practice we
@@ -123,7 +126,7 @@
                 ClassLoader classloader = ClassLoaderFactory.createClassLoader(
                         zip,  librarySearchPath, libraryPermittedPath, parent,
                         targetSdkVersion, isBundled, classLoaderName, sharedLibraries,
-                        nativeSharedLibraries);
+                        nativeSharedLibraries, sharedLibrariesLoadedAfterApp);
 
                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
@@ -140,7 +143,8 @@
 
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
             ClassLoader loader = ClassLoaderFactory.createClassLoader(
-                    zip, null, parent, classLoaderName, sharedLibraries);
+                    zip, null, parent, classLoaderName, sharedLibraries,
+                    null /*sharedLibrariesLoadedAfterApp*/);
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             return loader;
         }
@@ -196,7 +200,7 @@
         ClassLoader classLoader = getClassLoader(path, Build.VERSION.SDK_INT, true /*isBundled*/,
                 null /*librarySearchPath*/, null /*libraryPermittedPath*/, null /*parent*/,
                 null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/,
-                null /* nativeSharedLibraries */);
+                null /* nativeSharedLibraries */, null /*sharedLibrariesLoadedAfterApp*/);
 
         if (classLoader == null) {
             // bad configuration or break in classloading code
@@ -267,7 +271,8 @@
         // stub's APK path, when the actual package path is the donor APK.
         return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null,
                               cacheKey, null /* classLoaderName */, null /* sharedLibraries */,
-                              null /* nativeSharedLibraries */);
+                              null /* nativeSharedLibraries */,
+                              null /*sharedLibrariesLoadedAfterApp*/);
     }
 
     /**
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index a2c9795..f6d27e1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -54,10 +54,12 @@
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.DisplayAdjustments;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
 
@@ -76,6 +78,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Objects;
@@ -700,7 +703,7 @@
     ClassLoader createSharedLibraryLoader(SharedLibraryInfo sharedLibrary,
             boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
         List<String> paths = sharedLibrary.getAllCodePaths();
-        List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
+        Pair<List<ClassLoader>, List<ClassLoader>> sharedLibraries = createSharedLibrariesLoaders(
                 sharedLibrary.getDependencies(), isBundledApp, librarySearchPath,
                 libraryPermittedPath);
         final String jars = (paths.size() == 1) ? paths.get(0) :
@@ -711,15 +714,31 @@
         return ApplicationLoaders.getDefault().getSharedLibraryClassLoaderWithSharedLibraries(jars,
                     mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                     libraryPermittedPath, /* parent */ null,
-                    /* classLoaderName */ null, sharedLibraries);
+                    /* classLoaderName */ null, sharedLibraries.first, sharedLibraries.second);
     }
 
-    private List<ClassLoader> createSharedLibrariesLoaders(List<SharedLibraryInfo> sharedLibraries,
+    /**
+     *
+     * @return a {@link Pair} of List<ClassLoader> where the first is for standard shared libraries
+     *         and the second is list for shared libraries that code should be loaded after the dex
+     */
+    private Pair<List<ClassLoader>, List<ClassLoader>> createSharedLibrariesLoaders(
+            List<SharedLibraryInfo> sharedLibraries,
             boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) {
-        if (sharedLibraries == null) {
-            return null;
+        if (sharedLibraries == null || sharedLibraries.isEmpty()) {
+            return new Pair<>(null, null);
         }
+
+        // if configured to do so, shared libs are split into 2 collections: those that are
+        // on the class path before the applications code, which is standard, and those
+        // specified to be loaded after the applications code.
+        HashSet<String> libsToLoadAfter = new HashSet<>();
+        Resources systemR = Resources.getSystem();
+        Collections.addAll(libsToLoadAfter, systemR.getStringArray(
+                R.array.config_sharedLibrariesLoadedAfterApp));
+
         List<ClassLoader> loaders = new ArrayList<>();
+        List<ClassLoader> after = new ArrayList<>();
         for (SharedLibraryInfo info : sharedLibraries) {
             if (info.isNative()) {
                 // Native shared lib doesn't contribute to the native lib search path. Its name is
@@ -727,10 +746,19 @@
                 // default linker namespace.
                 continue;
             }
-            loaders.add(createSharedLibraryLoader(
-                    info, isBundledApp, librarySearchPath, libraryPermittedPath));
+            if (libsToLoadAfter.contains(info.getName())) {
+                if (DEBUG) {
+                    Slog.v(ActivityThread.TAG,
+                            info.getName() + " will be loaded after application code");
+                }
+                after.add(createSharedLibraryLoader(
+                        info, isBundledApp, librarySearchPath, libraryPermittedPath));
+            } else {
+                loaders.add(createSharedLibraryLoader(
+                        info, isBundledApp, librarySearchPath, libraryPermittedPath));
+            }
         }
-        return loaders;
+        return new Pair<>(loaders, after);
     }
 
     private StrictMode.ThreadPolicy allowThreadDiskReads() {
@@ -955,9 +983,9 @@
             // as this is early and necessary.
             StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
 
-            List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders(
-                    mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath,
-                    libraryPermittedPath);
+            Pair<List<ClassLoader>, List<ClassLoader>> sharedLibraries =
+                    createSharedLibrariesLoaders(mApplicationInfo.sharedLibraryInfos, isBundledApp,
+                            librarySearchPath, libraryPermittedPath);
 
             List<String> nativeSharedLibraries = new ArrayList<>();
             if (mApplicationInfo.sharedLibraryInfos != null) {
@@ -971,7 +999,8 @@
             mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
                     zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                     libraryPermittedPath, mBaseClassLoader,
-                    mApplicationInfo.classLoaderName, sharedLibraries, nativeSharedLibraries);
+                    mApplicationInfo.classLoaderName, sharedLibraries.first, nativeSharedLibraries,
+                    sharedLibraries.second);
             mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader);
 
             setThreadPolicy(oldPolicy);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 32ea41b..e2fd359 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1914,39 +1914,6 @@
         public abstract T createService() throws ServiceNotFoundException;
     }
 
-    /**
-     * Like StaticServiceFetcher, creates only one instance of the service per application, but when
-     * creating the service for the first time, passes it the application context of the creating
-     * application.
-     *
-     * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the
-     * case where multiple application components each have their own ConnectivityManager object.
-     */
-    static abstract class StaticApplicationContextServiceFetcher<T> implements ServiceFetcher<T> {
-        private T mCachedInstance;
-
-        @Override
-        public final T getService(ContextImpl ctx) {
-            synchronized (StaticApplicationContextServiceFetcher.this) {
-                if (mCachedInstance == null) {
-                    Context appContext = ctx.getApplicationContext();
-                    // If the application context is null, we're either in the system process or
-                    // it's the application context very early in app initialization. In both these
-                    // cases, the passed-in ContextImpl will not be freed, so it's safe to pass it
-                    // to the service. http://b/27532714 .
-                    try {
-                        mCachedInstance = createService(appContext != null ? appContext : ctx);
-                    } catch (ServiceNotFoundException e) {
-                        onServiceNotFound(e);
-                    }
-                }
-                return mCachedInstance;
-            }
-        }
-
-        public abstract T createService(Context applicationContext) throws ServiceNotFoundException;
-    }
-
     /** @hide */
     public static void onServiceNotFound(ServiceNotFoundException e) {
         // We're mostly interested in tracking down long-lived core system
diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
index df065bf..c17a7b4 100644
--- a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
+++ b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
@@ -16,18 +16,26 @@
 
 package android.bluetooth;
 
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Arrays;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Record of energy and activity information from controller and
  * underlying bt stack state.Timestamp the record with system
- * time
+ * time.
  *
  * @hide
  */
+@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
 public final class BluetoothActivityEnergyInfo implements Parcelable {
     private final long mTimestamp;
     private int mBluetoothStackState;
@@ -35,13 +43,24 @@
     private long mControllerRxTimeMs;
     private long mControllerIdleTimeMs;
     private long mControllerEnergyUsed;
-    private UidTraffic[] mUidTraffic;
+    private List<UidTraffic> mUidTraffic;
+
+    /** @hide */
+    @IntDef(prefix = { "BT_STACK_STATE_" }, value = {
+            BT_STACK_STATE_INVALID,
+            BT_STACK_STATE_STATE_ACTIVE,
+            BT_STACK_STATE_STATE_SCANNING,
+            BT_STACK_STATE_STATE_IDLE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BluetoothStackState {}
 
     public static final int BT_STACK_STATE_INVALID = 0;
     public static final int BT_STACK_STATE_STATE_ACTIVE = 1;
     public static final int BT_STACK_STATE_STATE_SCANNING = 2;
     public static final int BT_STACK_STATE_STATE_IDLE = 3;
 
+    /** @hide */
     public BluetoothActivityEnergyInfo(long timestamp, int stackState,
             long txTime, long rxTime, long idleTime, long energyUsed) {
         mTimestamp = timestamp;
@@ -52,17 +71,18 @@
         mControllerEnergyUsed = energyUsed;
     }
 
-    @SuppressWarnings("unchecked")
-    BluetoothActivityEnergyInfo(Parcel in) {
+    /** @hide */
+    private BluetoothActivityEnergyInfo(Parcel in) {
         mTimestamp = in.readLong();
         mBluetoothStackState = in.readInt();
         mControllerTxTimeMs = in.readLong();
         mControllerRxTimeMs = in.readLong();
         mControllerIdleTimeMs = in.readLong();
         mControllerEnergyUsed = in.readLong();
-        mUidTraffic = in.createTypedArray(UidTraffic.CREATOR);
+        mUidTraffic = in.createTypedArrayList(UidTraffic.CREATOR);
     }
 
+    /** @hide */
     @Override
     public String toString() {
         return "BluetoothActivityEnergyInfo{"
@@ -72,11 +92,11 @@
                 + " mControllerRxTimeMs=" + mControllerRxTimeMs
                 + " mControllerIdleTimeMs=" + mControllerIdleTimeMs
                 + " mControllerEnergyUsed=" + mControllerEnergyUsed
-                + " mUidTraffic=" + Arrays.toString(mUidTraffic)
+                + " mUidTraffic=" + mUidTraffic
                 + " }";
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR =
+    public static final @NonNull Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR =
             new Parcelable.Creator<BluetoothActivityEnergyInfo>() {
                 public BluetoothActivityEnergyInfo createFromParcel(Parcel in) {
                     return new BluetoothActivityEnergyInfo(in);
@@ -87,9 +107,8 @@
                 }
             };
 
-
+    /** @hide */
     @Override
-    @SuppressWarnings("unchecked")
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(mTimestamp);
         out.writeInt(mBluetoothStackState);
@@ -97,17 +116,21 @@
         out.writeLong(mControllerRxTimeMs);
         out.writeLong(mControllerIdleTimeMs);
         out.writeLong(mControllerEnergyUsed);
-        out.writeTypedArray(mUidTraffic, flags);
+        out.writeTypedList(mUidTraffic);
     }
 
+    /** @hide */
     @Override
     public int describeContents() {
         return 0;
     }
 
     /**
-     * @return bt stack reported state
+     * Get the Bluetooth stack state associated with the energy info.
+     *
+     * @return one of {@link #BluetoothStackState} states
      */
+    @BluetoothStackState
     public int getBluetoothStackState() {
         return mBluetoothStackState;
     }
@@ -134,7 +157,7 @@
     }
 
     /**
-     * product of current(mA), voltage(V) and time(ms)
+     * Get the product of current (mA), voltage (V), and time (ms).
      *
      * @return energy used
      */
@@ -143,22 +166,31 @@
     }
 
     /**
-     * @return timestamp(real time elapsed in milliseconds since boot) of record creation.
+     * @return timestamp (real time elapsed in milliseconds since boot) of record creation
      */
-    public long getTimeStamp() {
+    public @ElapsedRealtimeLong long getTimestampMillis() {
         return mTimestamp;
     }
 
-    public UidTraffic[] getUidTraffic() {
+    /**
+     * Get the {@link List} of each application {@link android.bluetooth.UidTraffic}.
+     *
+     * @return current {@link List} of {@link android.bluetooth.UidTraffic}
+     */
+    public @NonNull List<UidTraffic> getUidTraffic() {
+        if (mUidTraffic == null) {
+            return Collections.emptyList();
+        }
         return mUidTraffic;
     }
 
-    public void setUidTraffic(UidTraffic[] traffic) {
+    /** @hide */
+    public void setUidTraffic(List<UidTraffic> traffic) {
         mUidTraffic = traffic;
     }
 
     /**
-     * @return if the record is valid
+     * @return true if the record Tx time, Rx time, and Idle time are more than 0.
      */
     public boolean isValid() {
         return ((mControllerTxTimeMs >= 0) && (mControllerRxTimeMs >= 0)
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 06ce053..dac8ffe 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2272,6 +2272,66 @@
         return false;
     }
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            BluetoothStatusCodes.SUCCESS,
+            BluetoothStatusCodes.ERROR_UNKNOWN,
+            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+            BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED,
+    })
+    public @interface LeFeatureReturnValues {}
+
+    /**
+     * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Connected Isochronous Stream Central
+     * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
+     * the feature is not supported or an error code.
+     *
+     * @return whether the chipset supports the LE Connected Isochronous Stream Central feature
+     */
+    @RequiresNoPermission
+    public @LeFeatureReturnValues int isCisCentralSupported() {
+        if (!getLeAccess()) {
+            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) {
+                return mService.isCisCentralSupported();
+            }
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return BluetoothStatusCodes.ERROR_UNKNOWN;
+    }
+
+    /**
+     * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
+     * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
+     * feature is not supported or an error code
+     *
+     * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
+     */
+    @RequiresNoPermission
+    public @LeFeatureReturnValues int isLePeriodicAdvertisingSyncTransferSenderSupported() {
+        if (!getLeAccess()) {
+            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) {
+                return mService.isLePeriodicAdvertisingSyncTransferSenderSupported();
+            }
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return BluetoothStatusCodes.ERROR_UNKNOWN;
+    }
+
     /**
      * Return the maximum LE advertising data length in bytes,
      * if LE Extended Advertising feature is supported, 0 otherwise.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 9caeb29..6e918bd 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1186,6 +1186,11 @@
         mAttributionSource = attributionSource;
     }
 
+    /** {@hide} */
+    public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
+        setAttributionSource(attributionSource);
+    }
+
     @Override
     public boolean equals(@Nullable Object o) {
         if (o instanceof BluetoothDevice) {
@@ -1335,7 +1340,10 @@
             if (alias == null) {
                 return getName();
             }
-            return alias;
+            return alias
+                    .replace('\t', ' ')
+                    .replace('\n', ' ')
+                    .replace('\r', ' ');
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index ca898bd..4e7c01a 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,6 +16,8 @@
 
 package android.bluetooth;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresNoPermission;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
@@ -29,6 +31,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
@@ -140,27 +144,6 @@
     public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
 
     /**
-     * A GATT writeCharacteristic request is started successfully.
-     *
-     * @hide
-     */
-    public static final int GATT_WRITE_REQUEST_SUCCESS = 0;
-
-    /**
-     * A GATT writeCharacteristic request failed to start.
-     *
-     * @hide
-     */
-    public static final int GATT_WRITE_REQUEST_FAIL = 1;
-
-    /**
-     * A GATT writeCharacteristic request is issued to a busy remote device.
-     *
-     * @hide
-     */
-    public static final int GATT_WRITE_REQUEST_BUSY = 2;
-
-    /**
      * No authentication required.
      *
      * @hide
@@ -430,6 +413,9 @@
                             if (callback != null) {
                                 if (status == 0) characteristic.setValue(value);
                                 callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
+                                        value, status);
+                                // Keep calling deprecated callback to maintain app compatibility
+                                callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
                                         status);
                             }
                         }
@@ -443,7 +429,8 @@
                  */
                 @Override
                 @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onCharacteristicWrite(String address, int status, int handle) {
+                public void onCharacteristicWrite(String address, int status, int handle,
+                        byte[] value) {
                     if (VDBG) {
                         Log.d(TAG, "onCharacteristicWrite() - Device=" + address
                                 + " handle=" + handle + " Status=" + status);
@@ -467,12 +454,13 @@
                         try {
                             final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
                                     ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
-                            int requestStatus = GATT_WRITE_REQUEST_FAIL;
+                            int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
                             for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
                                 requestStatus =  mService.writeCharacteristic(mClientIf, address,
                                                   handle, characteristic.getWriteType(), authReq,
-                                                  characteristic.getValue(), mAttributionSource);
-                                if (requestStatus != GATT_WRITE_REQUEST_BUSY) {
+                                                  value, mAttributionSource);
+                                if (requestStatus
+                                        != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
                                     break;
                                 }
                                 try {
@@ -488,7 +476,6 @@
                     }
 
                     mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
                     runOrQueueCallback(new Runnable() {
                         @Override
                         public void run() {
@@ -525,6 +512,9 @@
                             if (callback != null) {
                                 characteristic.setValue(value);
                                 callback.onCharacteristicChanged(BluetoothGatt.this,
+                                        characteristic, value);
+                                // Keep calling deprecated callback to maintain app compatibility
+                                callback.onCharacteristicChanged(BluetoothGatt.this,
                                         characteristic);
                             }
                         }
@@ -578,6 +568,9 @@
                             final BluetoothGattCallback callback = mCallback;
                             if (callback != null) {
                                 if (status == 0) descriptor.setValue(value);
+                                callback.onDescriptorRead(BluetoothGatt.this, descriptor, status,
+                                        value);
+                                // Keep calling deprecated callback to maintain app compatibility
                                 callback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
                             }
                         }
@@ -590,7 +583,8 @@
                  */
                 @Override
                 @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onDescriptorWrite(String address, int status, int handle) {
+                public void onDescriptorWrite(String address, int status, int handle,
+                        byte[] value) {
                     if (VDBG) {
                         Log.d(TAG,
                                 "onDescriptorWrite() - Device=" + address + " handle=" + handle);
@@ -614,7 +608,7 @@
                             final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
                                     ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
                             mService.writeDescriptor(mClientIf, address, handle,
-                                    authReq, descriptor.getValue(), mAttributionSource);
+                                    authReq, value, mAttributionSource);
                             mAuthRetryState++;
                             return;
                         } catch (RemoteException e) {
@@ -1194,8 +1188,8 @@
      * Reads the requested characteristic from the associated remote device.
      *
      * <p>This is an asynchronous operation. The result of the read operation
-     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
-     * callback.
+     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
+     * BluetoothGattCharacteristic, byte[], int)} callback.
      *
      * @param characteristic Characteristic to read from the remote device
      * @return true, if the read operation was initiated successfully
@@ -1240,8 +1234,8 @@
      * Reads the characteristic using its UUID from the associated remote device.
      *
      * <p>This is an asynchronous operation. The result of the read operation
-     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
-     * callback.
+     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
+     * BluetoothGattCharacteristic, byte[], int)} callback.
      *
      * @param uuid UUID of characteristic to read from the remote device
      * @return true, if the read operation was initiated successfully
@@ -1284,40 +1278,94 @@
      *
      * @param characteristic Characteristic to write on the remote device
      * @return true, if the write operation was initiated successfully
+     * @throws IllegalArgumentException if characteristic or its value are null
+     *
+     * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[],
+     * int)} as this is not memory safe.
      */
+    @Deprecated
     @RequiresLegacyBluetoothPermission
     @RequiresBluetoothConnectPermission
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
     public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
+        try {
+            return writeCharacteristic(characteristic, characteristic.getValue(),
+                    characteristic.getWriteType()) == BluetoothStatusCodes.SUCCESS;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            BluetoothStatusCodes.SUCCESS,
+            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
+            BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
+            BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+            BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
+            BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
+            BluetoothStatusCodes.ERROR_UNKNOWN
+    })
+    public @interface WriteOperationReturnValues{}
+
+    /**
+     * Writes a given characteristic and its values to the associated remote device.
+     *
+     * <p>Once the write operation has been completed, the
+     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
+     * reporting the result of the operation.
+     *
+     * @param characteristic Characteristic to write on the remote device
+     * @return whether the characteristic was successfully written to
+     * @throws IllegalArgumentException if characteristic or value are null
+     */
+    @RequiresBluetoothConnectPermission
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+    @WriteOperationReturnValues
+    public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic,
+            @NonNull byte[] value, int writeType) {
+        if (characteristic == null) {
+            throw new IllegalArgumentException("characteristic must not be null");
+        }
+        if (value == null) {
+            throw new IllegalArgumentException("value must not be null");
+        }
+        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
         if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
                 && (characteristic.getProperties()
                 & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
-            return false;
+            return BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED;
+        }
+        if (mService == null || mClientIf == 0) {
+            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
         }
 
-        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
-        if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
-
         BluetoothGattService service = characteristic.getService();
-        if (service == null) return false;
+        if (service == null) {
+            throw new IllegalArgumentException("Characteristic must have a non-null service");
+        }
 
         BluetoothDevice device = service.getDevice();
-        if (device == null) return false;
+        if (device == null) {
+            throw new IllegalArgumentException("Service must have a non-null device");
+        }
 
         synchronized (mDeviceBusyLock) {
             if (mDeviceBusy) {
-                return false;
+                return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
             }
             mDeviceBusy = true;
         }
 
-        int requestStatus = GATT_WRITE_REQUEST_FAIL;
+        int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
         try {
             for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
                 requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(),
-                    characteristic.getInstanceId(), characteristic.getWriteType(),
-                    AUTHENTICATION_NONE, characteristic.getValue(), mAttributionSource);
-                if (requestStatus != GATT_WRITE_REQUEST_BUSY) {
+                        characteristic.getInstanceId(), writeType, AUTHENTICATION_NONE, value,
+                        mAttributionSource);
+                if (requestStatus != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
                     break;
                 }
                 try {
@@ -1330,10 +1378,10 @@
             synchronized (mDeviceBusyLock) {
                 mDeviceBusy = false;
             }
-            return false;
+            throw e.rethrowFromSystemServer();
         }
 
-        return requestStatus == GATT_WRITE_REQUEST_SUCCESS;
+        return requestStatus;
     }
 
     /**
@@ -1384,45 +1432,86 @@
     /**
      * Write the value of a given descriptor to the associated remote device.
      *
-     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
-     * triggered to report the result of the write operation.
+     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
+     * result of the write operation.
      *
      * @param descriptor Descriptor to write to the associated remote device
      * @return true, if the write operation was initiated successfully
+     * @throws IllegalArgumentException if descriptor or its value are null
+     *
+     * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as
+     * this is not memory safe.
      */
+    @Deprecated
     @RequiresLegacyBluetoothPermission
     @RequiresBluetoothConnectPermission
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
     public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
+        try {
+            return writeDescriptor(descriptor, descriptor.getValue())
+                    == BluetoothStatusCodes.SUCCESS;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Write the value of a given descriptor to the associated remote device.
+     *
+     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
+     * result of the write operation.
+     *
+     * @param descriptor Descriptor to write to the associated remote device
+     * @return true, if the write operation was initiated successfully
+     * @throws IllegalArgumentException if descriptor or value are null
+     */
+    @RequiresBluetoothConnectPermission
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+    @WriteOperationReturnValues
+    public int writeDescriptor(@NonNull BluetoothGattDescriptor descriptor,
+            @NonNull byte[] value) {
+        if (descriptor == null) {
+            throw new IllegalArgumentException("descriptor must not be null");
+        }
+        if (value == null) {
+            throw new IllegalArgumentException("value must not be null");
+        }
         if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
-        if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false;
+        if (mService == null || mClientIf == 0) {
+            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+        }
 
         BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
-        if (characteristic == null) return false;
+        if (characteristic == null) {
+            throw new IllegalArgumentException("Descriptor must have a non-null characteristic");
+        }
 
         BluetoothGattService service = characteristic.getService();
-        if (service == null) return false;
+        if (service == null) {
+            throw new IllegalArgumentException("Characteristic must have a non-null service");
+        }
 
         BluetoothDevice device = service.getDevice();
-        if (device == null) return false;
+        if (device == null) {
+            throw new IllegalArgumentException("Service must have a non-null device");
+        }
 
         synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) return false;
+            if (mDeviceBusy) return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
             mDeviceBusy = true;
         }
 
         try {
-            mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(),
-                    AUTHENTICATION_NONE, descriptor.getValue(), mAttributionSource);
+            return mService.writeDescriptor(mClientIf, device.getAddress(),
+                    descriptor.getInstanceId(), AUTHENTICATION_NONE, value, mAttributionSource);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
             synchronized (mDeviceBusyLock) {
                 mDeviceBusy = false;
             }
-            return false;
+            e.rethrowFromSystemServer();
         }
-
-        return true;
+        return BluetoothStatusCodes.ERROR_UNKNOWN;
     }
 
     /**
@@ -1431,9 +1520,9 @@
      * <p>Once a reliable write transaction has been initiated, all calls
      * to {@link #writeCharacteristic} are sent to the remote device for
      * verification and queued up for atomic execution. The application will
-     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
-     * in response to every {@link #writeCharacteristic} call and is responsible
-     * for verifying if the value has been transmitted accurately.
+     * receive a {@link BluetoothGattCallback#onCharacteristicWrite} callback in response to every
+     * {@link #writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} call and is
+     * responsible for verifying if the value has been transmitted accurately.
      *
      * <p>After all characteristics have been queued up and verified,
      * {@link #executeReliableWrite} will execute all writes. If a characteristic
@@ -1530,9 +1619,9 @@
      * Enable or disable notifications/indications for a given characteristic.
      *
      * <p>Once notifications are enabled for a characteristic, a
-     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
-     * triggered if the remote device indicates that the given characteristic
-     * has changed.
+     * {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
+     * BluetoothGattCharacteristic, byte[])} callback will be triggered if the remote device
+     * indicates that the given characteristic has changed.
      *
      * @param characteristic The characteristic for which to enable notifications
      * @param enable Set to true to enable notifications/indications
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 1c40cff..d0a5a1e 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -80,16 +80,34 @@
     /**
      * Callback reporting the result of a characteristic read operation.
      *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
+     * @param gatt           GATT client invoked
+     *                       {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
      * @param characteristic Characteristic that was read from the associated remote device.
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
-     * successfully.
+     * @param status         {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+     *                       successfully.
+     * @deprecated Use {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
+     * BluetoothGattCharacteristic, byte[], int)} as it is memory safe
      */
+    @Deprecated
     public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
             int status) {
     }
 
     /**
+     * Callback reporting the result of a characteristic read operation.
+     *
+     * @param gatt           GATT client invoked
+     *                       {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
+     * @param characteristic Characteristic that was read from the associated remote device.
+     * @param value          the value of the characteristic
+     * @param status         {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+     *                       successfully.
+     */
+    public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull
+            BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) {
+    }
+
+    /**
      * Callback indicating the result of a characteristic write operation.
      *
      * <p>If this callback is invoked while a reliable write transaction is
@@ -98,10 +116,13 @@
      * value to the desired value to be written. If the values don't match,
      * the application must abort the reliable write transaction.
      *
-     * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
+     * @param gatt           GATT client that invoked
+     *                       {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic,
+     *                       byte[], int)}
      * @param characteristic Characteristic that was written to the associated remote device.
-     * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
-     * operation succeeds.
+     * @param status         The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if
+     *                       the
+     *                       operation succeeds.
      */
     public void onCharacteristicWrite(BluetoothGatt gatt,
             BluetoothGattCharacteristic characteristic, int status) {
@@ -110,33 +131,68 @@
     /**
      * Callback triggered as a result of a remote characteristic notification.
      *
-     * @param gatt GATT client the characteristic is associated with
+     * @param gatt           GATT client the characteristic is associated with
      * @param characteristic Characteristic that has been updated as a result of a remote
-     * notification event.
+     *                       notification event.
+     * @deprecated Use {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
+     * BluetoothGattCharacteristic, byte[])} as it is memory safe by providing the characteristic
+     * value at the time of notification.
      */
+    @Deprecated
     public void onCharacteristicChanged(BluetoothGatt gatt,
             BluetoothGattCharacteristic characteristic) {
     }
 
     /**
+     * Callback triggered as a result of a remote characteristic notification. Note that the value
+     * within the characteristic object may have changed since receiving the remote characteristic
+     * notification, so check the parameter value for the value at the time of notification.
+     *
+     * @param gatt           GATT client the characteristic is associated with
+     * @param characteristic Characteristic that has been updated as a result of a remote
+     *                       notification event.
+     * @param value          notified characteristic value
+     */
+    public void onCharacteristicChanged(@NonNull BluetoothGatt gatt,
+            @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
+    }
+
+    /**
      * Callback reporting the result of a descriptor read operation.
      *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
+     * @param gatt       GATT client invoked {@link BluetoothGatt#readDescriptor}
      * @param descriptor Descriptor that was read from the associated remote device.
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
-     * successfully
+     * @param status     {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+     *                   successfully
+     * @deprecated Use {@link BluetoothGattCallback#onDescriptorRead(BluetoothGatt,
+     * BluetoothGattDescriptor, int, byte[])} as it is memory safe by providing the descriptor
+     * value at the time it was read.
      */
+    @Deprecated
     public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
             int status) {
     }
 
     /**
+     * Callback reporting the result of a descriptor read operation.
+     *
+     * @param gatt       GATT client invoked {@link BluetoothGatt#readDescriptor}
+     * @param descriptor Descriptor that was read from the associated remote device.
+     * @param status     {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+     *                   successfully
+     * @param value      the descriptor value at the time of the read operation
+     */
+    public void onDescriptorRead(@NonNull BluetoothGatt gatt,
+            @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) {
+    }
+
+    /**
      * Callback indicating the result of a descriptor write operation.
      *
-     * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
+     * @param gatt       GATT client invoked {@link BluetoothGatt#writeDescriptor}
      * @param descriptor Descriptor that was writte to the associated remote device.
-     * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
-     * operation succeeds.
+     * @param status     The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
+     *                   operation succeeds.
      */
     public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
             int status) {
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 8a7d4ba..c5e986e 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -451,8 +451,8 @@
      * Set the write type for this characteristic
      *
      * <p>Setting the write type of a characteristic determines how the
-     * {@link BluetoothGatt#writeCharacteristic} function write this
-     * characteristic.
+     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function
+     * write this characteristic.
      *
      * @param writeType The write type to for this characteristic. Can be one of: {@link
      * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}.
@@ -504,7 +504,10 @@
      * operation or if a characteristic update notification has been received.
      *
      * @return Cached value of the characteristic
+     *
+     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} instead
      */
+    @Deprecated
     public byte[] getValue() {
         return mValue;
     }
@@ -521,7 +524,11 @@
      * @param formatType The format type used to interpret the characteristic value.
      * @param offset Offset at which the integer value can be found.
      * @return Cached value of the characteristic or null of offset exceeds value size.
+     *
+     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
+     * the characteristic value
      */
+    @Deprecated
     public Integer getIntValue(int formatType, int offset) {
         if ((offset + getTypeLen(formatType)) > mValue.length) return null;
 
@@ -558,7 +565,11 @@
      * @param offset Offset at which the float value can be found.
      * @return Cached value of the characteristic at a given offset or null if the requested offset
      * exceeds the value size.
+     *
+     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
+     * the characteristic value
      */
+    @Deprecated
     public Float getFloatValue(int formatType, int offset) {
         if ((offset + getTypeLen(formatType)) > mValue.length) return null;
 
@@ -580,7 +591,11 @@
      *
      * @param offset Offset at which the string value can be found.
      * @return Cached value of the characteristic
+     *
+     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
+     * the characteristic value
      */
+    @Deprecated
     public String getStringValue(int offset) {
         if (mValue == null || offset > mValue.length) return null;
         byte[] strBytes = new byte[mValue.length - offset];
@@ -599,7 +614,11 @@
      * @param value New value for this characteristic
      * @return true if the locally stored value has been set, false if the requested value could not
      * be stored locally.
+     *
+     * @deprecated Pass the characteristic value directly into
+     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
      */
+    @Deprecated
     public boolean setValue(byte[] value) {
         mValue = value;
         return true;
@@ -613,7 +632,11 @@
      * @param formatType Integer format type used to transform the value parameter
      * @param offset Offset at which the value should be placed
      * @return true if the locally stored value has been set
+     *
+     * @deprecated Pass the characteristic value directly into
+     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
      */
+    @Deprecated
     public boolean setValue(int value, int formatType, int offset) {
         int len = offset + getTypeLen(formatType);
         if (mValue == null) mValue = new byte[len];
@@ -660,7 +683,11 @@
      * @param formatType Float format type used to transform the value parameter
      * @param offset Offset at which the value should be placed
      * @return true if the locally stored value has been set
+     *
+     * @deprecated Pass the characteristic value directly into
+     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
      */
+    @Deprecated
     public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
         int len = offset + getTypeLen(formatType);
         if (mValue == null) mValue = new byte[len];
@@ -697,7 +724,11 @@
      *
      * @param value New value for this characteristic
      * @return true if the locally stored value has been set
+     *
+     * @deprecated Pass the characteristic value directly into
+     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
      */
+    @Deprecated
     public boolean setValue(String value) {
         mValue = value.getBytes();
         return true;
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index ed5ea08..a35d5b9 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -260,7 +260,10 @@
      * operation.
      *
      * @return Cached value of the descriptor
+     *
+     * @deprecated  Use {@link BluetoothGatt#readDescriptor(BluetoothGattDescriptor)} instead
      */
+    @Deprecated
     public byte[] getValue() {
         return mValue;
     }
@@ -276,7 +279,11 @@
      * @param value New value for this descriptor
      * @return true if the locally stored value has been set, false if the requested value could not
      * be stored locally.
+     *
+     * @deprecated Pass the descriptor value directly into
+     * {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])}
      */
+    @Deprecated
     public boolean setValue(byte[] value) {
         mValue = value;
         return true;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 83108d2..a5a2470 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -817,7 +817,7 @@
     @RequiresBluetoothConnectPermission
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
     public Bundle getCurrentAgEvents(BluetoothDevice device) {
-        if (DBG) log("getCurrentCalls()");
+        if (DBG) log("getCurrentAgEvents()");
         final IBluetoothHeadsetClient service =
                 getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index b5df4db..20152f3 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -62,15 +62,15 @@
     private static final String TAG = "BluetoothManager";
     private static final boolean DBG = false;
 
-    private static AttributionSource sAttributionSource = null;
+    private final AttributionSource mAttributionSource;
     private final BluetoothAdapter mAdapter;
 
     /**
      * @hide
      */
     public BluetoothManager(Context context) {
-        sAttributionSource = resolveAttributionSource(context);
-        mAdapter = BluetoothAdapter.createAdapter(sAttributionSource);
+        mAttributionSource = resolveAttributionSource(context);
+        mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
     }
 
     /** {@hide} */
@@ -79,9 +79,6 @@
         if (context != null) {
             res = context.getAttributionSource();
         }
-        else if (sAttributionSource != null) {
-            return sAttributionSource;
-        }
         if (res == null) {
             res = ActivityThread.currentAttributionSource();
         }
@@ -201,8 +198,8 @@
             IBluetoothGatt iGatt = managerService.getBluetoothGatt();
             if (iGatt == null) return devices;
             devices = Attributable.setAttributionSource(
-                    iGatt.getDevicesMatchingConnectionStates(states, sAttributionSource),
-                    sAttributionSource);
+                    iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
+                    mAttributionSource);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index 3e46c49..ca01784 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -79,6 +79,33 @@
     public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
 
     /**
+     * Error code indicating that the caller does not have the
+     * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission
+     */
+    public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8;
+
+    /**
+     * Error code indicating that the profile service is not bound. You can bind a profile service
+     * by calling {@link BluetoothAdapter#getProfileProxy}
+     */
+    public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9;
+
+    /**
+     * Error code indicating that the feature is not supported.
+     */
+    public static final int ERROR_FEATURE_NOT_SUPPORTED = 10;
+
+    /**
+     * A GATT writeCharacteristic request is not permitted on the remote device.
+     */
+    public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101;
+
+    /**
+     * A GATT writeCharacteristic request is issued to a busy remote device.
+     */
+    public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102;
+
+    /**
      * If another application has already requested {@link OobData} then another fetch will be
      * disallowed until the callback is removed.
      *
diff --git a/core/java/android/bluetooth/UidTraffic.java b/core/java/android/bluetooth/UidTraffic.java
index 2ee786a..9982fa6 100644
--- a/core/java/android/bluetooth/UidTraffic.java
+++ b/core/java/android/bluetooth/UidTraffic.java
@@ -15,6 +15,7 @@
  */
 package android.bluetooth;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -23,27 +24,27 @@
  *
  * @hide
  */
-public class UidTraffic implements Cloneable, Parcelable {
+@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
+public final class UidTraffic implements Cloneable, Parcelable {
     private final int mAppUid;
     private long mRxBytes;
     private long mTxBytes;
 
-    public UidTraffic(int appUid) {
-        mAppUid = appUid;
-    }
-
+    /** @hide */
     public UidTraffic(int appUid, long rx, long tx) {
         mAppUid = appUid;
         mRxBytes = rx;
         mTxBytes = tx;
     }
 
-    UidTraffic(Parcel in) {
+    /** @hide */
+    private UidTraffic(Parcel in) {
         mAppUid = in.readInt();
         mRxBytes = in.readLong();
         mTxBytes = in.readLong();
     }
 
+    /** @hide */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mAppUid);
@@ -51,44 +52,60 @@
         dest.writeLong(mTxBytes);
     }
 
+    /** @hide */
     public void setRxBytes(long bytes) {
         mRxBytes = bytes;
     }
 
+    /** @hide */
     public void setTxBytes(long bytes) {
         mTxBytes = bytes;
     }
 
+    /** @hide */
     public void addRxBytes(long bytes) {
         mRxBytes += bytes;
     }
 
+    /** @hide */
     public void addTxBytes(long bytes) {
         mTxBytes += bytes;
     }
 
+    /**
+     * @return corresponding app Uid
+     */
     public int getUid() {
         return mAppUid;
     }
 
+    /**
+     * @return rx bytes count
+     */
     public long getRxBytes() {
         return mRxBytes;
     }
 
+    /**
+     * @return tx bytes count
+     */
     public long getTxBytes() {
         return mTxBytes;
     }
 
+    /** @hide */
     @Override
     public int describeContents() {
         return 0;
     }
 
+    /** @hide */
     @Override
     public UidTraffic clone() {
         return new UidTraffic(mAppUid, mRxBytes, mTxBytes);
     }
 
+    /** @hide */
     @Override
     public String toString() {
         return "UidTraffic{mAppUid=" + mAppUid + ", mRxBytes=" + mRxBytes + ", mTxBytes="
diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java
index 6381f55..ed50b09 100644
--- a/core/java/android/bluetooth/le/BluetoothLeUtils.java
+++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java
@@ -24,6 +24,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.UUID;
 
 /**
  * Helper class for Bluetooth LE utils.
@@ -137,4 +138,21 @@
         }
     }
 
+    /**
+     * Compares two UUIDs with a UUID mask.
+     *
+     * @param data first {@link #UUID} to compare.
+     * @param uuid second {@link #UUID} to compare.
+     * @param mask mask {@link #UUID}.
+     * @return true if both UUIDs are equals when masked, false otherwise.
+     */
+    static boolean maskedEquals(UUID data, UUID uuid, UUID mask) {
+        if (mask == null) {
+            return Objects.equals(data, uuid);
+        }
+        return (data.getLeastSignificantBits() & mask.getLeastSignificantBits())
+                == (uuid.getLeastSignificantBits() & mask.getLeastSignificantBits())
+                && (data.getMostSignificantBits() & mask.getMostSignificantBits())
+                == (uuid.getMostSignificantBits() & mask.getMostSignificantBits());
+    }
 }
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 8ff0181..b059193 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -28,8 +28,6 @@
 import android.os.ParcelUuid;
 import android.os.Parcelable;
 
-import com.android.internal.util.BitUtils;
-
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -448,7 +446,7 @@
 
     // Check if the uuid pattern matches the particular service uuid.
     private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
-        return BitUtils.maskedEquals(data, uuid, mask);
+        return BluetoothLeUtils.maskedEquals(data, uuid, mask);
     }
 
     /**
@@ -478,7 +476,7 @@
     // Check if the solicitation uuid pattern matches the particular service solicitation uuid.
     private static boolean matchesServiceSolicitationUuid(UUID solicitationUuid,
             UUID solicitationUuidMask, UUID data) {
-        return BitUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
+        return BluetoothLeUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
     }
 
     // Check whether the data pattern matches the parsed data.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2fd437d..e781c2f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -31,6 +31,7 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.AppGlobals;
+import android.bluetooth.BluetoothDevice;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -1146,6 +1147,10 @@
      * numbers.  Applications can <strong>dial</strong> emergency numbers using
      * {@link #ACTION_DIAL}, however.
      *
+     * <p>Note: An app filling the {@link android.app.role.RoleManager#ROLE_DIALER} role should use
+     * {@link android.telecom.TelecomManager#placeCall(Uri, Bundle)} to place calls rather than
+     * relying on this intent.
+     *
      * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M}
      * and above and declares as using the {@link android.Manifest.permission#CALL_PHONE}
      * permission which is not granted, then attempting to use this action will
@@ -11461,6 +11466,16 @@
         if (fromProtectedComponent) {
             mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
         }
+
+        // Special attribution fix-up logic for any BluetoothDevice extras
+        // passed via Bluetooth intents
+        if (mAction != null && mAction.startsWith("android.bluetooth.")
+                && hasExtra(BluetoothDevice.EXTRA_DEVICE)) {
+            final BluetoothDevice device = getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+            if (device != null) {
+                device.prepareToEnterProcess(source);
+            }
+        }
     }
 
     /** @hide */
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index c7f92c9..660368a 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -2,11 +2,9 @@
 per-file Context.java = *
 per-file ContextWrapper.java = *
 per-file Content* = file:/services/core/java/com/android/server/am/OWNERS
-per-file IntentFilter.java = toddke@google.com
-per-file IntentFilter.java = patb@google.com
+per-file IntentFilter.java = file:/PACKAGE_MANAGER_OWNERS
 per-file IntentFilter.java = file:/services/core/java/com/android/server/am/OWNERS
-per-file Intent.java = toddke@google.com
-per-file Intent.java = patb@google.com
+per-file Intent.java = file:/PACKAGE_MANAGER_OWNERS
 per-file Intent.java = file:/services/core/java/com/android/server/wm/OWNERS
 per-file Intent.java = file:/services/core/java/com/android/server/am/OWNERS
 per-file AutofillOptions* = file:/core/java/android/service/autofill/OWNERS
diff --git a/core/java/android/content/om/OWNERS b/core/java/android/content/om/OWNERS
index 91a0abf..3669817 100644
--- a/core/java/android/content/om/OWNERS
+++ b/core/java/android/content/om/OWNERS
@@ -3,4 +3,4 @@
 toddke@android.com
 toddke@google.com
 patb@google.com
-rtmitchell@google.com
+zyy@google.com
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
index bc2355c..d12d920 100644
--- a/core/java/android/content/res/OWNERS
+++ b/core/java/android/content/res/OWNERS
@@ -3,4 +3,4 @@
 toddke@android.com
 toddke@google.com
 patb@google.com
-rtmitchell@google.com
+zyy@google.com
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 7ef5bac..8605248 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -232,11 +232,10 @@
         ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO);
         ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO);
 
-        // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined
-        ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1);
+        ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S);
+        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S);
+        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S);
+        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S);
     }
 
     private static final Set<String> ENABLED_ALGOS =
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 1d07a03..eb8f43e 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -220,8 +220,10 @@
         String networkId = null;
         boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
-        boolean metered = !snapshot.getNetworkCapabilities().hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        boolean metered = !(snapshot.getNetworkCapabilities().hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+                || snapshot.getNetworkCapabilities().hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
 
         final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
 
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 08f75df..ee24084 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -160,19 +160,19 @@
     }
 
     /**
-     * Template to match cellular networks with the given IMSI and {@code ratType}.
-     * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
-     * See {@code TelephonyManager.NETWORK_TYPE_*}.
+     * Template to match cellular networks with the given IMSI, {@code ratType} and
+     * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
+     * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
      */
     public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
-            @NetworkType int ratType) {
+            @NetworkType int ratType, int metered) {
         if (TextUtils.isEmpty(subscriberId)) {
             return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
-                    METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+                    metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
                     SUBSCRIBER_ID_MATCH_RULE_EXACT);
         }
         return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
-                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+                metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
                 SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
@@ -305,6 +305,7 @@
         }
     }
 
+    // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
     @UnsupportedAppUsage
     public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
         this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
@@ -312,9 +313,14 @@
 
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String networkId) {
-        this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT);
+        // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
+        // to metered networks. It is now possible to match mobile with any meteredness, but
+        // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
+        //constructor passes METERED_YES for these types.
+        this(matchRule, subscriberId, matchSubscriberIds, networkId,
+                (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES
+                : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+                OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
     // TODO: Remove it after updating all of the caller.
@@ -589,11 +595,7 @@
             // TODO: consider matching against WiMAX subscriber identity
             return true;
         } else {
-            // Only metered mobile network would be matched regardless of metered filter.
-            // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
-            // TODO: Respect metered filter and remove mMetered condition.
-            return (ident.mType == TYPE_MOBILE && ident.mMetered)
-                    && !ArrayUtils.isEmpty(mMatchSubscriberIds)
+            return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds)
                     && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
                     && matchesCollapsedRatType(ident);
         }
@@ -707,8 +709,7 @@
         if (ident.mType == TYPE_WIMAX) {
             return true;
         } else {
-            return (ident.mType == TYPE_MOBILE && ident.mMetered)
-                    && matchesCollapsedRatType(ident);
+            return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident);
         }
     }
 
@@ -776,8 +777,8 @@
     }
 
     /**
-     * Examine the given template and normalize if it refers to a "merged"
-     * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+     * Examine the given template and normalize it.
+     * We pick the "lowest" merged subscriber as the primary
      * for key purposes, and expand the template to match all other merged
      * subscribers.
      * <p>
@@ -792,8 +793,8 @@
     }
 
     /**
-     * Examine the given template and normalize if it refers to a "merged"
-     * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+     * Examine the given template and normalize it.
+     * We pick the "lowest" merged subscriber as the primary
      * for key purposes, and expand the template to match all other merged
      * subscribers.
      *
@@ -805,7 +806,12 @@
      * A, but also matches B.
      */
     public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
-        if (!template.isMatchRuleMobile()) return template;
+        // Now there are several types of network which uses SubscriberId to store network
+        // information. For instances:
+        // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
+        // The TYPE_CARRIER means that the network associate to specific carrier network.
+
+        if (template.mSubscriberId == null) return template;
 
         for (String[] merged : mergedList) {
             if (ArrayUtils.contains(merged, template.mSubscriberId)) {
diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
index 09f5283..be57372 100644
--- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
+++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
@@ -79,6 +79,7 @@
         IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH);
         IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_MOBIKE);
         IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500);
+        IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT);
     }
 
     /** Serializes an IkeSessionParams to a PersistableBundle. */
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 2a344f6..ad3de25 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -103,7 +103,7 @@
      * are unparcelled, mParcelledData willbe set to null.
      */
     @UnsupportedAppUsage
-    Parcel mParcelledData = null;
+    volatile Parcel mParcelledData = null;
 
     /**
      * Whether {@link #mParcelledData} was generated by native code or not.
@@ -182,13 +182,56 @@
      * @param b a Bundle to be copied.
      */
     BaseBundle(BaseBundle b) {
-        copyInternal(b, false);
+        this(b, /* deep */ false);
     }
 
     /**
-     * Special constructor that does not initialize the bundle.
+     * Constructs a {@link BaseBundle} containing a copy of {@code from}.
+     *
+     * @param from The bundle to be copied.
+     * @param deep Whether is a deep or shallow copy.
+     *
+     * @hide
      */
-    BaseBundle(boolean doInit) {
+    BaseBundle(BaseBundle from, boolean deep) {
+        synchronized (from) {
+            mClassLoader = from.mClassLoader;
+
+            if (from.mMap != null) {
+                if (!deep) {
+                    mMap = new ArrayMap<>(from.mMap);
+                } else {
+                    final ArrayMap<String, Object> fromMap = from.mMap;
+                    final int n = fromMap.size();
+                    mMap = new ArrayMap<>(n);
+                    for (int i = 0; i < n; i++) {
+                        mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
+                    }
+                }
+            } else {
+                mMap = null;
+            }
+
+            final Parcel parcelledData;
+            if (from.mParcelledData != null) {
+                if (from.isEmptyParcel()) {
+                    parcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
+                    mParcelledByNative = false;
+                } else {
+                    parcelledData = Parcel.obtain();
+                    parcelledData.appendFrom(from.mParcelledData, 0,
+                            from.mParcelledData.dataSize());
+                    parcelledData.setDataPosition(0);
+                    mParcelledByNative = from.mParcelledByNative;
+                }
+            } else {
+                parcelledData = null;
+                mParcelledByNative = false;
+            }
+
+            // Keep as last statement to ensure visibility of other fields
+            mParcelledData = parcelledData;
+        }
     }
 
     /**
@@ -323,8 +366,8 @@
             } else {
                 mMap.erase();
             }
-            mParcelledData = null;
             mParcelledByNative = false;
+            mParcelledData = null;
             return;
         }
 
@@ -358,8 +401,8 @@
             if (recycleParcel) {
                 recycleParcel(parcelledData);
             }
-            mParcelledData = null;
             mParcelledByNative = false;
+            mParcelledData = null;
         }
         if (DEBUG) {
             Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
@@ -501,44 +544,7 @@
         mMap.clear();
     }
 
-    void copyInternal(BaseBundle from, boolean deep) {
-        synchronized (from) {
-            if (from.mParcelledData != null) {
-                if (from.isEmptyParcel()) {
-                    mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
-                    mParcelledByNative = false;
-                } else {
-                    mParcelledData = Parcel.obtain();
-                    mParcelledData.appendFrom(from.mParcelledData, 0,
-                            from.mParcelledData.dataSize());
-                    mParcelledData.setDataPosition(0);
-                    mParcelledByNative = from.mParcelledByNative;
-                }
-            } else {
-                mParcelledData = null;
-                mParcelledByNative = false;
-            }
-
-            if (from.mMap != null) {
-                if (!deep) {
-                    mMap = new ArrayMap<>(from.mMap);
-                } else {
-                    final ArrayMap<String, Object> fromMap = from.mMap;
-                    final int N = fromMap.size();
-                    mMap = new ArrayMap<>(N);
-                    for (int i = 0; i < N; i++) {
-                        mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
-                    }
-                }
-            } else {
-                mMap = null;
-            }
-
-            mClassLoader = from.mClassLoader;
-        }
-    }
-
-    Object deepCopyValue(Object value) {
+    private Object deepCopyValue(Object value) {
         if (value == null) {
             return null;
         }
@@ -570,7 +576,7 @@
         return value;
     }
 
-    ArrayList deepcopyArrayList(ArrayList from) {
+    private ArrayList deepcopyArrayList(ArrayList from) {
         final int N = from.size();
         ArrayList out = new ArrayList(N);
         for (int i=0; i<N; i++) {
@@ -1717,9 +1723,9 @@
         if (length < 0) {
             throw new RuntimeException("Bad length in parcel: " + length);
         } else if (length == 0) {
+            mParcelledByNative = false;
             // Empty Bundle or end of data.
             mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
-            mParcelledByNative = false;
             return;
         } else if (length % 4 != 0) {
             throw new IllegalStateException("Bundle length is not aligned by 4: " + length);
@@ -1757,8 +1763,8 @@
                 + ": " + length + " bundle bytes starting at " + offset);
         p.setDataPosition(0);
 
-        mParcelledData = p;
         mParcelledByNative = isNativeBundle;
+        mParcelledData = p;
     }
 
     /** {@hide} */
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 635f581..b069fb3 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -53,7 +53,7 @@
  *
  * <p>Most developers will not implement this class directly, instead using the
  * <a href="{@docRoot}guide/components/aidl.html">aidl</a> tool to describe the desired
- * interface, having it generate the appropriate Binder subclass.  You can,
+ * interface, having it generate the appropriate Binder subclass. You can,
  * however, derive directly from Binder to implement your own custom RPC
  * protocol or simply instantiate a raw Binder object directly to use as a
  * token that can be shared across processes.
@@ -63,17 +63,17 @@
  * To use this correctly, you must be doing so within the context of a top-level
  * application component (a {@link android.app.Service}, {@link android.app.Activity},
  * or {@link android.content.ContentProvider}) that lets the system know your process
- * should remain running.</p>
+ * should remain running.
  *
  * <p>You must keep in mind the situations in which your process
  * could go away, and thus require that you later re-create a new Binder and re-attach
- * it when the process starts again.  For example, if you are using this within an
+ * it when the process starts again. For example, if you are using this within an
  * {@link android.app.Activity}, your activity's process may be killed any time the
  * activity is not started; if the activity is later re-created you will need to
  * create a new Binder and hand it back to the correct place again; you need to be
  * aware that your process may be started for another reason (for example to receive
  * a broadcast) that will not involve re-creating the activity and thus run its code
- * to create a new Binder.</p>
+ * to create a new Binder.
  *
  * @see IBinder
  */
@@ -94,14 +94,15 @@
     /**
      * Value to represents that a calling work source is not set.
      *
-     * This constatnt needs to be kept in sync with IPCThreadState::kUnsetWorkSource.
+     * <p>This constant needs to be kept in sync with IPCThreadState::kUnsetWorkSource.
      *
      * @hide
      */
     public static final int UNSET_WORKSOURCE = -1;
 
     /**
-     * Control whether dump() calls are allowed.
+     * Control whether {@link #dump(FileDescriptor, PrintWriter, String[]) dump()}
+     * calls are allowed.
      */
     private static volatile String sDumpDisabled = null;
 
@@ -188,7 +189,7 @@
         sObserver = observer;
     }
 
-    /** {@hide} */
+    /** @hide */
     static volatile boolean sWarnOnBlocking = false;
 
     /**
@@ -207,8 +208,8 @@
     /**
      * Allow blocking calls on the given interface, overriding the requested
      * value of {@link #setWarnOnBlocking(boolean)}.
-     * <p>
-     * This should only be rarely called when you are <em>absolutely sure</em>
+     *
+     * <p>This should only be rarely called when you are <em>absolutely sure</em>
      * the remote interface is a built-in system component that can never be
      * upgraded. In particular, this <em>must never</em> be called for
      * interfaces hosted by package that could be upgraded or replaced,
@@ -258,7 +259,9 @@
             ThreadLocal.withInitial(() -> sWarnOnBlocking);
 
     /**
-     * Allow blocking calls for the current thread.  See {@link #allowBlocking}.
+     * Allow blocking calls for the current thread.
+     *
+     * @see {@link #allowBlocking}.
      *
      * @hide
      */
@@ -267,7 +270,9 @@
     }
 
     /**
-     * Reset the current thread to the default blocking behavior.  See {@link #defaultBlocking}.
+     * Reset the current thread to the default blocking behavior.
+     *
+     * @see {@link #defaultBlocking}.
      *
      * @hide
      */
@@ -286,10 +291,10 @@
 
     /**
      * Return the ID of the process that sent you the current transaction
-     * that is being processed.  This pid can be used with higher-level
+     * that is being processed. This PID can be used with higher-level
      * system services to determine its identity and check permissions.
      * If the current thread is not currently executing an incoming transaction,
-     * then its own pid is returned.
+     * then its own PID is returned.
      *
      * Warning: oneway transactions do not receive PID.
      */
@@ -297,11 +302,11 @@
     public static final native int getCallingPid();
 
     /**
-     * Return the Linux uid assigned to the process that sent you the
-     * current transaction that is being processed.  This uid can be used with
+     * Return the Linux UID assigned to the process that sent you the
+     * current transaction that is being processed. This UID can be used with
      * higher-level system services to determine its identity and check
-     * permissions.  If the current thread is not currently executing an
-     * incoming transaction, then its own uid is returned.
+     * permissions. If the current thread is not currently executing an
+     * incoming transaction, then its own UID is returned.
      */
     @CriticalNative
     public static final native int getCallingUid();
@@ -313,17 +318,17 @@
      * @hide
      */
     @CriticalNative
-    public static final native boolean isHandlingTransaction();
+    public static final native boolean isDirectlyHandlingTransaction();
 
     /**
-     * Return the Linux uid assigned to the process that sent the transaction
+     * Return the Linux UID assigned to the process that sent the transaction
      * currently being processed.
      *
      * @throws IllegalStateException if the current thread is not currently
-     *        executing an incoming transaction.
+     * executing an incoming transaction.
      */
     public static final int getCallingUidOrThrow() {
-        if (!isHandlingTransaction()) {
+        if (!isDirectlyHandlingTransaction()) {
             throw new IllegalStateException(
                   "Thread is not in a binder transcation");
         }
@@ -332,18 +337,20 @@
 
     /**
      * Return the UserHandle assigned to the process that sent you the
-     * current transaction that is being processed.  This is the user
-     * of the caller.  It is distinct from {@link #getCallingUid()} in that a
+     * current transaction that is being processed. This is the user
+     * of the caller. It is distinct from {@link #getCallingUid()} in that a
      * particular user will have multiple distinct apps running under it each
-     * with their own uid.  If the current thread is not currently executing an
+     * with their own UID. If the current thread is not currently executing an
      * incoming transaction, then its own UserHandle is returned.
+     *
+     * @see UserHandle
      */
     public static final @NonNull UserHandle getCallingUserHandle() {
         return UserHandle.of(UserHandle.getUserId(getCallingUid()));
     }
 
     /**
-     * Reset the identity of the incoming IPC on the current thread.  This can
+     * Reset the 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
@@ -376,10 +383,10 @@
 
     /**
      * Convenience method for running the provided action enclosed in
-     * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}
+     * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}.
      *
-     * Any exception thrown by the given action will be caught and rethrown after the call to
-     * {@link #restoreCallingIdentity}
+     * <p>Any exception thrown by the given action will be caught and
+     * rethrown after the call to {@link #restoreCallingIdentity}.
      *
      * @hide
      */
@@ -400,10 +407,10 @@
 
     /**
      * Convenience method for running the provided action enclosed in
-     * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result
+     * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result.
      *
-     * Any exception thrown by the given action will be caught and rethrown after the call to
-     * {@link #restoreCallingIdentity}
+     * <p>Any exception thrown by the given action will be caught and rethrown after
+     * the call to {@link #restoreCallingIdentity}.
      *
      * @hide
      */
@@ -428,12 +435,13 @@
      *
      * <p>The StrictMode settings are kept in two places: a Java-level
      * threadlocal for libcore/Dalvik, and a native threadlocal (set
-     * here) for propagation via Binder calls.  This is a little
+     * here) for propagation via Binder calls. This is a little
      * unfortunate, but necessary to break otherwise more unfortunate
      * dependencies either of Dalvik on Android, or Android
      * native-only code on Dalvik.
      *
      * @see StrictMode
+     *
      * @hide
      */
     @CriticalNative
@@ -443,6 +451,7 @@
      * Gets the current native thread-local StrictMode policy mask.
      *
      * @see #setThreadStrictModePolicy
+     *
      * @hide
      */
     @CriticalNative
@@ -459,7 +468,7 @@
      * reasons, we only support one UID. This UID represents the original user responsible for the
      * binder calls.
      *
-     * <p>{@link Binder#restoreCallingWorkSource(long)} must always be called after setting the
+     * <p>{@link #restoreCallingWorkSource(long)} must always be called after setting the
      * worksource.
      *
      * <p>A typical use case would be
@@ -477,16 +486,16 @@
      *
      * @param workSource The original UID responsible for the binder call.
      * @return token to restore original work source.
-     **/
+     */
     @CriticalNative
     public static final native long setCallingWorkSourceUid(int workSource);
 
     /**
      * Returns the work source set by the caller.
      *
-     * Unlike {@link Binder#getCallingUid()}, this result of this method cannot be trusted. The
+     * <p>Unlike {@link #getCallingUid()}, this result of this method cannot be trusted. The
      * caller can set the value to whatever they want. Only use this value if you trust the calling
-     * uid.
+     * UID.
      *
      * @return The original UID responsible for the binder transaction.
      */
@@ -499,7 +508,7 @@
      * <p>The work source will be propagated for future outgoing binder transactions
      * executed on this thread.
      *
-     * <p>{@link Binder#restoreCallingWorkSource(long)} must always be called after clearing the
+     * <p>{@link #restoreCallingWorkSource(long)} must always be called after clearing the
      * worksource.
      *
      * <p>A typical use case would be
@@ -513,13 +522,13 @@
      * </pre>
      *
      * @return token to restore original work source.
-     **/
+     */
     @CriticalNative
     public static final native long clearCallingWorkSource();
 
     /**
      * Restores the work source on this thread using a token returned by
-     * {@link #setCallingWorkSourceUid(int) or {@link clearCallingWorkSource()}.
+     * {@link #setCallingWorkSourceUid(int)} or {@link #clearCallingWorkSource()}.
      *
      * <p>A typical use case would be
      * <pre>
@@ -530,7 +539,7 @@
      *   Binder.restoreCallingWorkSource(token);
      * }
      * </pre>
-     **/
+     */
     @CriticalNative
     public static final native void restoreCallingWorkSource(long token);
 
@@ -553,7 +562,7 @@
      * Use a VINTF-stability binder w/o VINTF requirements. Should be called
      * on a binder before it is sent out of process.
      *
-     * This must be called before the object is sent to another process.
+     * <p>This must be called before the object is sent to another process.
      *
      * @hide
      */
@@ -561,7 +570,7 @@
 
     /**
      * Flush any Binder commands pending in the current thread to the kernel
-     * driver.  This can be
+     * driver. This can be
      * useful to call before performing an operation that may block for a long
      * time, to ensure that any pending object references have been released
      * in order to prevent the process from holding on to objects longer than
@@ -570,7 +579,7 @@
     public static final native void flushPendingCommands();
 
     /**
-     * Add the calling thread to the IPC thread pool.  This function does
+     * Add the calling thread to the IPC thread pool. This function does
      * not return until the current process is exiting.
      */
     public static final void joinThreadPool() {
@@ -579,6 +588,7 @@
 
     /**
      * Returns true if the specified interface is a proxy.
+     *
      * @hide
      */
     public static final boolean isProxy(IInterface iface) {
@@ -588,6 +598,7 @@
     /**
      * Call blocks until the number of executing binder threads is less
      * than the maximum number of binder threads allowed for this process.
+     *
      * @hide
      */
     public static final native void blockUntilThreadAvailable();
@@ -595,7 +606,7 @@
     /**
      * Default constructor just initializes the object.
      *
-     * If you're creating a Binder token (a Binder object without an attached interface),
+     * <p>If you're creating a Binder token (a Binder object without an attached interface),
      * you should use {@link #Binder(String)} instead.
      */
     public Binder() {
@@ -605,7 +616,7 @@
     /**
      * Constructor for creating a raw Binder object (token) along with a descriptor.
      *
-     * The descriptor of binder objects usually specifies the interface they are implementing.
+     * <p>The descriptor of binder objects usually specifies the interface they are implementing.
      * In case of binder tokens, no interface is implemented, and the descriptor can be used
      * as a sort of tag to help identify the binder token. This will help identify remote
      * references to these objects more easily when debugging.
@@ -614,7 +625,7 @@
      * Instead of creating multiple tokens with the same descriptor, consider adding a suffix to
      * help identify them.
      */
-    public Binder(@Nullable String descriptor)  {
+    public Binder(@Nullable String descriptor) {
         mObject = getNativeBBinderHolder();
         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
 
@@ -631,9 +642,9 @@
 
     /**
      * Convenience method for associating a specific interface with the Binder.
-     * After calling, queryLocalInterface() will be implemented for you
-     * to return the given owner IInterface when the corresponding
-     * descriptor is requested.
+     * After calling, {@link #queryLocalInterface(String) queryLocalInterface()}
+     * will be implemented for you to return the given owner IInterface when
+     * the corresponding descriptor is requested.
      */
     public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
         mOwner = owner;
@@ -666,8 +677,8 @@
     }
 
     /**
-     * Use information supplied to attachInterface() to return the
-     * associated IInterface if it matches the requested
+     * Use information supplied to {@link #attachInterface attachInterface()}
+     * to return the associated {@link IInterface} if it matches the requested
      * descriptor.
      */
     public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
@@ -678,14 +689,15 @@
     }
 
     /**
-     * Control disabling of dump calls in this process.  This is used by the system
+     * Control disabling of dump calls in this process. This is used by the system
      * process watchdog to disable incoming dump calls while it has detecting the system
-     * is hung and is reporting that back to the activity controller.  This is to
+     * is hung and is reporting that back to the activity controller. This is to
      * prevent the controller from getting hung up on bug reports at this point.
-     * @hide
      *
      * @param msg The message to show instead of the dump; if null, dumps are
      * re-enabled.
+     *
+     * @hide
      */
     public static void setDumpDisabled(String msg) {
         sDumpDisabled = msg;
@@ -694,7 +706,8 @@
     /**
      * Listener to be notified about each proxy-side binder call.
      *
-     * See {@link setProxyTransactListener}.
+     * @see {@link #setProxyTransactListener}.
+     *
      * @hide
      */
     @SystemApi
@@ -702,7 +715,8 @@
         /**
          * Called before onTransact.
          *
-         * @return an object that will be passed back to #onTransactEnded (or null).
+         * @return an object that will be passed back to {@link #onTransactEnded} (or null).,
+         *
          * @hide
          */
         @Nullable
@@ -713,15 +727,15 @@
         /**
          * Called before onTransact.
          *
-         * @return an object that will be passed back to #onTransactEnded (or null).
+         * @return an object that will be passed back to {@link #onTransactEnded} (or null).
          */
         @Nullable
         Object onTransactStarted(@NonNull IBinder binder, int transactionCode);
 
         /**
-         * Called after onTranact (even when an exception is thrown).
+         * Called after onTransact (even when an exception is thrown).
          *
-         * @param session The object return by #onTransactStarted.
+         * @param session The object return by {@link #onTransactStarted}.
          */
         void onTransactEnded(@Nullable Object session);
     }
@@ -732,16 +746,17 @@
      * <li>By default, this listener will propagate the worksource if the outgoing call happens on
      * the same thread as the incoming binder call.
      * <li>Custom attribution can be done by calling {@link ThreadLocalWorkSource#setUid(int)}.
+     *
      * @hide
      */
     public static class PropagateWorkSourceTransactListener implements ProxyTransactListener {
         @Override
         public Object onTransactStarted(IBinder binder, int transactionCode) {
-           // Note that {@link Binder#getCallingUid()} is already set to the UID of the current
-           // process when this method is called.
-           //
-           // We use ThreadLocalWorkSource instead. It also allows feature owners to set
-           // {@link ThreadLocalWorkSource#set(int) manually to attribute resources to a UID.
+            // Note that {@link #getCallingUid()} is already set to the UID of the current
+            // process when this method is called.
+            //
+            // We use {@link ThreadLocalWorkSource} instead. It also allows feature owners to set
+            // {@link ThreadLocalWorkSource#set(int)} manually to attribute resources to a UID.
             int uid = ThreadLocalWorkSource.getUid();
             if (uid != ThreadLocalWorkSource.UID_NONE) {
                 return Binder.setCallingWorkSourceUid(uid);
@@ -770,6 +785,7 @@
      * <li>The listener is called on the critical path of the binder transaction so be careful about
      * performance.
      * <li>Never execute another binder transaction inside the listener.
+     *
      * @hide
      */
     @SystemApi
@@ -778,7 +794,7 @@
     }
 
     /**
-     * Default implementation is a stub that returns false.  You will want
+     * Default implementation is a stub that returns false. You will want
      * to override this to do the appropriate unmarshalling of transactions.
      *
      * <p>If you want to call this, call transact().
@@ -786,15 +802,14 @@
      * <p>Implementations that are returning a result should generally use
      * {@link Parcel#writeNoException() Parcel.writeNoException} and
      * {@link Parcel#writeException(Exception) Parcel.writeException} to propagate
-     * exceptions back to the caller.</p>
+     * exceptions back to the caller.
      *
-     * @param code The action to perform.  This should
-     * be a number between {@link #FIRST_CALL_TRANSACTION} and
-     * {@link #LAST_CALL_TRANSACTION}.
+     * @param code The action to perform. This should be a number between
+     * {@link #FIRST_CALL_TRANSACTION} and {@link #LAST_CALL_TRANSACTION}.
      * @param data Marshalled data being received from the caller.
      * @param reply If the caller is expecting a result back, it should be marshalled
      * in to here.
-     * @param flags Additional operation flags.  Either 0 for a normal
+     * @param flags Additional operation flags. Either 0 for a normal
      * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
      *
      * @return Return true on a successful call; returning false is generally used to
@@ -856,10 +871,12 @@
      * Resolves a transaction code to a human readable name.
      *
      * <p>Default implementation is a stub that returns null.
+     *
      * <p>AIDL generated code will return the original method name.
      *
      * @param transactionCode The code to resolve.
      * @return A human readable name.
+     *
      * @hide
      */
     public @Nullable String getTransactionName(int transactionCode) {
@@ -925,7 +942,7 @@
      * Print the object's state into the given stream.
      *
      * @param fd The raw file descriptor that the dump is being sent to.
-     * @param fout The file to which you should dump your state.  This will be
+     * @param fout The file to which you should dump your state. This will be
      * closed for you after you return.
      * @param args additional arguments to the dump request.
      */
@@ -941,6 +958,7 @@
      * @param callback Callback through which to interact with the invoking shell.
      * @param resultReceiver Called when the command has finished executing, with the result code.
      * @throws RemoteException
+     *
      * @hide
      */
     public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@@ -958,7 +976,8 @@
      *
      * <p class="caution">Note: no permission checking is done before calling this method; you must
      * apply any security checks as appropriate for the command being executed.
-     * Consider using {@link ShellCommand} to help in the implementation.</p>
+     * Consider using {@link ShellCommand} to help in the implementation.
+     *
      * @hide
      */
     public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@@ -1013,7 +1032,7 @@
      * System services can implement this method to implement ADB shell commands.
      *
      * <p>A system binder service can implement it to handle shell commands on ADB. For example,
-     * the Job Scheduler service implements it to handle <code>adb shell cmd jobscheduler</code>.
+     * the Job Scheduler service implements it to handle {@code adb shell cmd jobscheduler}.
      *
      * <p>Commands are only executable by ADB shell; i.e. only {@link Process#SHELL_UID} and
      * {@link Process#ROOT_UID} can call them.
@@ -1022,8 +1041,8 @@
      * @param out standard output
      * @param err standard error
      * @param args arguments passed to the command. Can be empty. The first argument is typically
-     *             a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
-     * @return the status code returned from the <code>cmd</code> command.
+     * a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
+     * @return the status code returned from the {@code cmd} command.
      *
      * @hide
      */
@@ -1051,7 +1070,7 @@
     public final native void setExtension(@Nullable IBinder extension);
 
     /**
-     * Default implementation rewinds the parcels and calls onTransact.  On
+     * Default implementation rewinds the parcels and calls onTransact. On
      * the remote side, transact calls into the binder to do the IPC.
      */
     public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
@@ -1083,7 +1102,7 @@
 
     static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
         if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
-            // Trying to send > 800k, this is way too much
+            // Trying to send > 800k, this is way too much.
             StringBuilder sb = new StringBuilder();
             sb.append(msg);
             sb.append(": on ");
@@ -1107,7 +1126,7 @@
     private static native long getNativeBBinderHolder();
 
     /**
-     * By default, we use the calling uid since we can always trust it.
+     * By default, we use the calling UID since we can always trust it.
      */
     private static volatile BinderInternal.WorkSourceProvider sWorkSourceProvider =
             (x) -> Binder.getCallingUid();
@@ -1122,6 +1141,7 @@
      * <li>The callback is called on the critical path of the binder transaction so be careful about
      * performance.
      * <li>Never execute another binder transaction inside the callback.
+     *
      * @hide
      */
     public static void setWorkSourceProvider(BinderInternal.WorkSourceProvider workSourceProvider) {
@@ -1131,12 +1151,12 @@
         sWorkSourceProvider = workSourceProvider;
     }
 
-    // Entry point from android_util_Binder.cpp's onTransact
+    // Entry point from android_util_Binder.cpp's onTransact.
     @UnsupportedAppUsage
     private boolean execTransact(int code, long dataObj, long replyObj,
             int flags) {
         // At that point, the parcel request headers haven't been parsed so we do not know what
-        // WorkSource the caller has set. Use calling uid as the default.
+        // {@link WorkSource} the caller has set. Use calling UID as the default.
         final int callingUid = Binder.getCallingUid();
         final long origWorkSource = ThreadLocalWorkSource.setUid(callingUid);
         try {
@@ -1154,17 +1174,18 @@
                 observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null;
         Parcel data = Parcel.obtain(dataObj);
         Parcel reply = Parcel.obtain(replyObj);
-        // theoretically, we should call transact, which will call onTransact,
+        // Theoretically, we should call transact, which will call onTransact,
         // but all that does is rewind it, and we just got these from an IPC,
         // so we'll just call it directly.
         boolean res;
         // Log any exceptions as warnings, don't silently suppress them.
-        // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
+        // If the call was {@link IBinder#FLAG_ONEWAY} then these exceptions
+        // disappear into the ether.
         final boolean tracingEnabled = Binder.isTracingEnabled();
         try {
             final BinderCallHeavyHitterWatcher heavyHitterWatcher = sHeavyHitterWatcher;
             if (heavyHitterWatcher != null) {
-                // Notify the heavy hitter watcher, if it's enabled
+                // Notify the heavy hitter watcher, if it's enabled.
                 heavyHitterWatcher.onTransaction(callingUid, getClass(), code);
             }
             if (tracingEnabled) {
@@ -1197,7 +1218,7 @@
                     Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
                 }
             } else {
-                // Clear the parcel before writing the exception
+                // Clear the parcel before writing the exception.
                 reply.setDataSize(0);
                 reply.setDataPosition(0);
                 reply.writeException(e);
@@ -1209,7 +1230,7 @@
             }
             if (observer != null) {
                 // The parcel RPC headers have been called during onTransact so we can now access
-                // the worksource uid from the parcel.
+                // the worksource UID from the parcel.
                 final int workSourceUid = sWorkSourceProvider.resolveWorkSourceUid(
                         data.readCallingWorkSourceUid());
                 observer.callEnded(callSession, data.dataSize(), reply.dataSize(), workSourceUid);
@@ -1220,9 +1241,9 @@
         data.recycle();
 
         // Just in case -- we are done with the IPC, so there should be no more strict
-        // mode violations that have gathered for this thread.  Either they have been
+        // mode violations that have gathered for this thread. Either they have been
         // parceled and are now in transport off to the caller, or we are returning back
-        // to the main transaction loop to wait for another incoming transaction.  Either
+        // to the main transaction loop to wait for another incoming transaction. Either
         // way, strict mode begone!
         StrictMode.clearGatheredViolations();
         return res;
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 92eb7a5..b2bbfd6 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -102,6 +102,18 @@
     }
 
     /**
+     * Constructs a {@link Bundle} containing a copy of {@code from}.
+     *
+     * @param from The bundle to be copied.
+     * @param deep Whether is a deep or shallow copy.
+     *
+     * @hide
+     */
+    Bundle(Bundle from, boolean deep) {
+        super(from, deep);
+    }
+
+    /**
      * If {@link #mParcelledData} is not null, copy the HAS FDS bit from it because it's fast.
      * Otherwise (if {@link #mParcelledData} is already null), leave {@link #FLAG_HAS_FDS_KNOWN}
      * unset, because scanning a map is slower.  We'll do it lazily in
@@ -167,13 +179,6 @@
     }
 
     /**
-     * Constructs a Bundle without initializing it.
-     */
-    Bundle(boolean doInit) {
-        super(doInit);
-    }
-
-    /**
      * Make a Bundle for a single key/value pair.
      *
      * @hide
@@ -260,9 +265,7 @@
      * are referenced as-is and not copied in any way.
      */
     public Bundle deepCopy() {
-        Bundle b = new Bundle(false);
-        b.copyInternal(this, true);
-        return b;
+        return new Bundle(this, /* deep */ true);
     }
 
     /**
@@ -324,28 +327,10 @@
      */
     public boolean hasFileDescriptors() {
         if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
-            boolean fdFound = false;    // keep going until we find one or run out of data
-
-            if (mParcelledData != null) {
-                if (mParcelledData.hasFileDescriptors()) {
-                    fdFound = true;
-                }
-            } else {
-                // It's been unparcelled, so we need to walk the map
-                for (int i=mMap.size()-1; i>=0; i--) {
-                    Object obj = mMap.valueAt(i);
-                    if (Parcel.hasFileDescriptors(obj)) {
-                        fdFound = true;
-                        break;
-                    }
-                }
-            }
-
-            if (fdFound) {
-                mFlags |= FLAG_HAS_FDS;
-            } else {
-                mFlags &= ~FLAG_HAS_FDS;
-            }
+            Parcel p = mParcelledData;
+            mFlags = (Parcel.hasFileDescriptors((p != null) ? p : mMap))
+                    ? mFlags | FLAG_HAS_FDS
+                    : mFlags & ~FLAG_HAS_FDS;
             mFlags |= FLAG_HAS_FDS_KNOWN;
         }
         return (mFlags & FLAG_HAS_FDS) != 0;
diff --git a/core/java/android/os/BytesMatcher.java b/core/java/android/os/BytesMatcher.java
deleted file mode 100644
index 8974c5e..0000000
--- a/core/java/android/os/BytesMatcher.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2021 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.os;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.bluetooth.BluetoothUuid;
-import android.net.MacAddress;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.util.HexDump;
-
-import java.util.ArrayList;
-import java.util.function.Predicate;
-
-/**
- * Predicate that tests if a given {@code byte[]} value matches a set of
- * configured rules.
- * <p>
- * Rules are tested in the order in which they were originally added, which
- * means a narrow rule can reject a specific value before a later broader rule
- * might accept that same value, or vice versa.
- * <p>
- * Matchers can contain rules of varying lengths, and tested values will only be
- * matched against rules of the exact same length. This is designed to support
- * {@link BluetoothUuid} style values which can be variable length.
- *
- * @hide
- */
-public class BytesMatcher implements Predicate<byte[]> {
-    private static final String TAG = "BytesMatcher";
-
-    private static final char TYPE_EXACT_ACCEPT = '+';
-    private static final char TYPE_EXACT_REJECT = '-';
-    private static final char TYPE_PREFIX_ACCEPT = '⊆';
-    private static final char TYPE_PREFIX_REJECT = '⊈';
-
-    private final ArrayList<Rule> mRules = new ArrayList<>();
-
-    private static class Rule {
-        public final char type;
-        public final @NonNull byte[] value;
-        public final @Nullable byte[] mask;
-
-        public Rule(char type, @NonNull byte[] value, @Nullable byte[] mask) {
-            if (mask != null && value.length != mask.length) {
-                throw new IllegalArgumentException(
-                        "Expected length " + value.length + " but found " + mask.length);
-            }
-            this.type = type;
-            this.value = value;
-            this.mask = mask;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder();
-            encode(builder);
-            return builder.toString();
-        }
-
-        public void encode(@NonNull StringBuilder builder) {
-            builder.append(type);
-            builder.append(HexDump.toHexString(value));
-            if (mask != null) {
-                builder.append('/');
-                builder.append(HexDump.toHexString(mask));
-            }
-        }
-
-        public boolean test(@NonNull byte[] value) {
-            switch (type) {
-                case TYPE_EXACT_ACCEPT:
-                case TYPE_EXACT_REJECT:
-                    if (value.length != this.value.length) {
-                        return false;
-                    }
-                    break;
-                case TYPE_PREFIX_ACCEPT:
-                case TYPE_PREFIX_REJECT:
-                    if (value.length < this.value.length) {
-                        return false;
-                    }
-                    break;
-            }
-            for (int i = 0; i < this.value.length; i++) {
-                byte local = this.value[i];
-                byte remote = value[i];
-                if (this.mask != null) {
-                    local &= this.mask[i];
-                    remote &= this.mask[i];
-                }
-                if (local != remote) {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Add a rule that will result in {@link #test(byte[])} returning
-     * {@code true} when a value being tested matches it. This rule will only
-     * match values of the exact same length.
-     * <p>
-     * Rules are tested in the order in which they were originally added, which
-     * means a narrow rule can reject a specific value before a later broader
-     * rule might accept that same value, or vice versa.
-     *
-     * @param value to be matched
-     * @param mask to be applied to both values before testing for equality; if
-     *            {@code null} then both values must match exactly
-     */
-    public void addExactAcceptRule(@NonNull byte[] value, @Nullable byte[] mask) {
-        mRules.add(new Rule(TYPE_EXACT_ACCEPT, value, mask));
-    }
-
-    /**
-     * Add a rule that will result in {@link #test(byte[])} returning
-     * {@code false} when a value being tested matches it. This rule will only
-     * match values of the exact same length.
-     * <p>
-     * Rules are tested in the order in which they were originally added, which
-     * means a narrow rule can reject a specific value before a later broader
-     * rule might accept that same value, or vice versa.
-     *
-     * @param value to be matched
-     * @param mask to be applied to both values before testing for equality; if
-     *            {@code null} then both values must match exactly
-     */
-    public void addExactRejectRule(@NonNull byte[] value, @Nullable byte[] mask) {
-        mRules.add(new Rule(TYPE_EXACT_REJECT, value, mask));
-    }
-
-    /**
-     * Add a rule that will result in {@link #test(byte[])} returning
-     * {@code true} when a value being tested matches it. This rule will match
-     * values of the exact same length or longer.
-     * <p>
-     * Rules are tested in the order in which they were originally added, which
-     * means a narrow rule can reject a specific value before a later broader
-     * rule might accept that same value, or vice versa.
-     *
-     * @param value to be matched
-     * @param mask to be applied to both values before testing for equality; if
-     *            {@code null} then both values must match exactly
-     */
-    public void addPrefixAcceptRule(@NonNull byte[] value, @Nullable byte[] mask) {
-        mRules.add(new Rule(TYPE_PREFIX_ACCEPT, value, mask));
-    }
-
-    /**
-     * Add a rule that will result in {@link #test(byte[])} returning
-     * {@code false} when a value being tested matches it. This rule will match
-     * values of the exact same length or longer.
-     * <p>
-     * Rules are tested in the order in which they were originally added, which
-     * means a narrow rule can reject a specific value before a later broader
-     * rule might accept that same value, or vice versa.
-     *
-     * @param value to be matched
-     * @param mask to be applied to both values before testing for equality; if
-     *            {@code null} then both values must match exactly
-     */
-    public void addPrefixRejectRule(@NonNull byte[] value, @Nullable byte[] mask) {
-        mRules.add(new Rule(TYPE_PREFIX_REJECT, value, mask));
-    }
-
-    /**
-     * Test if the given {@code ParcelUuid} value matches the set of rules
-     * configured in this matcher.
-     */
-    public boolean testBluetoothUuid(@NonNull ParcelUuid value) {
-        return test(BluetoothUuid.uuidToBytes(value));
-    }
-
-    /**
-     * Test if the given {@code MacAddress} value matches the set of rules
-     * configured in this matcher.
-     */
-    public boolean testMacAddress(@NonNull MacAddress value) {
-        return test(value.toByteArray());
-    }
-
-    /**
-     * Test if the given {@code byte[]} value matches the set of rules
-     * configured in this matcher.
-     */
-    @Override
-    public boolean test(@NonNull byte[] value) {
-        return test(value, false);
-    }
-
-    /**
-     * Test if the given {@code byte[]} value matches the set of rules
-     * configured in this matcher.
-     */
-    public boolean test(@NonNull byte[] value, boolean defaultValue) {
-        final int size = mRules.size();
-        for (int i = 0; i < size; i++) {
-            final Rule rule = mRules.get(i);
-            if (rule.test(value)) {
-                switch (rule.type) {
-                    case TYPE_EXACT_ACCEPT:
-                    case TYPE_PREFIX_ACCEPT:
-                        return true;
-                    case TYPE_EXACT_REJECT:
-                    case TYPE_PREFIX_REJECT:
-                        return false;
-                }
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Encode the given matcher into a human-readable {@link String} which can
-     * be used to transport matchers across device boundaries.
-     * <p>
-     * The human-readable format is an ordered list separated by commas, where
-     * each rule is a {@code +} or {@code -} symbol indicating if the match
-     * should be accepted or rejected, then followed by a hex value and an
-     * optional hex mask. For example, {@code -caff,+cafe/ff00} is a valid
-     * encoded matcher.
-     *
-     * @see #decode(String)
-     */
-    public static @NonNull String encode(@NonNull BytesMatcher matcher) {
-        final StringBuilder builder = new StringBuilder();
-        final int size = matcher.mRules.size();
-        for (int i = 0; i < size; i++) {
-            final Rule rule = matcher.mRules.get(i);
-            rule.encode(builder);
-            builder.append(',');
-        }
-        if (builder.length() > 0) {
-            builder.deleteCharAt(builder.length() - 1);
-        }
-        return builder.toString();
-    }
-
-    /**
-     * Decode the given human-readable {@link String} used to transport matchers
-     * across device boundaries.
-     * <p>
-     * The human-readable format is an ordered list separated by commas, where
-     * each rule is a {@code +} or {@code -} symbol indicating if the match
-     * should be accepted or rejected, then followed by a hex value and an
-     * optional hex mask. For example, {@code -caff,+cafe/ff00} is a valid
-     * encoded matcher.
-     *
-     * @see #encode(BytesMatcher)
-     */
-    public static @NonNull BytesMatcher decode(@Nullable String value) {
-        final BytesMatcher matcher = new BytesMatcher();
-        if (TextUtils.isEmpty(value)) return matcher;
-
-        final int length = value.length();
-        for (int i = 0; i < length;) {
-            final char type = value.charAt(i);
-
-            int nextRule = value.indexOf(',', i);
-            int nextMask = value.indexOf('/', i);
-
-            if (nextRule == -1) nextRule = length;
-            if (nextMask > nextRule) nextMask = -1;
-
-            final byte[] ruleValue;
-            final byte[] ruleMask;
-            if (nextMask >= 0) {
-                ruleValue = HexDump.hexStringToByteArray(value.substring(i + 1, nextMask));
-                ruleMask = HexDump.hexStringToByteArray(value.substring(nextMask + 1, nextRule));
-            } else {
-                ruleValue = HexDump.hexStringToByteArray(value.substring(i + 1, nextRule));
-                ruleMask = null;
-            }
-
-            switch (type) {
-                case TYPE_EXACT_ACCEPT:
-                    matcher.addExactAcceptRule(ruleValue, ruleMask);
-                    break;
-                case TYPE_EXACT_REJECT:
-                    matcher.addExactRejectRule(ruleValue, ruleMask);
-                    break;
-                case TYPE_PREFIX_ACCEPT:
-                    matcher.addPrefixAcceptRule(ruleValue, ruleMask);
-                    break;
-                case TYPE_PREFIX_REJECT:
-                    matcher.addPrefixRejectRule(ruleValue, ruleMask);
-                    break;
-                default:
-                    Log.w(TAG, "Ignoring unknown type " + type);
-                    break;
-            }
-
-            i = nextRule + 1;
-        }
-        return matcher;
-    }
-}
diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl
index d83d94a..15e3ce2 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.content.ComponentName;
+
 /**
   * Binder interface to query SystemConfig in the system server.
   * {@hide}
@@ -44,5 +46,5 @@
     /**
      * @see SystemConfigManager#getEnabledComponentOverrides
      */
-    List<String> getEnabledComponentOverrides(String packageName);
+    List<ComponentName> getEnabledComponentOverrides(String packageName);
 }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index ab2c8c0..09e5a8f 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.app.AppOpsManager;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -61,6 +62,8 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.function.IntFunction;
 import java.util.function.Supplier;
 
 /**
@@ -177,8 +180,12 @@
  * {@link #writeStrongInterface(IInterface)}, {@link #readStrongBinder()},
  * {@link #writeBinderArray(IBinder[])}, {@link #readBinderArray(IBinder[])},
  * {@link #createBinderArray()},
+ * {@link #writeInterfaceArray(T[])}, {@link #readInterfaceArray(T[], Function)},
+ * {@link #createInterfaceArray(IntFunction, Function)},
  * {@link #writeBinderList(List)}, {@link #readBinderList(List)},
- * {@link #createBinderArrayList()}.</p>
+ * {@link #createBinderArrayList()},
+ * {@link #writeInterfaceList(List)}, {@link #readInterfaceList(List, Function)},
+ * {@link #createInterfaceArrayList(Function)}.</p>
  *
  * <p>FileDescriptor objects, representing raw Linux file descriptor identifiers,
  * can be written and {@link ParcelFileDescriptor} objects returned to operate
@@ -380,6 +387,8 @@
     private static native void nativeUnmarshall(
             long nativePtr, byte[] data, int offset, int length);
     private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
+    private static native boolean nativeCompareDataInRange(
+            long ptrA, int offsetA, long ptrB, int offsetB, int length);
     private static native void nativeAppendFrom(
             long thisNativePtr, long otherNativePtr, int offset, int length);
     @CriticalNative
@@ -677,11 +686,16 @@
     }
 
     /** @hide */
-    public final int compareData(Parcel other) {
+    public int compareData(Parcel other) {
         return nativeCompareData(mNativePtr, other.mNativePtr);
     }
 
     /** @hide */
+    public static boolean compareData(Parcel a, int offsetA, Parcel b, int offsetB, int length) {
+        return nativeCompareDataInRange(a.mNativePtr, offsetA, b.mNativePtr, offsetB, length);
+    }
+
+    /** @hide */
     public final void setClassCookie(Class clz, Object cookie) {
         if (mClassCookies == null) {
             mClassCookies = new ArrayMap<>();
@@ -739,57 +753,70 @@
     }
 
     /**
-     * Check if the object used in {@link #readValue(ClassLoader)} / {@link #writeValue(Object)}
-     * has file descriptors.
+     * Check if the object has file descriptors.
+     *
+     * <p>Objects supported are {@link Parcel} and objects that can be passed to {@link
+     * #writeValue(Object)}}
      *
      * <p>For most cases, it will use the self-reported {@link Parcelable#describeContents()} method
      * for that.
      *
-     * @throws IllegalArgumentException if you provide any object not supported by above methods.
-     *         Most notably, if you pass {@link Parcel}, this method will throw, for that check
-     *         {@link Parcel#hasFileDescriptors()}
+     * @throws IllegalArgumentException if you provide any object not supported by above methods
+     *     (including if the unsupported object is inside a nested container).
      *
      * @hide
      */
     public static boolean hasFileDescriptors(Object value) {
-        if (value instanceof LazyValue) {
-            return ((LazyValue) value).hasFileDescriptors();
-        } else if (value instanceof Parcelable) {
-            if ((((Parcelable) value).describeContents()
-                    & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+        if (value instanceof Parcel) {
+            Parcel parcel = (Parcel) value;
+            if (parcel.hasFileDescriptors()) {
                 return true;
             }
-        } else if (value instanceof Parcelable[]) {
-            Parcelable[] array = (Parcelable[]) value;
-            for (int n = array.length - 1; n >= 0; n--) {
-                Parcelable p = array[n];
-                if (p != null && ((p.describeContents()
-                        & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
+        } else if (value instanceof LazyValue) {
+            LazyValue lazy = (LazyValue) value;
+            if (lazy.hasFileDescriptors()) {
+                return true;
+            }
+        } else if (value instanceof Parcelable) {
+            Parcelable parcelable = (Parcelable) value;
+            if ((parcelable.describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+                return true;
+            }
+        } else if (value instanceof ArrayMap<?, ?>) {
+            ArrayMap<?, ?> map = (ArrayMap<?, ?>) value;
+            for (int i = 0, n = map.size(); i < n; i++) {
+                if (hasFileDescriptors(map.keyAt(i))
+                        || hasFileDescriptors(map.valueAt(i))) {
+                    return true;
+                }
+            }
+        } else if (value instanceof Map<?, ?>) {
+            Map<?, ?> map = (Map<?, ?>) value;
+            for (Map.Entry<?, ?> entry : map.entrySet()) {
+                if (hasFileDescriptors(entry.getKey())
+                        || hasFileDescriptors(entry.getValue())) {
+                    return true;
+                }
+            }
+        } else if (value instanceof List<?>) {
+            List<?> list = (List<?>) value;
+            for (int i = 0, n = list.size(); i < n; i++) {
+                if (hasFileDescriptors(list.get(i))) {
                     return true;
                 }
             }
         } else if (value instanceof SparseArray<?>) {
             SparseArray<?> array = (SparseArray<?>) value;
-            for (int n = array.size() - 1; n >= 0; n--) {
-                Object object = array.valueAt(n);
-                if (object instanceof Parcelable) {
-                    Parcelable p = (Parcelable) object;
-                    if (p != null && (p.describeContents()
-                            & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
-                        return true;
-                    }
+            for (int i = 0, n = array.size(); i < n; i++) {
+                if (hasFileDescriptors(array.valueAt(i))) {
+                    return true;
                 }
             }
-        } else if (value instanceof ArrayList<?>) {
-            ArrayList<?> array = (ArrayList<?>) value;
-            for (int n = array.size() - 1; n >= 0; n--) {
-                Object object = array.get(n);
-                if (object instanceof Parcelable) {
-                    Parcelable p = (Parcelable) object;
-                    if (p != null && ((p.describeContents()
-                            & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
-                        return true;
-                    }
+        } else if (value instanceof Object[]) {
+            Object[] array = (Object[]) value;
+            for (int i = 0, n = array.length; i < n; i++) {
+                if (hasFileDescriptors(array[i])) {
+                    return true;
                 }
             }
         } else {
@@ -1709,6 +1736,30 @@
     }
 
     /**
+     * Flatten a homogeneous array containing an IInterface type into the parcel,
+     * at the current dataPosition() and growing dataCapacity() if needed.  The
+     * type of the objects in the array must be one that implements IInterface.
+     *
+     * @param val The array of objects to be written.
+     *
+     * @see #createInterfaceArray
+     * @see #readInterfaceArray
+     * @see IInterface
+     */
+    public final <T extends IInterface> void writeInterfaceArray(
+            @SuppressLint("ArrayReturn") @Nullable T[] val) {
+        if (val != null) {
+            int N = val.length;
+            writeInt(N);
+            for (int i=0; i<N; i++) {
+                writeStrongInterface(val[i]);
+            }
+        } else {
+            writeInt(-1);
+        }
+    }
+
+    /**
      * @hide
      */
     public final void writeCharSequenceArray(@Nullable CharSequence[] val) {
@@ -1764,6 +1815,50 @@
     }
 
     /**
+     * Read and return a new array of T (IInterface) from the parcel.
+     *
+     * @return the IInterface array of type T
+     * @param newArray a function to create an array of T with a given length
+     * @param asInterface a function to convert IBinder object into T (IInterface)
+     */
+    @SuppressLint({"ArrayReturn", "NullableCollection", "SamShouldBeLast"})
+    @Nullable
+    public final <T extends IInterface> T[] createInterfaceArray(
+            @NonNull IntFunction<T[]> newArray, @NonNull Function<IBinder, T> asInterface) {
+        int N = readInt();
+        if (N >= 0) {
+            T[] val = newArray.apply(N);
+            for (int i=0; i<N; i++) {
+                val[i] = asInterface.apply(readStrongBinder());
+            }
+            return val;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Read an array of T (IInterface) from a parcel.
+     *
+     * @param asInterface a function to convert IBinder object into T (IInterface)
+     *
+     * @throws BadParcelableException Throws BadParcelableException if the length of `val`
+     *    mismatches the number of items in the parcel.
+     */
+    public final <T extends IInterface> void readInterfaceArray(
+            @SuppressLint("ArrayReturn") @NonNull T[] val,
+            @NonNull Function<IBinder, T> asInterface) {
+        int N = readInt();
+        if (N == val.length) {
+            for (int i=0; i<N; i++) {
+                val[i] = asInterface.apply(readStrongBinder());
+            }
+        } else {
+            throw new BadParcelableException("bad array lengths");
+        }
+    }
+
+    /**
      * Flatten a List containing a particular object type into the parcel, at
      * the current dataPosition() and growing dataCapacity() if needed.  The
      * type of the objects in the list must be one that implements Parcelable.
@@ -1877,6 +1972,28 @@
     }
 
     /**
+     * Flatten a {@code List} containing T (IInterface) objects into this parcel
+     * at the current position. They can later be retrieved with
+     * {@link #createInterfaceArrayList} or {@link #readInterfaceList}.
+     *
+     * @see #createInterfaceArrayList
+     * @see #readInterfaceList
+     */
+    public final <T extends IInterface> void writeInterfaceList(@Nullable List<T> val) {
+        if (val == null) {
+            writeInt(-1);
+            return;
+        }
+        int N = val.size();
+        int i=0;
+        writeInt(N);
+        while (i < N) {
+            writeStrongInterface(val.get(i));
+            i++;
+        }
+    }
+
+    /**
      * Flatten a {@code List} containing arbitrary {@code Parcelable} objects into this parcel
      * at the current position. They can later be retrieved using
      * {@link #readParcelableList(List, ClassLoader)} if required.
@@ -2440,9 +2557,9 @@
 
             writeByteArray(baos.toByteArray());
         } catch (IOException ioe) {
-            throw new RuntimeException("Parcelable encountered " +
-                "IOException writing serializable object (name = " + name +
-                ")", ioe);
+            throw new BadParcelableException("Parcelable encountered "
+                    + "IOException writing serializable object (name = "
+                    + name + ")", ioe);
         }
     }
 
@@ -2875,8 +2992,24 @@
      * from the parcel at the current dataPosition().
      */
     public final void readMap(@NonNull Map outVal, @Nullable ClassLoader loader) {
-        int N = readInt();
-        readMapInternal(outVal, N, loader);
+        int n = readInt();
+        readMapInternal(outVal, n, loader, /* clazzKey */ null, /* clazzValue */ null);
+    }
+
+    /**
+     * Same as {@link #readMap(Map, ClassLoader)} but accepts {@code clazzKey} and
+     * {@code clazzValue} parameter as the types required for each key and value pair.
+     *
+     * @throws BadParcelableException If the item to be deserialized is not an instance of that
+     * class or any of its children class
+     */
+    public <K, V> void readMap(@NonNull Map<? super K, ? super V> outVal,
+            @Nullable ClassLoader loader, @NonNull Class<K> clazzKey,
+            @NonNull Class<V> clazzValue) {
+        Objects.requireNonNull(clazzKey);
+        Objects.requireNonNull(clazzValue);
+        int n = readInt();
+        readMapInternal(outVal, n, loader, clazzKey, clazzValue);
     }
 
     /**
@@ -2914,16 +3047,38 @@
     @Nullable
     public final HashMap readHashMap(@Nullable ClassLoader loader)
     {
-        int N = readInt();
-        if (N < 0) {
+        int n = readInt();
+        if (n < 0) {
             return null;
         }
-        HashMap m = new HashMap(N);
-        readMapInternal(m, N, loader);
+        HashMap m = new HashMap(n);
+        readMapInternal(m, n, loader, /* clazzKey */ null, /* clazzValue */ null);
         return m;
     }
 
     /**
+     * Same as {@link #readHashMap(ClassLoader)} but accepts {@code clazzKey} and
+     * {@code clazzValue} parameter as the types required for each key and value pair.
+     *
+     * @throws BadParcelableException if the item to be deserialized is not an instance of that
+     * class or any of its children class
+     */
+    @SuppressLint({"ConcreteCollection", "NullableCollection"})
+    @Nullable
+    public <K, V> HashMap<K, V> readHashMap(@Nullable ClassLoader loader,
+            @NonNull Class<? extends K> clazzKey, @NonNull Class<? extends V> clazzValue) {
+        Objects.requireNonNull(clazzKey);
+        Objects.requireNonNull(clazzValue);
+        int n = readInt();
+        if (n < 0) {
+            return null;
+        }
+        HashMap<K, V> map = new HashMap<>(n);
+        readMapInternal(map, n, loader, clazzKey, clazzValue);
+        return map;
+    }
+
+    /**
      * Read and return a new Bundle object from the parcel at the current
      * dataPosition().  Returns null if the previously written Bundle object was
      * null.
@@ -3094,14 +3249,24 @@
      * Parcelables.
      */
     @Nullable
-    public final ArrayList readArrayList(@Nullable ClassLoader loader) {
-        int N = readInt();
-        if (N < 0) {
-            return null;
-        }
-        ArrayList l = new ArrayList(N);
-        readListInternal(l, N, loader, /* clazz */ null);
-        return l;
+    public ArrayList readArrayList(@Nullable ClassLoader loader) {
+        return readArrayListInternal(loader, /* clazz */ null);
+    }
+
+    /**
+     * Same as {@link #readArrayList(ClassLoader)} but accepts {@code clazz} parameter as
+     * the type required for each item.
+     *
+     * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+     * is not an instance of that class or any of its children classes or there was an error
+     * trying to instantiate an element.
+     */
+    @SuppressLint({"ConcreteCollection", "NullableCollection"})
+    @Nullable
+    public <T> ArrayList<T> readArrayList(@Nullable ClassLoader loader,
+            @NonNull Class<? extends T> clazz) {
+        Objects.requireNonNull(clazz);
+        return readArrayListInternal(loader, clazz);
     }
 
     /**
@@ -3111,14 +3276,23 @@
      * Parcelables.
      */
     @Nullable
-    public final Object[] readArray(@Nullable ClassLoader loader) {
-        int N = readInt();
-        if (N < 0) {
-            return null;
-        }
-        Object[] l = new Object[N];
-        readArrayInternal(l, N, loader);
-        return l;
+    public Object[] readArray(@Nullable ClassLoader loader) {
+        return readArrayInternal(loader, /* clazz */ null);
+    }
+
+    /**
+     * Same as {@link #readArray(ClassLoader)} but accepts {@code clazz} parameter as
+     * the type required for each item.
+     *
+     * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+     * is not an instance of that class or any of its children classes or there was an error
+     * trying to instantiate an element.
+     */
+    @SuppressLint({"ArrayReturn", "NullableCollection"})
+    @Nullable
+    public <T> T[] readArray(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
+        Objects.requireNonNull(clazz);
+        return readArrayInternal(loader, clazz);
     }
 
     /**
@@ -3128,14 +3302,23 @@
      * Parcelables.
      */
     @Nullable
-    public final <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader) {
-        int N = readInt();
-        if (N < 0) {
-            return null;
-        }
-        SparseArray sa = new SparseArray(N);
-        readSparseArrayInternal(sa, N, loader);
-        return sa;
+    public <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader) {
+        return readSparseArrayInternal(loader, /* clazz */ null);
+    }
+
+    /**
+     * Same as {@link #readSparseArray(ClassLoader)} but accepts {@code clazz} parameter as
+     * the type required for each item.
+     *
+     * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+     * is not an instance of that class or any of its children classes or there was an error
+     * trying to instantiate an element.
+     */
+    @Nullable
+    public <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader,
+            @NonNull Class<? extends T> clazz) {
+        Objects.requireNonNull(clazz);
+        return readSparseArrayInternal(loader, clazz);
     }
 
     /**
@@ -3331,6 +3514,32 @@
     }
 
     /**
+     * Read and return a new ArrayList containing T (IInterface) objects from
+     * the parcel that was written with {@link #writeInterfaceList} at the
+     * current dataPosition().  Returns null if the
+     * previously written list object was null.
+     *
+     * @return A newly created ArrayList containing T (IInterface)
+     *
+     * @see #writeInterfaceList
+     */
+    @SuppressLint({"ConcreteCollection", "NullableCollection"})
+    @Nullable
+    public final <T extends IInterface> ArrayList<T> createInterfaceArrayList(
+            @NonNull Function<IBinder, T> asInterface) {
+        int N = readInt();
+        if (N < 0) {
+            return null;
+        }
+        ArrayList<T> l = new ArrayList<T>(N);
+        while (N > 0) {
+            l.add(asInterface.apply(readStrongBinder()));
+            N--;
+        }
+        return l;
+    }
+
+    /**
      * Read into the given List items String objects that were written with
      * {@link #writeStringList} at the current dataPosition().
      *
@@ -3373,6 +3582,28 @@
     }
 
     /**
+     * Read into the given List items IInterface objects that were written with
+     * {@link #writeInterfaceList} at the current dataPosition().
+     *
+     * @see #writeInterfaceList
+     */
+    public final <T extends IInterface> void readInterfaceList(@NonNull List<T> list,
+            @NonNull Function<IBinder, T> asInterface) {
+        int M = list.size();
+        int N = readInt();
+        int i = 0;
+        for (; i < M && i < N; i++) {
+            list.set(i, asInterface.apply(readStrongBinder()));
+        }
+        for (; i<N; i++) {
+            list.add(asInterface.apply(readStrongBinder()));
+        }
+        for (; i<M; i++) {
+            list.remove(N);
+        }
+    }
+
+    /**
      * Read the list of {@code Parcelable} objects at the current data position into the
      * given {@code list}. The contents of the {@code list} are replaced. If the serialized
      * list was {@code null}, {@code list} is cleared.
@@ -3580,7 +3811,6 @@
         private final int mType;
         @Nullable private final ClassLoader mLoader;
         @Nullable private Object mObject;
-        @Nullable private volatile Parcel mValueParcel;
 
         /**
          * This goes from non-null to null once. Always check the nullability of this object before
@@ -3678,7 +3908,7 @@
                 return false;
             }
             // Finally we compare the payload.
-            return getValueParcel(source).compareData(value.getValueParcel(otherSource)) == 0;
+            return Parcel.compareData(source, mPosition, otherSource, value.mPosition, mLength);
         }
 
         @Override
@@ -3686,17 +3916,6 @@
             // Accessing mSource first to provide memory barrier for mObject
             return Objects.hash(mSource == null, mObject, mLoader, mType, mLength);
         }
-
-        /** This extracts the parcel section responsible for the object and returns it. */
-        private Parcel getValueParcel(Parcel source) {
-            Parcel parcel = mValueParcel;
-            if (parcel == null) {
-                parcel = Parcel.obtain();
-                parcel.appendFrom(source, mPosition, mLength);
-                mValueParcel = parcel;
-            }
-            return parcel;
-        }
     }
 
     /**
@@ -3794,7 +4013,7 @@
                 break;
 
             case VAL_SERIALIZABLE:
-                object = readSerializable(loader);
+                object = readSerializableInternal(loader, clazz);
                 break;
 
             case VAL_PARCELABLEARRAY:
@@ -3851,7 +4070,7 @@
                     "Parcel " + this + ": Unmarshalling unknown type code " + type
                             + " at offset " + off);
         }
-        if (clazz != null && !clazz.isInstance(object)) {
+        if (object != null && clazz != null && !clazz.isInstance(object)) {
             throw new BadParcelableException("Unparcelled object " + object
                     + " is not an instance of required class " + clazz.getName()
                     + " provided in the parameter");
@@ -3910,7 +4129,6 @@
     }
 
     /**
-     *
      * @param clazz The type of the parcelable expected or {@code null} for performing no checks.
      */
     @SuppressWarnings("unchecked")
@@ -3969,7 +4187,7 @@
      * as the required type.
      *
      * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
-     * is not an instance of that class or any of its children class or there there was an error
+     * is not an instance of that class or any of its children classes or there there was an error
      * trying to read the {@link Parcelable.Creator}.
      */
     @Nullable
@@ -4092,17 +4310,25 @@
         return p;
     }
 
-    /** @hide */
+    /**
+     * Same as {@link #readParcelableArray(ClassLoader)}  but accepts {@code clazz} parameter as
+     * the type required for each item.
+     *
+     * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+     * is not an instance of that class or any of its children classes or there was an error
+     * trying to instantiate an element.
+     */
+    @SuppressLint({"ArrayReturn", "NullableCollection"})
+    @SuppressWarnings("unchecked")
     @Nullable
-    public final <T extends Parcelable> T[] readParcelableArray(@Nullable ClassLoader loader,
-            @NonNull Class<T> clazz) {
-        int N = readInt();
-        if (N < 0) {
+    public <T> T[] readParcelableArray(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
+        int n = readInt();
+        if (n < 0) {
             return null;
         }
-        T[] p = (T[]) Array.newInstance(clazz, N);
-        for (int i = 0; i < N; i++) {
-            p[i] = readParcelable(loader);
+        T[] p = (T[]) Array.newInstance(clazz, n);
+        for (int i = 0; i < n; i++) {
+            p[i] = readParcelableInternal(loader, clazz);
         }
         return p;
     }
@@ -4113,12 +4339,37 @@
      * wasn't found in the parcel.
      */
     @Nullable
-    public final Serializable readSerializable() {
-        return readSerializable(null);
+    public Serializable readSerializable() {
+        return readSerializableInternal(/* loader */ null, /* clazz */ null);
     }
 
+    /**
+     * Same as {@link #readSerializable()} but accepts {@code loader} parameter
+     * as the primary classLoader for resolving the Serializable class; and {@code clazz} parameter
+     * as the required type.
+     *
+     * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+     * is not an instance of that class or any of its children class or there there was an error
+     * deserializing the object.
+     */
     @Nullable
-    private final Serializable readSerializable(@Nullable final ClassLoader loader) {
+    public <T extends Serializable> T readSerializable(@Nullable ClassLoader loader,
+            @NonNull Class<T> clazz) {
+        Objects.requireNonNull(clazz);
+        return readSerializableInternal(loader, clazz);
+    }
+
+    /**
+     * @param clazz The type of the serializable expected or {@code null} for performing no checks
+     */
+    @Nullable
+    private <T> T readSerializableInternal(@Nullable final ClassLoader loader,
+            @Nullable Class<T> clazz) {
+        if (clazz != null && !Serializable.class.isAssignableFrom(clazz)) {
+            throw new BadParcelableException("About to unparcel a serializable object "
+                    + " but class required " + clazz.getName() + " is not Serializable");
+        }
+
         String name = readString();
         if (name == null) {
             // For some reason we were unable to read the name of the Serializable (either there
@@ -4127,9 +4378,20 @@
             return null;
         }
 
-        byte[] serializedData = createByteArray();
-        ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
         try {
+            if (clazz != null && loader != null) {
+                // If custom classloader is provided, resolve the type of serializable using the
+                // name, then check the type before deserialization. As in this case we can resolve
+                // the class the same way as ObjectInputStream, using the provided classloader.
+                Class<?> cl = Class.forName(name, false, loader);
+                if (!clazz.isAssignableFrom(cl)) {
+                    throw new BadParcelableException("Serializable object "
+                            + cl.getName() + " is not a subclass of required class "
+                            + clazz.getName() + " provided in the parameter");
+                }
+            }
+            byte[] serializedData = createByteArray();
+            ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
             ObjectInputStream ois = new ObjectInputStream(bais) {
                 @Override
                 protected Class<?> resolveClass(ObjectStreamClass osClass)
@@ -4137,22 +4399,31 @@
                     // try the custom classloader if provided
                     if (loader != null) {
                         Class<?> c = Class.forName(osClass.getName(), false, loader);
-                        if (c != null) {
-                            return c;
-                        }
+                        return Objects.requireNonNull(c);
                     }
                     return super.resolveClass(osClass);
                 }
             };
-            return (Serializable) ois.readObject();
+            T object = (T) ois.readObject();
+            if (clazz != null && loader == null) {
+                // If custom classloader is not provided, check the type of the serializable using
+                // the deserialized object, as we cannot resolve the class the same way as
+                // ObjectInputStream.
+                if (!clazz.isAssignableFrom(object.getClass())) {
+                    throw new BadParcelableException("Serializable object "
+                            + object.getClass().getName() + " is not a subclass of required class "
+                            + clazz.getName() + " provided in the parameter");
+                }
+            }
+            return object;
         } catch (IOException ioe) {
-            throw new RuntimeException("Parcelable encountered " +
-                "IOException reading a Serializable object (name = " + name +
-                ")", ioe);
+            throw new BadParcelableException("Parcelable encountered "
+                    + "IOException reading a Serializable object (name = "
+                    + name + ")", ioe);
         } catch (ClassNotFoundException cnfe) {
-            throw new RuntimeException("Parcelable encountered " +
-                "ClassNotFoundException reading a Serializable object (name = "
-                + name + ")", cnfe);
+            throw new BadParcelableException("Parcelable encountered "
+                    + "ClassNotFoundException reading a Serializable object (name = "
+                    + name + ")", cnfe);
         }
     }
 
@@ -4239,13 +4510,23 @@
         destroy();
     }
 
-    /* package */ void readMapInternal(@NonNull Map outVal, int N,
+    /**
+     * To be replaced by {@link #readMapInternal(Map, int, ClassLoader, Class, Class)}, but keep
+     * the old API for compatibility usages.
+     */
+    /* package */ void readMapInternal(@NonNull Map outVal, int n,
             @Nullable ClassLoader loader) {
-        while (N > 0) {
-            Object key = readValue(loader);
-            Object value = readValue(loader);
+        readMapInternal(outVal, n, loader, /* clazzKey */null, /* clazzValue */null);
+    }
+
+    /* package */ <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal, int n,
+            @Nullable ClassLoader loader, @Nullable Class<K> clazzKey,
+            @Nullable Class<V> clazzValue) {
+        while (n > 0) {
+            K key = readValue(loader, clazzKey);
+            V value = readValue(loader, clazzValue);
             outVal.put(key, value);
-            N--;
+            n--;
         }
     }
 
@@ -4320,9 +4601,12 @@
         return result;
     }
 
-    private void readListInternal(@NonNull List outVal, int n,
-            @Nullable ClassLoader loader) {
-        readListInternal(outVal, n, loader, null);
+    /**
+     * The method is replaced by {@link #readListInternal(List, int, ClassLoader, Class)}, however
+     * we are keeping this unused method here to allow unsupported app usages.
+     */
+    private void readListInternal(@NonNull List outVal, int n, @Nullable ClassLoader loader) {
+        readListInternal(outVal, n, loader,  /* clazz */ null);
     }
 
     /**
@@ -4338,26 +4622,88 @@
         }
     }
 
+    /**
+     * @param clazz The type of the object expected or {@code null} for performing no checks.
+     */
+    @SuppressLint({"ConcreteCollection", "NullableCollection"})
+    @Nullable
+    private <T> ArrayList<T> readArrayListInternal(@Nullable ClassLoader loader,
+            @Nullable Class<? extends T> clazz) {
+        int n = readInt();
+        if (n < 0) {
+            return null;
+        }
+        ArrayList<T> l = new ArrayList<>(n);
+        readListInternal(l, n, loader, clazz);
+        return l;
+    }
+
+    /**
+     * The method is replaced by {@link #readArrayInternal(ClassLoader, Class)}, however
+     * we are keeping this unused method here to allow unsupported app usages.
+     */
     private void readArrayInternal(@NonNull Object[] outVal, int N,
             @Nullable ClassLoader loader) {
         for (int i = 0; i < N; i++) {
-            Object value = readValue(loader);
-            //Log.d(TAG, "Unmarshalling value=" + value);
+            Object value = readValue(loader, /* clazz */ null);
             outVal[i] = value;
         }
     }
 
+    /**
+     * @param clazz The type of the object expected or {@code null} for performing no checks.
+     */
+    @SuppressWarnings("unchecked")
+    @Nullable
+    private <T> T[] readArrayInternal(@Nullable ClassLoader loader, @Nullable Class<T> clazz) {
+        int n = readInt();
+        if (n < 0) {
+            return null;
+        }
+        T[] outVal = (T[]) ((clazz == null) ? new Object[n] : Array.newInstance(clazz, n));
+
+        for (int i = 0; i < n; i++) {
+            T value = readValue(loader, clazz);
+            outVal[i] = value;
+        }
+        return outVal;
+    }
+
+    /**
+     * The method is replaced by {@link #readSparseArray(ClassLoader, Class)}, however
+     * we are keeping this unused method here to allow unsupported app usages.
+     */
     private void readSparseArrayInternal(@NonNull SparseArray outVal, int N,
             @Nullable ClassLoader loader) {
         while (N > 0) {
             int key = readInt();
             Object value = readValue(loader);
-            //Log.i(TAG, "Unmarshalling key=" + key + " value=" + value);
             outVal.append(key, value);
             N--;
         }
     }
 
+    /**
+     * @param clazz The type of the object expected or {@code null} for performing no checks.
+     */
+    @Nullable
+    private <T> SparseArray<T> readSparseArrayInternal(@Nullable ClassLoader loader,
+            @Nullable Class<? extends T> clazz) {
+        int n = readInt();
+        if (n < 0) {
+            return null;
+        }
+        SparseArray<T> outVal = new SparseArray<>(n);
+
+        while (n > 0) {
+            int key = readInt();
+            T value = readValue(loader, clazz);
+            outVal.append(key, value);
+            n--;
+        }
+        return outVal;
+    }
+
 
     private void readSparseBooleanArrayInternal(@NonNull SparseBooleanArray outVal, int N) {
         while (N > 0) {
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 7b55e710..f4edcb1 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -156,10 +156,15 @@
     }
 
     /**
-     * Constructs a PersistableBundle without initializing it.
+     * Constructs a {@link PersistableBundle} containing a copy of {@code from}.
+     *
+     * @param from The bundle to be copied.
+     * @param deep Whether is a deep or shallow copy.
+     *
+     * @hide
      */
-    PersistableBundle(boolean doInit) {
-        super(doInit);
+    PersistableBundle(PersistableBundle from, boolean deep) {
+        super(from, deep);
     }
 
     /**
@@ -190,9 +195,7 @@
      * are referenced as-is and not copied in any way.
      */
     public PersistableBundle deepCopy() {
-        PersistableBundle b = new PersistableBundle(false);
-        b.copyInternal(this, true);
-        return b;
+        return new PersistableBundle(this, /* deep */ true);
     }
 
     /**
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index a6316df..cde2063 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -17,10 +17,10 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.content.ComponentName;
 import android.content.Context;
 import android.util.ArraySet;
 import android.util.Log;
@@ -138,9 +138,9 @@
      * @return The enabled component
      * {@hide}
      */
-    @SystemApi
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     @NonNull
-    public List<String> getEnabledComponentOverrides(@NonNull String packageName) {
+    public List<ComponentName> getEnabledComponentOverrides(@NonNull String packageName) {
         try {
             return mInterface.getEnabledComponentOverrides(packageName);
         } catch (RemoteException e) {
diff --git a/core/java/android/os/health/HealthStats.java b/core/java/android/os/health/HealthStats.java
index 74ce515..6c648f1 100644
--- a/core/java/android/os/health/HealthStats.java
+++ b/core/java/android/os/health/HealthStats.java
@@ -32,7 +32,7 @@
  * Each of the keys references data in one of five data types:
  *
  * <p>
- * A <b>measurement</b> metric contains a sinlge {@code long} value. That value may
+ * A <b>measurement</b> metric contains a single {@code long} value. That value may
  * be a count, a time, or some other type of value. The unit for a measurement
  * (COUNT, MS, etc) will always be in the name of the constant for the key to
  * retrieve it. For example, the
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
index afc9d78..488a542 100644
--- a/core/java/android/os/health/UidHealthStats.java
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -43,14 +43,14 @@
 
     /**
      * How many milliseconds this statistics report covers in wall-clock time while the
-     * device was on battery including both screen-on and screen-off time.
+     * device was on battery including only screen-off time.
      */
     @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
     public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = HealthKeys.BASE_UID + 3;
 
     /**
      * How many milliseconds this statistics report covers that the CPU was running while the
-     * device was on battery including both screen-on and screen-off time.
+     * device was on battery including only screen-off time.
      */
     @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
     public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = HealthKeys.BASE_UID + 4;
@@ -65,7 +65,7 @@
 
     /**
      * Key for a TimerStat for the times a
-     * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK full wake lock}
+     * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK partial wake lock}
      * was acquired for this uid.
      */
     @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
diff --git a/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
new file mode 100644
index 0000000..cb521c8
--- /dev/null
+++ b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
@@ -0,0 +1,8 @@
+ewol@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/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 25e3a4f..6644f1e 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -181,6 +181,22 @@
     public static final String NAMESPACE_CONNECTIVITY = "connectivity";
 
     /**
+     * Namespace for CaptivePortalLogin module.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_CAPTIVEPORTALLOGIN = "captive_portal_login";
+
+    /**
+     * Namespace for Tethering module.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_TETHERING = "tethering";
+
+    /**
      * Namespace for content capture feature used by on-device machine intelligence
      * to provide suggestions in a privacy-safe manner.
      *
@@ -606,6 +622,14 @@
     public static final String NAMESPACE_GAME_OVERLAY = "game_overlay";
 
     /**
+     * Namespace for Android Virtualization Framework related features accessible by native code.
+     *
+     * @hide
+     */
+    public static final String NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE =
+            "virtualization_framework_native";
+
+    /**
      * Namespace for Constrain Display APIs related features.
      *
      * @hide
diff --git a/core/java/android/security/attestationverification/OWNERS b/core/java/android/security/attestationverification/OWNERS
new file mode 100644
index 0000000..80a1f44
--- /dev/null
+++ b/core/java/android/security/attestationverification/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1111194
+
+dlm@google.com
+dkrahn@google.com
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index d39b56d..5b9d69c 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -191,20 +191,6 @@
     public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
 
     /**
-     * Listen for changes of the network signal strengths (cellular) always reported from modem,
-     * even in some situations such as the screen of the device is off.
-     *
-     * @see #onSignalStrengthsChanged
-     *
-     * @hide
-     * @deprecated Use TelephonyManager#setSignalStrengthUpdateRequest
-     * instead.
-     */
-    @Deprecated
-    @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
-    public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH          = 0x00000200;
-
-    /**
      * Listen for changes to observed cell info.
      *
      * Listening to this event requires the {@link Manifest.permission#READ_PHONE_STATE} and
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index bedad73..cb1cff9 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1041,10 +1041,6 @@
             eventList.add(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED);
         }
 
-        if ((eventMask & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
-            eventList.add(TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED);
-        }
-
         if ((eventMask & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
             eventList.add(TelephonyCallback.EVENT_CELL_INFO_CHANGED);
         }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index cda9b23..ba6f4eb 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -830,13 +830,45 @@
      * consuming content. May be consumed by system to set account globally.
      */
     public static final int KEYCODE_PROFILE_SWITCH = 288;
+    /** Key code constant: Video Application key #1. */
+    public static final int KEYCODE_VIDEO_APP_1 = 289;
+    /** Key code constant: Video Application key #2. */
+    public static final int KEYCODE_VIDEO_APP_2 = 290;
+    /** Key code constant: Video Application key #3. */
+    public static final int KEYCODE_VIDEO_APP_3 = 291;
+    /** Key code constant: Video Application key #4. */
+    public static final int KEYCODE_VIDEO_APP_4 = 292;
+    /** Key code constant: Video Application key #5. */
+    public static final int KEYCODE_VIDEO_APP_5 = 293;
+    /** Key code constant: Video Application key #6. */
+    public static final int KEYCODE_VIDEO_APP_6 = 294;
+    /** Key code constant: Video Application key #7. */
+    public static final int KEYCODE_VIDEO_APP_7 = 295;
+    /** Key code constant: Video Application key #8. */
+    public static final int KEYCODE_VIDEO_APP_8 = 296;
+    /** Key code constant: Featured Application key #1. */
+    public static final int KEYCODE_FEATURED_APP_1 = 297;
+    /** Key code constant: Featured Application key #2. */
+    public static final int KEYCODE_FEATURED_APP_2 = 298;
+    /** Key code constant: Featured Application key #3. */
+    public static final int KEYCODE_FEATURED_APP_3 = 299;
+    /** Key code constant: Featured Application key #4. */
+    public static final int KEYCODE_FEATURED_APP_4 = 300;
+    /** Key code constant: Demo Application key #1. */
+    public static final int KEYCODE_DEMO_APP_1 = 301;
+    /** Key code constant: Demo Application key #2. */
+    public static final int KEYCODE_DEMO_APP_2 = 302;
+    /** Key code constant: Demo Application key #3. */
+    public static final int KEYCODE_DEMO_APP_3 = 303;
+    /** Key code constant: Demo Application key #4. */
+    public static final int KEYCODE_DEMO_APP_4 = 304;
 
-    /**
+   /**
      * Integer value of the last KEYCODE. Increases as new keycodes are added to KeyEvent.
      * @hide
      */
     @TestApi
-    public static final int LAST_KEYCODE = KEYCODE_PROFILE_SWITCH;
+    public static final int LAST_KEYCODE = KEYCODE_DEMO_APP_4;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 8143cf9..ffce461 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -157,6 +157,7 @@
     private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
 
     private static native long[] nativeGetPhysicalDisplayIds();
+    private static native long nativeGetPrimaryPhysicalDisplayId();
     private static native IBinder nativeGetPhysicalDisplayToken(long physicalDisplayId);
     private static native IBinder nativeCreateDisplay(String name, boolean secure);
     private static native void nativeDestroyDisplay(IBinder displayToken);
@@ -2266,6 +2267,15 @@
     }
 
     /**
+     * Exposed to identify the correct display to apply the primary display orientation. Avoid using
+     * for any other purpose.
+     * @hide
+     */
+    public static long getPrimaryPhysicalDisplayId() {
+        return nativeGetPrimaryPhysicalDisplayId();
+    }
+
+    /**
      * @hide
      */
     public static IBinder getPhysicalDisplayToken(long physicalDisplayId) {
diff --git a/core/java/com/android/internal/compat/OWNERS b/core/java/com/android/internal/compat/OWNERS
index cfd0a4b..ee3086a 100644
--- a/core/java/com/android/internal/compat/OWNERS
+++ b/core/java/com/android/internal/compat/OWNERS
@@ -1,6 +1 @@
-# Use this reviewer by default.
-platform-compat-eng+reviews@google.com
-
-andreionea@google.com
-mathewi@google.com
-satayev@google.com
+include tools/platform-compat:/OWNERS
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
index 3f3c9bd..7c39118 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -25,17 +25,22 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.apex.ApexInfo;
+import com.android.apex.XmlParser;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.om.OverlayConfigParser.OverlayPartition;
 import com.android.internal.content.om.OverlayConfigParser.ParsedConfiguration;
 import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.TriConsumer;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
-import java.util.function.BiConsumer;
+import java.util.List;
 import java.util.function.Supplier;
 
 /**
@@ -73,7 +78,7 @@
     public interface PackageProvider {
 
         /** Performs the given action for each package. */
-        void forEachPackage(BiConsumer<ParsingPackageRead, Boolean> p);
+        void forEachPackage(TriConsumer<ParsingPackageRead, Boolean, File> p);
     }
 
     private static final Comparator<ParsedConfiguration> sStaticOverlayComparator = (c1, c2) -> {
@@ -115,6 +120,8 @@
                             p)));
         }
 
+        ArrayMap<Integer, List<String>> activeApexesPerPartition = getActiveApexes(partitions);
+
         boolean foundConfigFile = false;
         ArrayList<ParsedOverlayInfo> packageManagerOverlayInfos = null;
 
@@ -123,7 +130,9 @@
             final OverlayPartition partition = partitions.get(i);
             final OverlayScanner scanner = (scannerFactory == null) ? null : scannerFactory.get();
             final ArrayList<ParsedConfiguration> partitionOverlays =
-                    OverlayConfigParser.getConfigurations(partition, scanner);
+                    OverlayConfigParser.getConfigurations(partition, scanner,
+                            activeApexesPerPartition.getOrDefault(partition.type,
+                                    Collections.emptyList()));
             if (partitionOverlays != null) {
                 foundConfigFile = true;
                 overlays.addAll(partitionOverlays);
@@ -145,7 +154,8 @@
                 // Filter out overlays not present in the partition.
                 partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos);
                 for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) {
-                    if (!partition.containsFile(partitionOverlayInfos.get(j).path)) {
+                    if (!partition.containsFile(partitionOverlayInfos.get(j)
+                            .getOriginalPartitionPath())) {
                         partitionOverlayInfos.remove(j);
                     }
                 }
@@ -292,16 +302,49 @@
     private static ArrayList<ParsedOverlayInfo> getOverlayPackageInfos(
             @NonNull PackageProvider packageManager) {
         final ArrayList<ParsedOverlayInfo> overlays = new ArrayList<>();
-        packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem) -> {
+        packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem,
+                @Nullable File preInstalledApexPath) -> {
             if (p.getOverlayTarget() != null && isSystem) {
                 overlays.add(new ParsedOverlayInfo(p.getPackageName(), p.getOverlayTarget(),
                         p.getTargetSdkVersion(), p.isOverlayIsStatic(), p.getOverlayPriority(),
-                        new File(p.getBaseApkPath())));
+                        new File(p.getBaseApkPath()), preInstalledApexPath));
             }
         });
         return overlays;
     }
 
+    /** Returns a map of PartitionType to List of active APEX module names. */
+    @NonNull
+    private static ArrayMap<Integer, List<String>> getActiveApexes(
+            @NonNull List<OverlayPartition> partitions) {
+        // An Overlay in an APEX, which is an update of an APEX in a given partition,
+        // is considered as belonging to that partition.
+        ArrayMap<Integer, List<String>> result = new ArrayMap<>();
+        for (OverlayPartition partition : partitions) {
+            result.put(partition.type, new ArrayList<String>());
+        }
+        // Read from apex-info-list because ApexManager is not accessible to zygote.
+        File apexInfoList = new File("/apex/apex-info-list.xml");
+        if (apexInfoList.exists() && apexInfoList.canRead()) {
+            try (FileInputStream stream = new FileInputStream(apexInfoList)) {
+                List<ApexInfo> apexInfos = XmlParser.readApexInfoList(stream).getApexInfo();
+                for (ApexInfo info : apexInfos) {
+                    if (info.getIsActive()) {
+                        for (OverlayPartition partition : partitions) {
+                            if (partition.containsPath(info.getPreinstalledModulePath())) {
+                                result.get(partition.type).add(info.getModuleName());
+                                break;
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                Log.w(TAG, "Error reading apex-info-list: " + e);
+            }
+        }
+        return result;
+    }
+
     /** Represents a single call to idmap create-multiple. */
     @VisibleForTesting
     public static class IdmapInvocation {
diff --git a/core/java/com/android/internal/content/om/OverlayConfigParser.java b/core/java/com/android/internal/content/om/OverlayConfigParser.java
index a86e595..d48c2e7 100644
--- a/core/java/com/android/internal/content/om/OverlayConfigParser.java
+++ b/core/java/com/android/internal/content/om/OverlayConfigParser.java
@@ -40,6 +40,7 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Responsible for parsing configurations of Runtime Resource Overlays that control mutability,
@@ -192,13 +193,19 @@
      */
     @Nullable
     static ArrayList<ParsedConfiguration> getConfigurations(
-            @NonNull OverlayPartition partition, @Nullable OverlayScanner scanner) {
-        if (partition.getOverlayFolder() == null) {
-            return null;
+            @NonNull OverlayPartition partition, @Nullable OverlayScanner scanner,
+            @NonNull List<String> activeApexes) {
+        if (scanner != null) {
+            if (partition.getOverlayFolder() != null) {
+                scanner.scanDir(partition.getOverlayFolder());
+            }
+            for (String apex : activeApexes) {
+                scanner.scanDir(new File("/apex/" + apex + "/overlay/"));
+            }
         }
 
-        if (scanner != null) {
-            scanner.scanDir(partition.getOverlayFolder());
+        if (partition.getOverlayFolder() == null) {
+            return null;
         }
 
         final File configFile = new File(partition.getOverlayFolder(), CONFIG_DEFAULT_FILENAME);
diff --git a/core/java/com/android/internal/content/om/OverlayScanner.java b/core/java/com/android/internal/content/om/OverlayScanner.java
index 6b5cb8d..138d1ce 100644
--- a/core/java/com/android/internal/content/om/OverlayScanner.java
+++ b/core/java/com/android/internal/content/om/OverlayScanner.java
@@ -47,23 +47,38 @@
         public final boolean isStatic;
         public final int priority;
         public final File path;
+        @Nullable public final File preInstalledApexPath;
 
         public ParsedOverlayInfo(String packageName, String targetPackageName,
-                int targetSdkVersion, boolean isStatic, int priority, File path) {
+                int targetSdkVersion, boolean isStatic, int priority, File path,
+                @Nullable File preInstalledApexPath) {
             this.packageName = packageName;
             this.targetPackageName = targetPackageName;
             this.targetSdkVersion = targetSdkVersion;
             this.isStatic = isStatic;
             this.priority = priority;
             this.path = path;
+            this.preInstalledApexPath = preInstalledApexPath;
         }
 
         @Override
         public String toString() {
             return getClass().getSimpleName() + String.format("{packageName=%s"
                             + ", targetPackageName=%s, targetSdkVersion=%s, isStatic=%s"
-                            + ", priority=%s, path=%s}",
-                    packageName, targetPackageName, targetSdkVersion, isStatic, priority, path);
+                            + ", priority=%s, path=%s, preInstalledApexPath=%s}",
+                    packageName, targetPackageName, targetSdkVersion, isStatic,
+                    priority, path, preInstalledApexPath);
+        }
+
+        /**
+         * Retrieves the path of the overlay in its original installation partition.
+         *
+         * An Overlay in an APEX, which is an update of an APEX in a given partition,
+         * is considered as belonging to that partition.
+         */
+        @NonNull
+        public File getOriginalPartitionPath() {
+            return preInstalledApexPath != null ? preInstalledApexPath : path;
         }
     }
 
@@ -138,6 +153,6 @@
         return apkLite.getTargetPackageName() == null ? null :
                 new ParsedOverlayInfo(apkLite.getPackageName(), apkLite.getTargetPackageName(),
                         apkLite.getTargetSdkVersion(), apkLite.isOverlayIsStatic(),
-                        apkLite.getOverlayPriority(), new File(apkLite.getPath()));
+                        apkLite.getOverlayPriority(), new File(apkLite.getPath()), null);
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8c63f38..630851d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12143,7 +12143,7 @@
             rxTimeMs = info.getControllerRxTimeMillis();
             txTimeMs = info.getControllerTxTimeMillis();
             energy = info.getControllerEnergyUsed();
-            if (info.getUidTraffic() != null) {
+            if (!info.getUidTraffic().isEmpty()) {
                 for (UidTraffic traffic : info.getUidTraffic()) {
                     uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
                     uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
@@ -12294,10 +12294,10 @@
         long totalTxBytes = 0;
         long totalRxBytes = 0;
 
-        final UidTraffic[] uidTraffic = info.getUidTraffic();
-        final int numUids = uidTraffic != null ? uidTraffic.length : 0;
+        final List<UidTraffic> uidTraffic = info.getUidTraffic();
+        final int numUids = uidTraffic.size();
         for (int i = 0; i < numUids; i++) {
-            final UidTraffic traffic = uidTraffic[i];
+            final UidTraffic traffic = uidTraffic.get(i);
             final long rxBytes = traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(
                     traffic.getUid());
             final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(
@@ -12320,7 +12320,7 @@
         if ((totalTxBytes != 0 || totalRxBytes != 0) && (leftOverRxTimeMs != 0
                 || leftOverTxTimeMs != 0)) {
             for (int i = 0; i < numUids; i++) {
-                final UidTraffic traffic = uidTraffic[i];
+                final UidTraffic traffic = uidTraffic.get(i);
                 final int uid = traffic.getUid();
                 final long rxBytes =
                         traffic.getRxBytes() - mLastBluetoothActivityInfo.uidRxBytes.get(uid);
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index d347f2e..8b0411d 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -80,15 +80,20 @@
      */
     public static ClassLoader createClassLoader(String dexPath,
             String librarySearchPath, ClassLoader parent, String classloaderName,
-            List<ClassLoader> sharedLibraries) {
+            List<ClassLoader> sharedLibraries, List<ClassLoader> sharedLibrariesLoadedAfter) {
         ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null)
                 ? null
                 : sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]);
+        ClassLoader[] arrayOfSharedLibrariesLoadedAfterApp = (sharedLibrariesLoadedAfter == null)
+                ? null
+                : sharedLibrariesLoadedAfter.toArray(
+                        new ClassLoader[sharedLibrariesLoadedAfter.size()]);
         if (isPathClassLoaderName(classloaderName)) {
-            return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries);
+            return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries,
+                    arrayOfSharedLibrariesLoadedAfterApp);
         } else if (isDelegateLastClassLoaderName(classloaderName)) {
             return new DelegateLastClassLoader(dexPath, librarySearchPath, parent,
-                    arrayOfSharedLibraries);
+                    arrayOfSharedLibraries, arrayOfSharedLibrariesLoadedAfterApp);
         }
 
         throw new AssertionError("Invalid classLoaderName: " + classloaderName);
@@ -102,20 +107,20 @@
             String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
             int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) {
         return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath,
-            parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null);
+            parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null, null);
     }
 
-
     /**
      * Create a ClassLoader and initialize a linker-namespace for it.
      */
     public static ClassLoader createClassLoader(String dexPath,
             String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
             int targetSdkVersion, boolean isNamespaceShared, String classLoaderName,
-            List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries) {
+            List<ClassLoader> sharedLibraries, List<String> nativeSharedLibraries,
+            List<ClassLoader> sharedLibrariesAfter) {
 
         final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
-                classLoaderName, sharedLibraries);
+                classLoaderName, sharedLibraries, sharedLibrariesAfter);
 
         String sonameList = "";
         if (nativeSharedLibraries != null) {
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index 5ec882c..475caa5 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -63,6 +63,8 @@
     public int argi4;
     public int argi5;
     public int argi6;
+    public long argl1;
+    public long argl2;
 
     private SomeArgs() {
         /* do nothing - reduce visibility */
@@ -129,5 +131,7 @@
         argi4 = 0;
         argi5 = 0;
         argi6 = 0;
+        argl1 = 0;
+        argl2 = 0;
     }
 }
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index be9aaaf..0d530f6 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -604,6 +604,25 @@
     return thisParcel->compareData(*otherParcel);
 }
 
+static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
+                                                     jint thisOffset, jlong otherNativePtr,
+                                                     jint otherOffset, jint length) {
+    Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
+    LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
+
+    Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
+    LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
+
+    int result;
+    status_t err =
+            thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
+    if (err != NO_ERROR) {
+        signalExceptionForError(env, clazz, err);
+        return JNI_FALSE;
+    }
+    return (result == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
 static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
                                           jlong otherNativePtr, jint offset, jint length)
 {
@@ -841,6 +860,7 @@
     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
     {"nativeUnmarshall",          "(J[BII)V", (void*)android_os_Parcel_unmarshall},
     {"nativeCompareData",         "(JJ)I", (void*)android_os_Parcel_compareData},
+    {"nativeCompareDataInRange",  "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
     {"nativeAppendFrom",          "(JJII)V", (void*)android_os_Parcel_appendFrom},
     // @CriticalNative
     {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 793b4eb..61b91dd 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -959,8 +959,7 @@
     return IPCThreadState::self()->getCallingUid();
 }
 
-static jboolean android_os_Binder_isHandlingTransaction()
-{
+static jboolean android_os_Binder_isDirectlyHandlingTransaction() {
     return getCurrentServingCall() == BinderCallType::BINDER;
 }
 
@@ -1056,6 +1055,7 @@
 
 // ----------------------------------------------------------------------------
 
+// clang-format off
 static const JNINativeMethod gBinderMethods[] = {
      /* name, signature, funcPtr */
     // @CriticalNative
@@ -1063,7 +1063,7 @@
     // @CriticalNative
     { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
     // @CriticalNative
-    { "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction },
+    { "isDirectlyHandlingTransaction", "()Z", (void*)android_os_Binder_isDirectlyHandlingTransaction },
     // @CriticalNative
     { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
     // @CriticalNative
@@ -1088,6 +1088,7 @@
     { "getExtension", "()Landroid/os/IBinder;", (void*)android_os_Binder_getExtension },
     { "setExtension", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension },
 };
+// clang-format on
 
 const char* const kBinderPathName = "android/os/Binder";
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 8d12df22..e477183 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -889,6 +889,12 @@
     return array;
 }
 
+static jlong nativeGetPrimaryPhysicalDisplayId(JNIEnv* env, jclass clazz) {
+    PhysicalDisplayId displayId;
+    SurfaceComposerClient::getPrimaryPhysicalDisplayId(&displayId);
+    return static_cast<jlong>(displayId.value);
+}
+
 static jobject nativeGetPhysicalDisplayToken(JNIEnv* env, jclass clazz, jlong physicalDisplayId) {
     sp<IBinder> token =
             SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId(physicalDisplayId));
@@ -1879,6 +1885,8 @@
             (void*)nativeReleaseFrameRateFlexibilityToken },
     {"nativeGetPhysicalDisplayIds", "()[J",
             (void*)nativeGetPhysicalDisplayIds },
+    {"nativeGetPrimaryPhysicalDisplayId", "()J",
+            (void*)nativeGetPrimaryPhysicalDisplayId },
     {"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;",
             (void*)nativeGetPhysicalDisplayToken },
     {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index be82879..ef6fd7d 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -36,6 +36,7 @@
 #include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <linux/fs.h>
 
 #include <memory>
 
@@ -253,6 +254,16 @@
         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/fd_utils.cpp b/core/jni/fd_utils.cpp
index 6f5cc53..40f6e4f 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -138,6 +138,14 @@
         return true;
     }
 
+    // Allow Runtime Resource Overlays inside APEXes.
+    static const char* kOverlayPathSuffix = "/overlay";
+    if (android::base::StartsWith(path, kApexPrefix) &&
+        android::base::EndsWith(android::base::Dirname(path), kOverlayPathSuffix) &&
+        android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) {
+        return true;
+    }
+
     static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
     static const char* kOverlayIdmapSuffix = ".apk@idmap";
     if (android::base::StartsWith(path, kOverlayIdmapPrefix) &&
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index fa1e9d4..a62ddd0 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -351,6 +351,7 @@
     optional bool translucent = 30;
     optional bool pip_auto_enter_enabled = 31;
     optional bool in_size_compat_mode = 32;
+    optional float min_aspect_ratio = 33;
 }
 
 /* represents WindowToken */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bd89578..d727a55 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -252,6 +252,11 @@
         android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
     <protected-broadcast
         android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONF_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.action.TETHERING_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
@@ -1976,6 +1981,14 @@
         android:label="@string/permlab_uwb_ranging"
         android:protectionLevel="dangerous" />
 
+    <!-- Required to be able to advertise and connect to nearby devices via Wi-Fi.
+         <p>Protection level: dangerous -->
+    <permission android:name="android.permission.NEARBY_WIFI_DEVICES"
+                android:permissionGroup="android.permission-group.UNDEFINED"
+                android:description="@string/permdesc_nearby_wifi_devices"
+                android:label="@string/permlab_nearby_wifi_devices"
+                android:protectionLevel="dangerous" />
+
     <!-- @SystemApi @TestApi Allows an application to suspend other apps, which will prevent the
          user from using them until they are unsuspended.
          @hide
@@ -2386,7 +2399,7 @@
     <permission android:name="android.permission.READ_ACTIVE_EMERGENCY_SESSION"
         android:protectionLevel="signature" />
 
-    <!-- Allows listen permission to always reported signal strength.
+    <!-- Allows listen permission to always reported system signal strength.
          @hide Used internally. -->
     <permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH"
         android:protectionLevel="signature" />
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 684202b..165dcad 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -28,3 +28,6 @@
 
 # Multiuser
 per-file res/xml/config_user_types.xml = file:/MULTIUSER_OWNERS
+
+# Car
+per-file res/values/dimens_car.xml = file:/platform/packages/services/Car:/OWNERS
\ No newline at end of file
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a5f5051..dc92e10 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1984,6 +1984,22 @@
         <enum name="KEYCODE_THUMBS_UP" value="286" />
         <enum name="KEYCODE_THUMBS_DOWN" value="287" />
         <enum name="KEYCODE_PROFILE_SWITCH" value="288" />
+        <enum name="KEYCODE_VIDEO_APP_1" value="289" />
+        <enum name="KEYCODE_VIDEO_APP_2" value="290" />
+        <enum name="KEYCODE_VIDEO_APP_3" value="291" />
+        <enum name="KEYCODE_VIDEO_APP_4" value="292" />
+        <enum name="KEYCODE_VIDEO_APP_5" value="293" />
+        <enum name="KEYCODE_VIDEO_APP_6" value="294" />
+        <enum name="KEYCODE_VIDEO_APP_7" value="295" />
+        <enum name="KEYCODE_VIDEO_APP_8" value="296" />
+        <enum name="KEYCODE_FEATURED_APP_1" value="297" />
+        <enum name="KEYCODE_FEATURED_APP_2" value="298" />
+        <enum name="KEYCODE_FEATURED_APP_3" value="299" />
+        <enum name="KEYCODE_FEATURED_APP_4" value="300" />
+        <enum name="KEYCODE_DEMO_APP_1" value="301" />
+        <enum name="KEYCODE_DEMO_APP_2" value="302" />
+        <enum name="KEYCODE_DEMO_APP_3" value="303" />
+        <enum name="KEYCODE_DEMO_APP_4" value="304" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aa05b13..8496a47 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5047,6 +5047,14 @@
          to 0, the seconds hand will be disabled. -->
     <integer name="config_defaultAnalogClockSecondsHandFps">1</integer>
 
+    <!-- List of shared library packages that should be loaded by the classloader after the
+         code and resources provided by applications. This value will be set by the manufacturer  -->
+    <string-array name="config_sharedLibrariesLoadedAfterApp" translatable="false">
+    </string-array>
+
     <!-- the number of the max cached processes in the system. -->
     <integer name="config_customizedMaxCachedProcesses">32</integer>
+
+    <!-- Whether this device should support taking app snapshots on closure -->
+    <bool name="config_disableTaskSnapshots">false</bool>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a99a220..a350d14 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1488,6 +1488,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=120]-->
     <string name="permdesc_uwb_ranging">Allow the app to determine relative position between nearby Ultra-Wideband devices</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50]-->
+    <string name="permlab_nearby_wifi_devices">interact with nearby Wi\u2011Fi devices</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=120]-->
+    <string name="permdesc_nearby_wifi_devices">Allows the app to advertise, connect, and determine the relative position of nearby Wi\u2011Fi devices</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_preferredPaymentInfo">Preferred NFC Payment Service Information</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 092be40..d06dafe 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4403,7 +4403,7 @@
   <java-symbol type="string" name="view_and_control_notification_title" />
   <java-symbol type="string" name="view_and_control_notification_content" />
   <java-symbol type="array" name="config_accessibility_allowed_install_source" />
-  
+
   <!-- Translation -->
   <java-symbol type="string" name="ui_translation_accessibility_translated_text" />
   <java-symbol type="string" name="ui_translation_accessibility_translation_finished" />
@@ -4425,5 +4425,12 @@
 
   <java-symbol type="bool" name="config_volumeShowRemoteSessions" />
 
+  <!-- List of shared library packages that should be loaded by the classloader after the
+       code and resources provided by applications. -->
+  <java-symbol type="array" name="config_sharedLibrariesLoadedAfterApp" />
+
   <java-symbol type="integer" name="config_customizedMaxCachedProcesses" />
+
+  <java-symbol type="bool" name="config_disableTaskSnapshots" />
+
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index f1c66c5..4c20ae1 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -105,6 +105,9 @@
          http://www.tja.ee/public/documents/Elektrooniline_side/Oigusaktid/ENG/Estonian_Numbering_Plan_annex_06_09_2010.mht -->
     <shortcode country="ee" pattern="1\\d{2,4}" premium="90\\d{5}|15330|1701[0-3]" free="116\\d{3}|95034" />
 
+    <!-- Egypt: 4 digits, known codes listed -->
+    <shortcode country="eg" pattern="\\d{4}" free="1499" />
+
     <!-- Spain: 5-6 digits: 25xxx, 27xxx, 280xx, 35xxx, 37xxx, 795xxx, 797xxx, 995xxx, 997xxx, plus EU.
          http://www.legallink.es/?q=en/content/which-current-regulatory-status-premium-rate-services-spain -->
     <shortcode country="es" premium="[23][57]\\d{3}|280\\d{2}|[79]9[57]\\d{3}" free="116\\d{3}|22791|222145|22189" />
@@ -196,7 +199,7 @@
     <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223|1662" />
 
     <!-- Nigeria -->
-    <shortcode country="ng" pattern="\\d{1,5}" free="2441|55019" />
+    <shortcode country="ng" pattern="\\d{1,5}" free="2441|55020" />
 
     <!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
     <shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" free="2171" />
diff --git a/core/tests/PlatformCompatFramework/OWNERS b/core/tests/PlatformCompatFramework/OWNERS
index cfd0a4b..ee3086a 100644
--- a/core/tests/PlatformCompatFramework/OWNERS
+++ b/core/tests/PlatformCompatFramework/OWNERS
@@ -1,6 +1 @@
-# Use this reviewer by default.
-platform-compat-eng+reviews@google.com
-
-andreionea@google.com
-mathewi@google.com
-satayev@google.com
+include tools/platform-compat:/OWNERS
diff --git a/core/tests/bluetoothtests/Android.bp b/core/tests/bluetoothtests/Android.bp
index a2e4dff..68416dd 100644
--- a/core/tests/bluetoothtests/Android.bp
+++ b/core/tests/bluetoothtests/Android.bp
@@ -15,7 +15,10 @@
         "android.test.runner",
         "android.test.base",
     ],
-    static_libs: ["junit"],
+    static_libs: [
+        "junit",
+        "modules-utils-bytesmatcher",
+    ],
     platform_apis: true,
     certificate: "platform",
 }
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
index c287ea9..4e817d4 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
@@ -16,11 +16,11 @@
 
 package android.bluetooth.le;
 
-import android.os.BytesMatcher;
 import android.os.ParcelUuid;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.internal.util.HexDump;
+import com.android.modules.utils.BytesMatcher;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java
index ddd0070..09f4840 100644
--- a/core/tests/coretests/src/android/os/BundleTest.java
+++ b/core/tests/coretests/src/android/os/BundleTest.java
@@ -273,16 +273,21 @@
         Parcelable p1 = new CustomParcelable(13, "Tiramisu");
         Parcelable p2 = new CustomParcelable(13, "Tiramisu");
         Bundle a = new Bundle();
-        a.putParcelable("key", p1);
+        a.putParcelable("key1", p1);
         a.readFromParcel(getParcelledBundle(a));
         a.setClassLoader(getClass().getClassLoader());
         Bundle b = new Bundle();
-        b.putParcelable("key", p2);
+        // Adding extra element so that the position of the elements of interest in their respective
+        // source parcels are different so we can cover that case of Parcel.compareData(). We'll
+        // remove the element later so the map is equal.
+        b.putString("key0", "string");
+        b.putParcelable("key1", p2);
         b.readFromParcel(getParcelledBundle(b));
         b.setClassLoader(getClass().getClassLoader());
-        // 2 lazy values with identical parcels inside
         a.isEmpty();
         b.isEmpty();
+        b.remove("key0");
+        // 2 lazy values with identical parcels inside
 
         assertTrue(Bundle.kindofEquals(a, b));
     }
diff --git a/core/tests/coretests/src/android/os/BytesMatcherTest.java b/core/tests/coretests/src/android/os/BytesMatcherTest.java
deleted file mode 100644
index b28e309..0000000
--- a/core/tests/coretests/src/android/os/BytesMatcherTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2021 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.os;
-
-import static com.android.internal.util.HexDump.hexStringToByteArray;
-
-import android.bluetooth.BluetoothUuid;
-import android.net.MacAddress;
-
-import androidx.test.filters.SmallTest;
-
-import junit.framework.TestCase;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-@SmallTest
-public class BytesMatcherTest extends TestCase {
-    @Test
-    public void testEmpty() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("");
-        assertFalse(matcher.test(hexStringToByteArray("cafe")));
-        assertFalse(matcher.test(hexStringToByteArray("")));
-    }
-
-    @Test
-    public void testExact() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("+cafe");
-        assertTrue(matcher.test(hexStringToByteArray("cafe")));
-        assertFalse(matcher.test(hexStringToByteArray("beef")));
-        assertFalse(matcher.test(hexStringToByteArray("ca")));
-        assertFalse(matcher.test(hexStringToByteArray("cafe00")));
-    }
-
-    @Test
-    public void testMask() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("+cafe/ff00");
-        assertTrue(matcher.test(hexStringToByteArray("cafe")));
-        assertTrue(matcher.test(hexStringToByteArray("ca88")));
-        assertFalse(matcher.test(hexStringToByteArray("beef")));
-        assertFalse(matcher.test(hexStringToByteArray("ca")));
-        assertFalse(matcher.test(hexStringToByteArray("cafe00")));
-    }
-
-    @Test
-    public void testPrefix() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("⊆cafe,⊆beef/ff00");
-        assertTrue(matcher.test(hexStringToByteArray("cafe")));
-        assertFalse(matcher.test(hexStringToByteArray("caff")));
-        assertTrue(matcher.test(hexStringToByteArray("cafecafe")));
-        assertFalse(matcher.test(hexStringToByteArray("ca")));
-        assertTrue(matcher.test(hexStringToByteArray("beef")));
-        assertTrue(matcher.test(hexStringToByteArray("beff")));
-        assertTrue(matcher.test(hexStringToByteArray("beffbeff")));
-        assertFalse(matcher.test(hexStringToByteArray("be")));
-    }
-
-    @Test
-    public void testMacAddress() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("+cafe00112233/ffffff000000");
-        assertTrue(matcher.testMacAddress(
-                MacAddress.fromString("ca:fe:00:00:00:00")));
-        assertFalse(matcher.testMacAddress(
-                MacAddress.fromString("f0:0d:00:00:00:00")));
-    }
-
-    @Test
-    public void testBluetoothUuid() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("+cafe/ff00");
-        assertTrue(matcher.testBluetoothUuid(
-                BluetoothUuid.parseUuidFrom(hexStringToByteArray("cafe"))));
-        assertFalse(matcher.testBluetoothUuid(
-                BluetoothUuid.parseUuidFrom(hexStringToByteArray("beef"))));
-    }
-
-    /**
-     * Verify that single matcher can be configured to match Bluetooth UUIDs of
-     * varying lengths.
-     */
-    @Test
-    public void testBluetoothUuid_Mixed() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("+aaaa/ff00,+bbbbbbbb/ffff0000");
-        assertTrue(matcher.testBluetoothUuid(
-                BluetoothUuid.parseUuidFrom(hexStringToByteArray("aaaa"))));
-        assertFalse(matcher.testBluetoothUuid(
-                BluetoothUuid.parseUuidFrom(hexStringToByteArray("bbbb"))));
-        assertTrue(matcher.testBluetoothUuid(
-                BluetoothUuid.parseUuidFrom(hexStringToByteArray("bbbbbbbb"))));
-        assertFalse(matcher.testBluetoothUuid(
-                BluetoothUuid.parseUuidFrom(hexStringToByteArray("aaaaaaaa"))));
-    }
-
-    @Test
-    public void testSerialize_Empty() throws Exception {
-        BytesMatcher matcher = new BytesMatcher();
-        matcher = BytesMatcher.decode(BytesMatcher.encode(matcher));
-
-        // Also very empty and null values
-        BytesMatcher.decode("");
-        BytesMatcher.decode(null);
-    }
-
-    @Test
-    public void testSerialize_Exact() throws Exception {
-        BytesMatcher matcher = new BytesMatcher();
-        matcher.addExactRejectRule(hexStringToByteArray("cafe00112233"),
-                hexStringToByteArray("ffffff000000"));
-        matcher.addExactRejectRule(hexStringToByteArray("beef00112233"),
-                null);
-        matcher.addExactAcceptRule(hexStringToByteArray("000000000000"),
-                hexStringToByteArray("000000000000"));
-
-        assertFalse(matcher.test(hexStringToByteArray("cafe00ffffff")));
-        assertFalse(matcher.test(hexStringToByteArray("beef00112233")));
-        assertTrue(matcher.test(hexStringToByteArray("beef00ffffff")));
-
-        // Bounce through serialization pass and confirm it still works
-        matcher = BytesMatcher.decode(BytesMatcher.encode(matcher));
-
-        assertFalse(matcher.test(hexStringToByteArray("cafe00ffffff")));
-        assertFalse(matcher.test(hexStringToByteArray("beef00112233")));
-        assertTrue(matcher.test(hexStringToByteArray("beef00ffffff")));
-    }
-
-    @Test
-    public void testSerialize_Prefix() throws Exception {
-        BytesMatcher matcher = new BytesMatcher();
-        matcher.addExactRejectRule(hexStringToByteArray("aa"), null);
-        matcher.addExactAcceptRule(hexStringToByteArray("bb"), null);
-        matcher.addPrefixAcceptRule(hexStringToByteArray("aa"), null);
-        matcher.addPrefixRejectRule(hexStringToByteArray("bb"), null);
-
-        assertFalse(matcher.test(hexStringToByteArray("aa")));
-        assertTrue(matcher.test(hexStringToByteArray("bb")));
-        assertTrue(matcher.test(hexStringToByteArray("aaaa")));
-        assertFalse(matcher.test(hexStringToByteArray("bbbb")));
-
-        // Bounce through serialization pass and confirm it still works
-        matcher = BytesMatcher.decode(BytesMatcher.encode(matcher));
-
-        assertFalse(matcher.test(hexStringToByteArray("aa")));
-        assertTrue(matcher.test(hexStringToByteArray("bb")));
-        assertTrue(matcher.test(hexStringToByteArray("aaaa")));
-        assertFalse(matcher.test(hexStringToByteArray("bbbb")));
-    }
-
-    @Test
-    public void testOrdering_RejectFirst() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("-ff/0f,+ff/f0");
-        assertFalse(matcher.test(hexStringToByteArray("ff")));
-        assertTrue(matcher.test(hexStringToByteArray("f0")));
-        assertFalse(matcher.test(hexStringToByteArray("0f")));
-    }
-
-    @Test
-    public void testOrdering_AcceptFirst() throws Exception {
-        BytesMatcher matcher = BytesMatcher.decode("+ff/f0,-ff/0f");
-        assertTrue(matcher.test(hexStringToByteArray("ff")));
-        assertTrue(matcher.test(hexStringToByteArray("f0")));
-        assertFalse(matcher.test(hexStringToByteArray("0f")));
-    }
-}
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index dcb3e2f..fdd278b 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -17,6 +17,9 @@
 package android.os;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
 
@@ -110,4 +113,130 @@
             assertEquals(string, p.readString16());
         }
     }
+
+    @Test
+    public void testCompareDataInRange_whenSameData() {
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(13);
+        pA.writeString("Tiramisu");
+        int length = pA.dataPosition() - iA;
+        Parcel pB = Parcel.obtain();
+        pB.writeString("Prefix");
+        int iB = pB.dataPosition();
+        pB.writeInt(13);
+        pB.writeString("Tiramisu");
+
+        assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
+    }
+
+    @Test
+    public void testCompareDataInRange_whenSameDataWithBinder() {
+        Binder binder = new Binder();
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(13);
+        pA.writeStrongBinder(binder);
+        pA.writeString("Tiramisu");
+        int length = pA.dataPosition() - iA;
+        Parcel pB = Parcel.obtain();
+        pB.writeString("Prefix");
+        int iB = pB.dataPosition();
+        pB.writeInt(13);
+        pB.writeStrongBinder(binder);
+        pB.writeString("Tiramisu");
+
+        assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
+    }
+
+    @Test
+    public void testCompareDataInRange_whenDifferentData() {
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(13);
+        pA.writeString("Tiramisu");
+        int length = pA.dataPosition() - iA;
+        Parcel pB = Parcel.obtain();
+        int iB = pB.dataPosition();
+        pB.writeString("Prefix");
+        pB.writeInt(13);
+        pB.writeString("Tiramisu");
+
+        assertFalse(Parcel.compareData(pA, iA, pB, iB, length));
+    }
+
+    @Test
+    public void testCompareDataInRange_whenLimitOutOfBounds_throws() {
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(12);
+        pA.writeString("Tiramisu");
+        int length = pA.dataPosition() - iA;
+        Parcel pB = Parcel.obtain();
+        pB.writeString("Prefix");
+        int iB = pB.dataPosition();
+        pB.writeInt(13);
+        pB.writeString("Tiramisu");
+        pB.writeInt(-1);
+
+        assertThrows(IllegalArgumentException.class,
+                () -> Parcel.compareData(pA, iA + length, pB, iB, 1));
+        assertThrows(IllegalArgumentException.class,
+                () -> Parcel.compareData(pA, iA, pB, pB.dataSize(), 1));
+        assertThrows(IllegalArgumentException.class,
+                () -> Parcel.compareData(pA, iA, pB, iB, length + 1));
+        assertThrows(IllegalArgumentException.class,
+                () -> Parcel.compareData(pA, iA + length + 1, pB, iB, 0));
+        assertThrows(IllegalArgumentException.class,
+                () -> Parcel.compareData(pA, iA, pB, iB + pB.dataSize() + 1, 0));
+    }
+
+    @Test
+    public void testCompareDataInRange_whenLengthZero() {
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(12);
+        pA.writeString("Tiramisu");
+        int length = pA.dataPosition() - iA;
+        Parcel pB = Parcel.obtain();
+        pB.writeString("Prefix");
+        int iB = pB.dataPosition();
+        pB.writeInt(13);
+        pB.writeString("Tiramisu");
+
+        assertTrue(Parcel.compareData(pA, 0, pB, iB, 0));
+        assertTrue(Parcel.compareData(pA, iA + length, pB, iB, 0));
+        assertTrue(Parcel.compareData(pA, iA, pB, pB.dataSize(), 0));
+    }
+
+    @Test
+    public void testCompareDataInRange_whenNegativeLength_throws() {
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(12);
+        pA.writeString("Tiramisu");
+        Parcel pB = Parcel.obtain();
+        pB.writeString("Prefix");
+        int iB = pB.dataPosition();
+        pB.writeInt(13);
+        pB.writeString("Tiramisu");
+
+        assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, iA, pB, iB, -1));
+    }
+
+    @Test
+    public void testCompareDataInRange_whenNegativeOffset_throws() {
+        Parcel pA = Parcel.obtain();
+        int iA = pA.dataPosition();
+        pA.writeInt(12);
+        pA.writeString("Tiramisu");
+        Parcel pB = Parcel.obtain();
+        pB.writeString("Prefix");
+        int iB = pB.dataPosition();
+        pB.writeInt(13);
+        pB.writeString("Tiramisu");
+
+        assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0));
+        assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0));
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
index c50c818..e2c40d8 100644
--- a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
+++ b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigIterationRule.java
@@ -28,6 +28,7 @@
 import com.android.internal.content.om.OverlayConfig.PackageProvider;
 import com.android.internal.content.om.OverlayScanner;
 import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+import com.android.internal.util.function.TriConsumer;
 
 import org.junit.Assert;
 import org.junit.rules.TestRule;
@@ -39,7 +40,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Map;
-import java.util.function.BiConsumer;
 import java.util.function.Supplier;
 
 /**
@@ -73,7 +73,7 @@
             final File canonicalPath = new File(path.getCanonicalPath());
             mOverlayStubResults.put(canonicalPath, new ParsedOverlayInfo(
                     packageName, targetPackage, targetSdkVersion, isStatic, priority,
-                    canonicalPath));
+                    canonicalPath, null));
         } catch (IOException e) {
             Assert.fail("Failed to add overlay " + e);
         }
@@ -135,8 +135,8 @@
                 mIteration = Iteration.SYSTEM_SERVER;
                 doAnswer((InvocationOnMock invocation) -> {
                     final Object[] args = invocation.getArguments();
-                    final BiConsumer<ParsingPackageRead, Boolean> f =
-                            (BiConsumer<ParsingPackageRead, Boolean>) args[0];
+                    final TriConsumer<ParsingPackageRead, Boolean, File> f =
+                            (TriConsumer<ParsingPackageRead, Boolean, File>) args[0];
                     for (Map.Entry<File, ParsedOverlayInfo> overlay :
                             mOverlayStubResults.entrySet()) {
                         final ParsingPackageRead a = Mockito.mock(ParsingPackageRead.class);
@@ -147,7 +147,8 @@
                         when(a.isOverlayIsStatic()).thenReturn(info.isStatic);
                         when(a.getOverlayPriority()).thenReturn(info.priority);
                         when(a.getBaseApkPath()).thenReturn(info.path.getPath());
-                        f.accept(a, !info.path.getPath().contains("data/overlay"));
+                        f.accept(a, !info.path.getPath().contains("data/overlay"),
+                                /*preInstalledApexPath=*/null);
                     }
                     return null;
                 }).when(mPkgProvider).forEachPackage(any());
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index 5c84794..d361da9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -33,6 +33,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class BluetoothPowerCalculatorTest {
@@ -105,10 +107,10 @@
         final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000,
                 BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 7000, 5000, 0,
                 reportedEnergyUc);
-        info.setUidTraffic(new UidTraffic[]{
-                new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000),
-                new UidTraffic(APP_UID, 3000, 4000)
-        });
+        info.setUidTraffic(new ArrayList<UidTraffic>(){{
+                add(new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000));
+                add(new UidTraffic(APP_UID, 3000, 4000));
+            }});
         mStatsRule.getBatteryStats().updateBluetoothStateLocked(info,
                 consumedEnergyUc, 1000, 1000);
     }
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index b67988e..c94b3d5 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -499,6 +499,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "-1556507536": {
+      "message": "Passing transform hint %d for window %s%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "-1554521902": {
       "message": "showInsets(ime) was requested by different window: %s ",
       "level": "WARN",
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index c3b1cd74..b61ae12 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -1075,6 +1076,53 @@
         ProcessInitializer.sInstance.setContext(context);
     }
 
+    /**
+     * Returns true if HardwareRender will produce output.
+     *
+     * This value is global to the process and affects all uses of HardwareRenderer,
+     * including
+     * those created by the system such as those used by the View tree when using hardware
+     * accelerated rendering.
+     *
+     * Default is true in all production environments, but may be false in testing-focused
+     * emulators or if {@link #setDrawingEnabled(boolean)} is used.
+     *
+     * Backported from android T.
+     *
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public static boolean isDrawingEnabled() {
+        return nIsDrawingEnabled();
+    }
+
+    /**
+     * Toggles whether or not HardwareRenderer will produce drawing output globally in the current
+     * process.
+     *
+     * This applies to all HardwareRenderer instances, including those created by the platform such
+     * as those used by the system for hardware accelerated View rendering.
+     *
+     * The capability to disable drawing output is intended for test environments, primarily
+     * headless ones. By setting this to false, tests that launch activities or interact with Views
+     * can be quicker with less RAM usage by skipping the final step of View drawing. All View
+     * lifecycle events will occur as normal, only the final step of rendering on the GPU to the
+     * display will be skipped.
+     *
+     * This can be toggled on and off at will, so screenshot tests can also run in this same
+     * environment by toggling drawing back on and forcing a frame to be drawn such as by calling
+     * view#invalidate(). Once drawn and the screenshot captured, this can then be turned back off.
+     *
+     * Backported from android T.
+     *
+     * @hide
+     */
+    // TODO: Add link to androidx's Screenshot library for help with this
+    @UnsupportedAppUsage
+    public static void setDrawingEnabled(boolean drawingEnabled) {
+        nSetDrawingEnabled(drawingEnabled);
+    }
+
     private static final class DestroyContextRunnable implements Runnable {
         private final long mNativeInstance;
 
@@ -1393,4 +1441,8 @@
 
     private static native void nInitDisplayInfo(int width, int height, float refreshRate,
             int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos);
+
+    private static native void nSetDrawingEnabled(boolean drawingEnabled);
+
+    private static native boolean nIsDrawingEnabled();
 }
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index d80699d..f49e80a 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 909476
 # includes OWNERS from parent directories
 natanieljr@google.com
+pablogamito@google.com
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index 610fd80..17f5164 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 toddke@google.com
-rtmitchell@google.com
+zyy@google.com
 patb@google.com
 
 per-file CursorWindow.cpp=omakoto@google.com
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index b8fa55a..c804418 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -88,6 +88,8 @@
 
 StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI;
 
+DrawingEnabled Properties::drawingEnabled = DrawingEnabled::NotInitialized;
+
 bool Properties::load() {
     bool prevDebugLayersUpdates = debugLayersUpdates;
     bool prevDebugOverdraw = debugOverdraw;
@@ -141,6 +143,9 @@
 
     enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, false);
 
+    // call isDrawingEnabled to force loading of the property
+    isDrawingEnabled();
+
     return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
 }
 
@@ -210,5 +215,19 @@
     sRenderPipelineType = type;
 }
 
+void Properties::setDrawingEnabled(bool newDrawingEnabled) {
+    drawingEnabled = newDrawingEnabled ? DrawingEnabled::On : DrawingEnabled::Off;
+    enableRTAnimations = newDrawingEnabled;
+}
+
+bool Properties::isDrawingEnabled() {
+    if (drawingEnabled == DrawingEnabled::NotInitialized) {
+        bool drawingEnabledProp = base::GetBoolProperty(PROPERTY_DRAWING_ENABLED, true);
+        drawingEnabled = drawingEnabledProp ? DrawingEnabled::On : DrawingEnabled::Off;
+        enableRTAnimations = drawingEnabledProp;
+    }
+    return drawingEnabled == DrawingEnabled::On;
+}
+
 }  // namespace uirenderer
 }  // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 7df6e2c..7f9782b 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -187,6 +187,12 @@
  */
 #define PROPERTY_WEBVIEW_OVERLAYS_ENABLED "debug.hwui.webview_overlays_enabled"
 
+/**
+ * Property for globally GL drawing state. Can be overridden per process with
+ * setDrawingEnabled.
+ */
+#define PROPERTY_DRAWING_ENABLED "debug.hwui.drawing_enabled"
+
 ///////////////////////////////////////////////////////////////////////////////
 // Misc
 ///////////////////////////////////////////////////////////////////////////////
@@ -208,6 +214,8 @@
     UniformScale  // Uniform scale stretch everywhere
 };
 
+enum class DrawingEnabled { NotInitialized, On, Off };
+
 /**
  * Renderthread-only singleton which manages several static rendering properties. Most of these
  * are driven by system properties which are queried once at initialization, and again if init()
@@ -301,6 +309,11 @@
         stretchEffectBehavior = behavior;
     }
 
+    // Represents if drawing is enabled. Should only be Off in headless testing environments
+    static DrawingEnabled drawingEnabled;
+    static bool isDrawingEnabled();
+    static void setDrawingEnabled(bool enable);
+
 private:
     static StretchEffectBehavior stretchEffectBehavior;
     static ProfileType sProfileType;
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 54367b8..9e56584 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -817,6 +817,14 @@
     DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
 }
 
+static void android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv*, jclass, jboolean enabled) {
+    Properties::setDrawingEnabled(enabled);
+}
+
+static jboolean android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv*, jclass) {
+    return Properties::isDrawingEnabled();
+}
+
 // ----------------------------------------------------------------------------
 // HardwareRendererObserver
 // ----------------------------------------------------------------------------
@@ -953,6 +961,9 @@
         {"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
         {"isWebViewOverlaysEnabled", "()Z",
          (void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
+        {"nSetDrawingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDrawingEnabled},
+        {"nIsDrawingEnabled", "()Z", (void*)android_view_ThreadedRenderer_isDrawingEnabled},
+
 };
 
 static JavaVM* mJvm = nullptr;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2f3a509..bb0b135 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -256,7 +256,7 @@
 }
 
 void CanvasContext::allocateBuffers() {
-    if (mNativeSurface) {
+    if (mNativeSurface && Properties::isDrawingEnabled()) {
         ANativeWindow_tryAllocateBuffers(mNativeSurface->getNativeWindow());
     }
 }
@@ -480,7 +480,8 @@
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
 
-    if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
+    if (!Properties::isDrawingEnabled() ||
+        (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         if (auto grContext = getGrContext()) {
             // Submit to ensure that any texture uploads complete and Skia can
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6dbfcc3..2fed468 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -90,9 +90,17 @@
      *         and false otherwise (e.g. cache limits have been exceeded).
      */
     bool pinImages(std::vector<SkImage*>& mutableImages) {
+        if (!Properties::isDrawingEnabled()) {
+            return true;
+        }
         return mRenderPipeline->pinImages(mutableImages);
     }
-    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) { return mRenderPipeline->pinImages(images); }
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) {
+        if (!Properties::isDrawingEnabled()) {
+            return true;
+        }
+        return mRenderPipeline->pinImages(images);
+    }
 
     /**
      * Unpin any image that had be previously pinned to the GPU cache
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ed8cdb9..cf7039b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3255,6 +3255,54 @@
     }
 
     /**
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+    public void setHfpEnabled(boolean enable) {
+        AudioSystem.setParameters("hfp_enable=" + enable);
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+    public void setHfpVolume(int volume) {
+        AudioSystem.setParameters("hfp_volume=" + volume);
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+    public void setHfpSamplingRate(int rate) {
+        AudioSystem.setParameters("hfp_set_sampling_rate=" + rate);
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+    public void setBluetoothHeadsetProperties(@NonNull String name, boolean hasNrecEnabled,
+            boolean hasWbsEnabled) {
+        AudioSystem.setParameters("bt_headset_name=" + name
+                + ";bt_headset_nrec=" + (hasNrecEnabled ? "on" : "off")
+                + ";bt_wbs=" + (hasWbsEnabled ? "on" : "off"));
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+    public void setA2dpSuspended(boolean enable) {
+        AudioSystem.setParameters("A2dpSuspended=" + enable);
+    }
+
+    /**
      * Gets a variable number of parameter values from audio hardware.
      *
      * @param keys list of parameters
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 8b91536..de31a7f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -60,10 +60,10 @@
  with {@link MediaExtractor}, {@link MediaSync}, {@link MediaMuxer}, {@link MediaCrypto},
  {@link MediaDrm}, {@link Image}, {@link Surface}, and {@link AudioTrack}.)
  <p>
- <center><object style="width: 540px; height: 205px;" type="image/svg+xml"
-   data="../../../images/media/mediacodec_buffers.svg"><img
-   src="../../../images/media/mediacodec_buffers.png" style="width: 540px; height: 205px"
-   alt="MediaCodec buffer flow diagram"></object></center>
+ <center>
+   <img src="../../../images/media/mediacodec_buffers.svg" style="width: 540px; height: 205px"
+       alt="MediaCodec buffer flow diagram">
+ </center>
  <p>
  In broad terms, a codec processes input data to generate output data. It processes data
  asynchronously and uses a set of input and output buffers. At a simplistic level, you request
@@ -268,10 +268,10 @@
  Uninitialized, Configured and Error, whereas the Executing state conceptually progresses through
  three sub-states: Flushed, Running and End-of-Stream.
  <p>
- <center><object style="width: 516px; height: 353px;" type="image/svg+xml"
-   data="../../../images/media/mediacodec_states.svg"><img
-   src="../../../images/media/mediacodec_states.png" style="width: 519px; height: 356px"
-   alt="MediaCodec state diagram"></object></center>
+ <center>
+   <img src="../../../images/media/mediacodec_states.svg" style="width: 519px; height: 356px"
+       alt="MediaCodec state diagram">
+ </center>
  <p>
  When you create a codec using one of the factory methods, the codec is in the Uninitialized
  state. First, you need to configure it via {@link #configure configure(&hellip;)}, which brings
@@ -513,10 +513,10 @@
  Similarly, upon an initial call to {@code start} the codec will move directly to the Running
  sub-state and start passing available input buffers via the callback.
  <p>
- <center><object style="width: 516px; height: 353px;" type="image/svg+xml"
-   data="../../../images/media/mediacodec_async_states.svg"><img
-   src="../../../images/media/mediacodec_async_states.png" style="width: 516px; height: 353px"
-   alt="MediaCodec state diagram for asynchronous operation"></object></center>
+ <center>
+   <img src="../../../images/media/mediacodec_async_states.svg" style="width: 516px; height: 353px"
+       alt="MediaCodec state diagram for asynchronous operation">
+ </center>
  <p>
  MediaCodec is typically used like this in asynchronous mode:
  <pre class=prettyprint>
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 49477b9..374cc75 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -182,10 +182,15 @@
         public String mName;
         public int mValue;
         public boolean mDefault;
+        public boolean mInternal;
         public Feature(String name, int value, boolean def) {
+            this(name, value, def, false /* internal */);
+        }
+        public Feature(String name, int value, boolean def, boolean internal) {
             mName = name;
             mValue = value;
             mDefault = def;
+            mInternal = internal;
         }
     }
 
@@ -579,6 +584,11 @@
         public static final String FEATURE_LowLatency = "low-latency";
 
         /**
+         * Do not include in REGULAR_CODECS list in MediaCodecList.
+         */
+        private static final String FEATURE_SpecialCodec = "special-codec";
+
+        /**
          * <b>video encoder only</b>: codec supports quantization parameter bounds.
          * @see MediaFormat#KEY_VIDEO_QP_MAX
          * @see MediaFormat#KEY_VIDEO_QP_MIN
@@ -616,6 +626,8 @@
             new Feature(FEATURE_MultipleFrames,   (1 << 5), false),
             new Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
             new Feature(FEATURE_LowLatency,       (1 << 7), true),
+            // feature to exclude codec from REGULAR codec list
+            new Feature(FEATURE_SpecialCodec,     (1 << 30), false, true),
         };
 
         private static final Feature[] encoderFeatures = {
@@ -623,6 +635,8 @@
             new Feature(FEATURE_MultipleFrames, (1 << 1), false),
             new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
             new Feature(FEATURE_QpBounds, (1 << 3), false),
+            // feature to exclude codec from REGULAR codec list
+            new Feature(FEATURE_SpecialCodec,     (1 << 30), false, true),
         };
 
         /** @hide */
@@ -630,7 +644,9 @@
             Feature[] features = getValidFeatures();
             String[] res = new String[features.length];
             for (int i = 0; i < res.length; i++) {
-                res[i] = features[i].mName;
+                if (!features[i].mInternal) {
+                    res[i] = features[i].mName;
+                }
             }
             return res;
         }
@@ -778,6 +794,10 @@
 
             // check feature support
             for (Feature feat: getValidFeatures()) {
+                if (feat.mInternal) {
+                    continue;
+                }
+
                 Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
                 if (yesNo == null) {
                     continue;
@@ -1091,7 +1111,9 @@
                     mFlagsRequired |= feat.mValue;
                 }
                 mFlagsSupported |= feat.mValue;
-                mDefaultFormat.setInteger(key, 1);
+                if (!feat.mInternal) {
+                    mDefaultFormat.setInteger(key, 1);
+                }
                 // TODO restrict features by mFlagsVerified once all codecs reliably verify them
             }
         }
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 86ed50b..72ee00f 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -102,6 +102,13 @@
         mState = AudioPlaybackConfiguration.PLAYER_STATE_IDLE;
     };
 
+    /** @hide */
+    public int getPlayerIId() {
+        synchronized (mLock) {
+            return mPlayerIId;
+        }
+    }
+
     /**
      * Call from derived class when instantiation / initialization is successful
      */
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index bc73f6a..c775b6f 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -183,8 +183,8 @@
         "libmedia",
         "libnativehelper",
         "libutils",
-        "tv_tuner_aidl_interface-ndk_platform",
-        "tv_tuner_resource_manager_aidl_interface-ndk_platform",
+        "tv_tuner_aidl_interface-ndk",
+        "tv_tuner_resource_manager_aidl_interface-ndk",
     ],
 
     static_libs: [
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2636ab2..8dcdc98 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -953,7 +953,7 @@
     Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
     android::content::AttributionSourceState attributionSource;
     attributionSource.readFromParcel(parcel);
-    sp<MediaPlayer> mp = new MediaPlayer(attributionSource);
+    sp<MediaPlayer> mp = sp<MediaPlayer>::make(attributionSource);
     if (mp == NULL) {
         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
         return;
diff --git a/mms/OWNERS b/mms/OWNERS
index 7f05a2a..f56845e 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -3,16 +3,15 @@
 tgunn@google.com
 breadley@google.com
 rgreenwalt@google.com
-amitmahajan@google.com
 fionaxu@google.com
 jackyu@google.com
 jminjie@google.com
 satk@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index 0d23f05..b9de5a3 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -2,17 +2,16 @@
 tgunn@google.com
 breadley@google.com
 rgreenwalt@google.com
-amitmahajan@google.com
 fionaxu@google.com
 jackyu@google.com
 jminjie@google.com
 satk@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
 
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c1a0a9a..b4cafd8 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -93,9 +93,9 @@
             final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
             setTitle(Html.fromHtml(getString(
                     R.string.confirmation_title,
-                    getCallingAppName(),
-                    profileName,
-                    selectedDevice.getDisplayName()), 0));
+                    Html.escapeHtml(getCallingAppName()),
+                    Html.escapeHtml(selectedDevice.getDisplayName())), 0));
+
             mPairButton = findViewById(R.id.button_pair);
             mPairButton.setOnClickListener(v -> onDeviceConfirmed(getService().mSelectedDevice));
             getService().mSelectedDevice = selectedDevice;
@@ -108,8 +108,8 @@
             mPairButton = findViewById(R.id.button_pair);
             mPairButton.setVisibility(View.GONE);
             setTitle(Html.fromHtml(getString(R.string.chooser_title,
-                    profileName,
-                    getCallingAppName()), 0));
+                    Html.escapeHtml(profileName),
+                    Html.escapeHtml(getCallingAppName())), 0));
             mDeviceListView = findViewById(R.id.device_list);
             mDevicesAdapter = new DevicesAdapter();
             mDeviceListView.setAdapter(mDevicesAdapter);
diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS
index c633113..2736870 100644
--- a/packages/PackageInstaller/OWNERS
+++ b/packages/PackageInstaller/OWNERS
@@ -1,7 +1,5 @@
 svetoslavganov@google.com
-toddke@google.com
-patb@google.com
-suprabh@google.com
+include /PACKAGE_MANAGER_OWNERS
 
 # For automotive related changes
 rogerxue@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS b/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
index a0e28ba..e3e28cb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
@@ -1,5 +1,3 @@
-# Default reviewers for this and subdirectories.
-takaoka@google.com
-yukawa@google.com
+# Bug component: 34867
 
-# Emergency approvers in case the above are not available
\ No newline at end of file
+include platform/frameworks/base:/services/core/java/com/android/server/inputmethod/OWNERS
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
index 5252c6c..52d243a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
@@ -20,9 +20,8 @@
 
 import static org.robolectric.shadow.api.Shadow.extract;
 
-import android.net.ConnectivityManager;
 import android.os.UserManager;
-import android.util.SparseBooleanArray;
+import android.telephony.TelephonyManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,7 +34,7 @@
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {SimStatusImeiInfoPreferenceControllerTest.ShadowUserManager.class,
-                SimStatusImeiInfoPreferenceControllerTest.ShadowConnectivityManager.class})
+                SimStatusImeiInfoPreferenceControllerTest.ShadowTelephonyManager.class})
 public class SimStatusImeiInfoPreferenceControllerTest {
 
     private AbstractSimStatusImeiInfoPreferenceController mController;
@@ -56,9 +55,9 @@
         ShadowUserManager userManager =
                 extract(RuntimeEnvironment.application.getSystemService(UserManager.class));
         userManager.setIsAdminUser(true);
-        ShadowConnectivityManager connectivityManager =
-                extract(RuntimeEnvironment.application.getSystemService(ConnectivityManager.class));
-        connectivityManager.setNetworkSupported(ConnectivityManager.TYPE_MOBILE, true);
+        ShadowTelephonyManager telephonyManager =
+                extract(RuntimeEnvironment.application.getSystemService(TelephonyManager.class));
+        telephonyManager.setDataCapable(true);
 
         assertThat(mController.isAvailable()).isTrue();
     }
@@ -68,9 +67,9 @@
         ShadowUserManager userManager =
                 extract(RuntimeEnvironment.application.getSystemService(UserManager.class));
         userManager.setIsAdminUser(true);
-        ShadowConnectivityManager connectivityManager =
-                extract(RuntimeEnvironment.application.getSystemService(ConnectivityManager.class));
-        connectivityManager.setNetworkSupported(ConnectivityManager.TYPE_MOBILE, false);
+        ShadowTelephonyManager telephonyManager =
+                extract(RuntimeEnvironment.application.getSystemService(TelephonyManager.class));
+        telephonyManager.setDataCapable(false);
 
         assertThat(mController.isAvailable()).isFalse();
     }
@@ -99,19 +98,17 @@
         }
     }
 
-    @Implements(ConnectivityManager.class)
-    public static class ShadowConnectivityManager
-            extends org.robolectric.shadows.ShadowConnectivityManager {
-
-        private final SparseBooleanArray mSupportedNetworkTypes = new SparseBooleanArray();
-
-        private void setNetworkSupported(int networkType, boolean supported) {
-            mSupportedNetworkTypes.put(networkType, supported);
+    @Implements(TelephonyManager.class)
+    public static class ShadowTelephonyManager
+            extends org.robolectric.shadows.ShadowTelephonyManager {
+        private boolean mDataCapable = false;
+        private void setDataCapable(boolean capable) {
+            mDataCapable = capable;
         }
 
         @Implementation
-        public boolean isNetworkSupported(int networkType) {
-            return mSupportedNetworkTypes.get(networkType);
+        public boolean isDataCapable() {
+            return mDataCapable;
         }
     }
 }
diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS
index 6c61d4b9..5ade971 100644
--- a/packages/SettingsProvider/OWNERS
+++ b/packages/SettingsProvider/OWNERS
@@ -2,6 +2,4 @@
 hackbod@google.com
 narayan@google.com
 svetoslavganov@google.com
-schfan@google.com
-toddke@google.com
-patb@google.com
+include /PACKAGE_MANAGER_OWNERS
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 54fb647..76b0b38 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -641,6 +641,15 @@
             </intent-filter>
         </receiver>
 
+        <receiver
+            android:name=".ProfcollectUploadReceiver"
+            android:exported="true"
+            android:permission="android.permission.TRIGGER_SHELL_PROFCOLLECT_UPLOAD" >
+            <intent-filter>
+                <action android:name="com.android.shell.action.PROFCOLLECT_UPLOAD" />
+            </intent-filter>
+        </receiver>
+
         <service
             android:name=".BugreportProgressService"
             android:exported="false"/>
diff --git a/packages/Shell/res/xml/file_provider_paths.xml b/packages/Shell/res/xml/file_provider_paths.xml
index 225c757..85d7dd3 100644
--- a/packages/Shell/res/xml/file_provider_paths.xml
+++ b/packages/Shell/res/xml/file_provider_paths.xml
@@ -1,3 +1,4 @@
 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <files-path name="bugreports" path="bugreports/" />
+    <root-path name="profcollect" path="/data/misc/profcollectd/report/" />
 </paths>
diff --git a/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java b/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java
new file mode 100644
index 0000000..d2da724
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.shell;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.util.Log;
+
+import androidx.core.content.FileProvider;
+
+import com.android.internal.R;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * A proxy service that relays report upload requests to the uploader app, while translating
+ * the path to the report to a content URI owned by this service.
+ */
+public final class ProfcollectUploadReceiver extends BroadcastReceiver {
+    private static final String AUTHORITY = "com.android.shell";
+    private static final String PROFCOLLECT_DATA_ROOT = "/data/misc/profcollectd/report/";
+
+    private static final String LOG_TAG = "ProfcollectUploadReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.i(LOG_TAG, "Received upload intent");
+
+        String uploaderPkg = getUploaderPackageName(context);
+        String uploaderAction = getUploaderActionName(context);
+
+        try {
+            ApplicationInfo info = context.getPackageManager().getApplicationInfo(uploaderPkg,
+                    0);
+            if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                Log.e(LOG_TAG, "The profcollect uploader app " + uploaderPkg
+                        + " must be a system application");
+                return;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(LOG_TAG, "Cannot find profcollect uploader app " + uploaderPkg);
+            return;
+        }
+
+        String filename = intent.getStringExtra("filename");
+        File reportFile = new File(PROFCOLLECT_DATA_ROOT + filename);
+        Uri reportUri = FileProvider.getUriForFile(context, AUTHORITY, reportFile);
+        Intent uploadIntent =
+                new Intent(uploaderAction)
+                        .setPackage(uploaderPkg)
+                        .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
+                        .putExtra("EXTRA_PACKAGE_NAME", context.getPackageName())
+                        .setData(reportUri)
+                        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+        List<ResolveInfo> receivers =
+                context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
+        if (receivers == null || receivers.isEmpty()) {
+            Log.e(LOG_TAG, "No one to receive upload intent, abort upload.");
+            return;
+        }
+
+        context.grantUriPermission(uploaderPkg, reportUri,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        context.sendBroadcast(uploadIntent);
+    }
+
+    private String getUploaderPackageName(Context context) {
+        return context.getResources().getString(
+                R.string.config_defaultProfcollectReportUploaderApp);
+    }
+
+    private String getUploaderActionName(Context context) {
+        return context.getResources().getString(
+                R.string.config_defaultProfcollectReportUploaderAction);
+    }
+}
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 1cf14f2..e1da744 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -11,6 +11,7 @@
 awickham@google.com
 beverlyt@google.com
 brockman@google.com
+brycelee@google.com
 ccassidy@google.com
 cinek@google.com
 cwren@google.com
@@ -22,6 +23,7 @@
 hyunyoungs@google.com
 jaggies@google.com
 jamesoleary@google.com
+jbolinger@google.com
 jdemeulenaere@google.com
 jeffdq@google.com
 jjaggi@google.com
@@ -70,4 +72,4 @@
 hseog@google.com
 
 #Android TV
-rgl@google.com
\ No newline at end of file
+rgl@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricUdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricUdfpsView.java
index 376368f..d80d9cc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricUdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricUdfpsView.java
@@ -21,12 +21,19 @@
 import android.content.Context;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
 
 /**
  * Manages the layout for under-display fingerprint sensors (UDFPS). Ensures that UI elements
  * do not overlap with
  */
 public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView {
+    private static final String TAG = "AuthBiometricUdfpsView";
+
     @Nullable private UdfpsDialogMeasureAdapter mMeasureAdapter;
 
     public AuthBiometricUdfpsView(Context context) {
@@ -51,4 +58,23 @@
                 ? mMeasureAdapter.onMeasureInternal(width, height, layoutParams)
                 : layoutParams;
     }
+
+    @Override
+    void onLayoutInternal() {
+        super.onLayoutInternal();
+
+        // Move the UDFPS icon and indicator text if necessary. This probably only needs to happen
+        // for devices where the UDFPS sensor is too low.
+        // TODO(b/201510778): Update this logic to support cases where the sensor or text overlap
+        //  the button bar area.
+        final int bottomSpacerHeight = mMeasureAdapter.getBottomSpacerHeight();
+        Log.w(TAG, "bottomSpacerHeight: " + bottomSpacerHeight);
+        if (bottomSpacerHeight < 0) {
+            FrameLayout iconFrame = findViewById(R.id.biometric_icon_frame);
+            iconFrame.setTranslationY(-bottomSpacerHeight);
+
+            TextView indicator = findViewById(R.id.indicator);
+            indicator.setTranslationY(-bottomSpacerHeight);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java
index 7ccfb86..6185e59 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java
@@ -45,6 +45,7 @@
     @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
 
     @Nullable private WindowManager mWindowManager;
+    private int mBottomSpacerHeight;
 
     public UdfpsDialogMeasureAdapter(
             @NonNull ViewGroup view, @NonNull FingerprintSensorPropertiesInternal sensorProps) {
@@ -74,6 +75,16 @@
         }
     }
 
+    /**
+     * @return the actual (and possibly negative) bottom spacer height. If negative, this indicates
+     * that the UDFPS sensor is too low. Our current xml and custom measurement logic is very hard
+     * too cleanly support this case. So, let's have the onLayout code translate the sensor location
+     * instead.
+     */
+    int getBottomSpacerHeight() {
+        return mBottomSpacerHeight;
+    }
+
     @NonNull
     private AuthDialog.LayoutParams onMeasureInternalPortrait(int width, int height) {
         // Get the height of the everything below the icon. Currently, that's the indicator and
@@ -86,7 +97,7 @@
         final int dialogMargin = getDialogMarginPx();
         final int displayHeight = getWindowBounds().height();
         final Insets navbarInsets = getNavbarInsets();
-        final int bottomSpacerHeight = calculateBottomSpacerHeightForPortrait(
+        mBottomSpacerHeight = calculateBottomSpacerHeightForPortrait(
                 mSensorProps, displayHeight, textIndicatorHeight, buttonBarHeight,
                 dialogMargin, navbarInsets.bottom);
 
@@ -122,9 +133,10 @@
                                 MeasureSpec.EXACTLY));
             } else if (child.getId() == R.id.space_below_icon) {
                 // Set the spacer height so the fingerprint icon is on the physical sensor area
+                final int clampedSpacerHeight = Math.max(mBottomSpacerHeight, 0);
                 child.measure(
                         MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                        MeasureSpec.makeMeasureSpec(bottomSpacerHeight, MeasureSpec.EXACTLY));
+                        MeasureSpec.makeMeasureSpec(clampedSpacerHeight, MeasureSpec.EXACTLY));
             } else {
                 child.measure(
                         MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index 89786ee..a617850 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -139,7 +139,7 @@
                                 + " with ducking", e);
                     }
                     player.start();
-                    if (DEBUG) { Log.d(mTag, "player.start"); }
+                    if (DEBUG) { Log.d(mTag, "player.start piid:" + player.getPlayerIId()); }
                 } catch (Exception e) {
                     if (player != null) {
                         player.release();
@@ -155,7 +155,13 @@
                     mPlayer = player;
                 }
                 if (mp != null) {
-                    if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
+                    if (DEBUG) {
+                        Log.d(mTag, "mPlayer.pause+release piid:" + player.getPlayerIId());
+                    }
+                    mp.pause();
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException ie) { }
                     mp.release();
                 }
                 this.notify();
@@ -244,6 +250,10 @@
                         try {
                             mp.stop();
                         } catch (Exception e) { }
+                        if (DEBUG) {
+                            Log.i(mTag, "About to release MediaPlayer piid:"
+                                    + mp.getPlayerIId() + " due to notif cancelled");
+                        }
                         mp.release();
                         synchronized(mQueueAudioFocusLock) {
                             if (mAudioManagerWithAudioFocus != null) {
@@ -284,7 +294,7 @@
     public void onCompletion(MediaPlayer mp) {
         synchronized(mQueueAudioFocusLock) {
             if (mAudioManagerWithAudioFocus != null) {
-                if (DEBUG) Log.d(mTag, "onCompletion() abandonning AudioFocus");
+                if (DEBUG) Log.d(mTag, "onCompletion() abandoning AudioFocus");
                 mAudioManagerWithAudioFocus.abandonAudioFocus(null);
                 mAudioManagerWithAudioFocus = null;
             } else {
@@ -310,6 +320,10 @@
             }
         }
         if (mp != null) {
+            if (DEBUG) {
+                Log.i("NotificationPlayer", "About to release MediaPlayer piid:"
+                        + mp.getPlayerIId() + " due to onCompletion");
+            }
             mp.release();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 541ee2c..4a75810 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -51,6 +51,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -95,6 +96,7 @@
     private final UiEventLogger mUiEventLogger;
     private final InstanceIdSequence mInstanceIdSequence;
     private final CustomTileStatePersister mCustomTileStatePersister;
+    private final FeatureFlags mFeatureFlags;
 
     private final List<Callback> mCallbacks = new ArrayList<>();
     private AutoTileManager mAutoTiles;
@@ -122,7 +124,8 @@
             UiEventLogger uiEventLogger,
             UserTracker userTracker,
             SecureSettings secureSettings,
-            CustomTileStatePersister customTileStatePersister
+            CustomTileStatePersister customTileStatePersister,
+            FeatureFlags featureFlags
     ) {
         mIconController = iconController;
         mContext = context;
@@ -144,6 +147,7 @@
         mUserTracker = userTracker;
         mSecureSettings = secureSettings;
         mCustomTileStatePersister = customTileStatePersister;
+        mFeatureFlags = featureFlags;
 
         mainHandler.post(() -> {
             // This is technically a hack to avoid circular dependency of
@@ -265,7 +269,7 @@
         if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {
             newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);
         }
-        final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
+        final List<String> tileSpecs = loadTileSpecs(mContext, newValue, mFeatureFlags);
         int currentUser = mUserTracker.getUserId();
         if (currentUser != mCurrentUser) {
             mUserContext = mUserTracker.getUserContext();
@@ -334,7 +338,7 @@
         if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {
             // If we didn't manage to create any tiles, set it to empty (default)
             Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");
-            changeTiles(currentSpecs, loadTileSpecs(mContext, ""));
+            changeTiles(currentSpecs, loadTileSpecs(mContext, "", mFeatureFlags));
         } else {
             for (int i = 0; i < mCallbacks.size(); i++) {
                 mCallbacks.get(i).onTilesChanged();
@@ -389,7 +393,7 @@
 
     private void changeTileSpecs(Predicate<List<String>> changeFunction) {
         final String setting = mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser);
-        final List<String> tileSpecs = loadTileSpecs(mContext, setting);
+        final List<String> tileSpecs = loadTileSpecs(mContext, setting, mFeatureFlags);
         if (changeFunction.test(tileSpecs)) {
             saveTilesToSettings(tileSpecs);
         }
@@ -478,7 +482,8 @@
         throw new RuntimeException("Default factory didn't create view for " + tile.getTileSpec());
     }
 
-    protected static List<String> loadTileSpecs(Context context, String tileList) {
+    protected static List<String> loadTileSpecs(
+            Context context, String tileList, FeatureFlags featureFlags) {
         final Resources res = context.getResources();
 
         if (TextUtils.isEmpty(tileList)) {
@@ -511,6 +516,21 @@
                 }
             }
         }
+        if (featureFlags.isProviderModelSettingEnabled()) {
+            if (!tiles.contains("internet")) {
+                if (tiles.contains("wifi")) {
+                    // Replace the WiFi with Internet, and remove the Cell
+                    tiles.set(tiles.indexOf("wifi"), "internet");
+                    tiles.remove("cell");
+                } else if (tiles.contains("cell")) {
+                    // Replace the Cell with Internet
+                    tiles.set(tiles.indexOf("cell"), "internet");
+                }
+            } else {
+                tiles.remove("wifi");
+                tiles.remove("cell");
+            }
+        }
         return tiles;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 3c2f35b..f2832b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -41,6 +41,7 @@
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.util.leak.GarbageMonitor;
 
 import java.util.ArrayList;
@@ -62,6 +63,7 @@
     private final Executor mBgExecutor;
     private final Context mContext;
     private final UserTracker mUserTracker;
+    private final FeatureFlags mFeatureFlags;
     private TileStateListener mListener;
 
     private boolean mFinished;
@@ -71,12 +73,14 @@
             Context context,
             UserTracker userTracker,
             @Main Executor mainExecutor,
-            @Background Executor bgExecutor
+            @Background Executor bgExecutor,
+            FeatureFlags featureFlags
     ) {
         mContext = context;
         mMainExecutor = mainExecutor;
         mBgExecutor = bgExecutor;
         mUserTracker = userTracker;
+        mFeatureFlags = featureFlags;
     }
 
     public void setListener(TileStateListener listener) {
@@ -117,6 +121,10 @@
         }
 
         final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
+        if (mFeatureFlags.isProviderModelSettingEnabled()) {
+            possibleTiles.remove("cell");
+            possibleTiles.remove("wifi");
+        }
 
         for (String spec : possibleTiles) {
             // Only add current and stock tiles that can be created from QSFactoryImpl.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 86c90c7..9eb95c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -28,15 +27,12 @@
 import com.android.systemui.statusbar.notification.stack.ViewState;
 
 public class FooterView extends StackScrollerDecorView {
-    private final int mClearAllTopPadding;
     private FooterViewButton mDismissButton;
     private FooterViewButton mManageButton;
     private boolean mShowHistory;
 
     public FooterView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mClearAllTopPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.clear_all_padding_top);
     }
 
     @Override
@@ -55,11 +51,6 @@
         mManageButton = findViewById(R.id.manage_text);
     }
 
-    public void setTextColor(@ColorInt int color) {
-        mManageButton.setTextColor(color);
-        mDismissButton.setTextColor(color);
-    }
-
     public void setManageButtonClickListener(OnClickListener listener) {
         mManageButton.setOnClickListener(listener);
     }
@@ -95,21 +86,25 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        int textColor = getResources().getColor(R.color.notif_pill_text);
-        Resources.Theme theme = getContext().getTheme();
-        mDismissButton.setBackground(
-                getResources().getDrawable(R.drawable.notif_footer_btn_background, theme));
-        mDismissButton.setTextColor(textColor);
-        mManageButton.setBackground(
-                getResources().getDrawable(R.drawable.notif_footer_btn_background, theme));
-        mManageButton = findViewById(R.id.manage_text);
+        updateColors();
         mDismissButton.setText(R.string.clear_all_notifications_text);
-        mManageButton.setTextColor(textColor);
         mDismissButton.setContentDescription(
                 mContext.getString(R.string.accessibility_clear_all));
         showHistory(mShowHistory);
     }
 
+    /**
+     * Update the text and background colors for the current color palette and night mode setting.
+     */
+    public void updateColors() {
+        Resources.Theme theme = mContext.getTheme();
+        int textColor = getResources().getColor(R.color.notif_pill_text, theme);
+        mDismissButton.setBackground(theme.getDrawable(R.drawable.notif_footer_btn_background));
+        mDismissButton.setTextColor(textColor);
+        mManageButton.setBackground(theme.getDrawable(R.drawable.notif_footer_btn_background));
+        mManageButton.setTextColor(textColor);
+    }
+
     @Override
     public ExpandableViewState createExpandableViewState() {
         return new FooterViewState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 289c32f..0660daa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4231,7 +4231,7 @@
         final @ColorInt int textColor =
                 Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
         mSectionsManager.setHeaderForegroundColor(textColor);
-        mFooterView.setTextColor(textColor);
+        mFooterView.updateColors();
         mEmptyShadeView.setTextColor(textColor);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 3ee3e55..7f89b26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -139,7 +139,7 @@
                 () -> mock(AutoTileManager.class), mock(DumpManager.class),
                 mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
                 mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
-                mock(SecureSettings.class), mock(CustomTileStatePersister.class));
+                mock(SecureSettings.class), mock(CustomTileStatePersister.class), mFeatureFlags);
         qs.setHost(host);
 
         qs.setListening(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 9e97f80..4cbad5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -63,6 +63,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -124,6 +125,8 @@
     private SecureSettings mSecureSettings;
     @Mock
     private CustomTileStatePersister mCustomTileStatePersister;
+    @Mock
+    private FeatureFlags mFeatureFlags;
 
     private Handler mHandler;
     private TestableLooper mLooper;
@@ -137,9 +140,9 @@
         mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
                 mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
                 mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger, mUserTracker,
-                mSecureSettings, mCustomTileStatePersister);
+                mSecureSettings, mCustomTileStatePersister, mFeatureFlags);
         setUpTileFactory();
-
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
         when(mSecureSettings.getStringForUser(eq(QSTileHost.TILES_SETTING), anyInt()))
                 .thenReturn("");
     }
@@ -169,13 +172,13 @@
 
     @Test
     public void testLoadTileSpecs_emptySetting() {
-        List<String> tiles = QSTileHost.loadTileSpecs(mContext, "");
+        List<String> tiles = QSTileHost.loadTileSpecs(mContext, "", mFeatureFlags);
         assertFalse(tiles.isEmpty());
     }
 
     @Test
     public void testLoadTileSpecs_nullSetting() {
-        List<String> tiles = QSTileHost.loadTileSpecs(mContext, null);
+        List<String> tiles = QSTileHost.loadTileSpecs(mContext, null, mFeatureFlags);
         assertFalse(tiles.isEmpty());
     }
 
@@ -189,6 +192,55 @@
     }
 
     @Test
+    public void testRemoveWifiAndCellularWithoutInternet() {
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2");
+
+        assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
+        assertEquals("spec1", mQSTileHost.mTileSpecs.get(1));
+        assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+    }
+
+    @Test
+    public void testRemoveWifiAndCellularWithInternet() {
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2, internet");
+
+        assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+        assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+        assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+    }
+
+    @Test
+    public void testRemoveWifiWithoutInternet() {
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, wifi, spec2");
+
+        assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+        assertEquals("internet", mQSTileHost.mTileSpecs.get(1));
+        assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+    }
+
+    @Test
+    public void testRemoveCellWithInternet() {
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, spec2, cell, internet");
+
+        assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+        assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+        assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+    }
+
+    @Test
+    public void testNoWifiNoCellularNoInternet() {
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
+
+        assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+        assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+    }
+
+    @Test
     public void testSpecWithInvalidDoesNotUseDefault() {
         mContext.getOrCreateTestableResources()
                 .addOverride(R.string.quick_settings_tiles, "spec1,spec2");
@@ -321,7 +373,7 @@
 
     @Test
     public void testLoadTileSpec_repeated() {
-        List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2");
+        List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2", mFeatureFlags);
 
         assertEquals(2, specs.size());
         assertEquals("spec1", specs.get(0));
@@ -332,7 +384,7 @@
     public void testLoadTileSpec_repeatedInDefault() {
         mContext.getOrCreateTestableResources()
                 .addOverride(R.string.quick_settings_tiles_default, "spec1,spec1");
-        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default");
+        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default", mFeatureFlags);
 
         // Remove spurious tiles, like dbg:mem
         specs.removeIf(spec -> !"spec1".equals(spec));
@@ -343,7 +395,7 @@
     public void testLoadTileSpec_repeatedDefaultAndSetting() {
         mContext.getOrCreateTestableResources()
                 .addOverride(R.string.quick_settings_tiles_default, "spec1");
-        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1");
+        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1", mFeatureFlags);
 
         // Remove spurious tiles, like dbg:mem
         specs.removeIf(spec -> !"spec1".equals(spec));
@@ -371,11 +423,12 @@
                 Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
                 BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger,
                 UiEventLogger uiEventLogger, UserTracker userTracker,
-                SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister) {
+                SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister,
+                FeatureFlags featureFlags) {
             super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
                     tunerService, autoTiles, dumpManager, broadcastDispatcher,
                     Optional.of(statusBar), qsLogger, uiEventLogger, userTracker, secureSettings,
-                    customTileStatePersister);
+                    customTileStatePersister, featureFlags);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 4efcc5c..c5b6709 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -58,6 +58,7 @@
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -108,6 +109,8 @@
     private PackageManager mPackageManager;
     @Mock
     private UserTracker mUserTracker;
+    @Mock
+    private FeatureFlags mFeatureFlags;
     @Captor
     private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
 
@@ -133,12 +136,12 @@
                     }
                 }
         ).when(mQSTileHost).createTile(anyString());
-
+        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
         FakeSystemClock clock = new FakeSystemClock();
         mMainExecutor = new FakeExecutor(clock);
         mBgExecutor = new FakeExecutor(clock);
         mTileQueryHelper = new TileQueryHelper(
-                mContext, mUserTracker, mMainExecutor, mBgExecutor);
+                mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
         mTileQueryHelper.setListener(mListener);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 2b18404..01fa222 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -98,6 +99,8 @@
     private UserTracker mUserTracker;
     @Mock
     private SecureSettings  mSecureSettings;
+    @Mock
+    private FeatureFlags mFeatureFlags;
 
     @Before
     public void setUp() throws Exception {
@@ -119,7 +122,8 @@
                 mUiEventLogger,
                 mUserTracker,
                 mSecureSettings,
-                mock(CustomTileStatePersister.class));
+                mock(CustomTileStatePersister.class),
+                mFeatureFlags);
         mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher,
                 mUserTracker);
     }
diff --git a/rs/jni/Android.bp b/rs/jni/Android.bp
new file mode 100644
index 0000000..9a6fa8e
--- /dev/null
+++ b/rs/jni/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+cc_library_shared {
+    name: "librs_jni",
+
+    srcs: ["android_renderscript_RenderScript.cpp"],
+
+    shared_libs: [
+        "libandroid",
+        "libandroid_runtime",
+        "libandroidfw",
+        "libRS",
+        "libcutils",
+        "libhwui",
+        "liblog",
+        "libutils",
+        "libui",
+        "libgui",
+        "libjnigraphics",
+    ],
+
+    header_libs: [
+        "jni_headers",
+        "libbase_headers",
+    ],
+
+    include_dirs: ["frameworks/rs"],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wunused",
+        "-Wunreachable-code",
+        "-Wno-deprecated-declarations",
+    ],
+}
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
deleted file mode 100644
index 0caba42..0000000
--- a/rs/jni/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    android_renderscript_RenderScript.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libandroid \
-    libandroid_runtime \
-    libandroidfw \
-    libRS \
-    libcutils \
-    libhwui \
-    liblog \
-    libutils \
-    libui \
-    libgui \
-    libjnigraphics
-
-LOCAL_HEADER_LIBRARIES := \
-    jni_headers \
-    libbase_headers
-
-LOCAL_C_INCLUDES += \
-    frameworks/rs
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -Wno-deprecated-declarations
-
-LOCAL_MODULE:= librs_jni
-LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS:= notice
-LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE
-LOCAL_MODULE_TAGS := optional
-LOCAL_REQUIRED_MODULES := libRS
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 55b982b..2103bcc 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -138,9 +138,11 @@
         "android.hardware.boot-V1.1-java",
         "android.hardware.boot-V1.2-java",
         "android.hardware.broadcastradio-V2.0-java",
-        "android.hardware.health-V1.0-java",
-        "android.hardware.health-V2.0-java",
-        "android.hardware.health-V2.1-java",
+        "android.hardware.health-V1.0-java", // HIDL
+        "android.hardware.health-V2.0-java", // HIDL
+        "android.hardware.health-V2.1-java", // HIDL
+        "android.hardware.health-V1-java", // AIDL
+        "android.hardware.health-translate-java",
         "android.hardware.light-V1-java",
         "android.hardware.tv.cec-V1.1-java",
         "android.hardware.weaver-V1.0-java",
@@ -149,7 +151,7 @@
         "android.hardware.biometrics.fingerprint-V2.3-java",
         "android.hardware.biometrics.fingerprint-V1-java",
         "android.hardware.oemlock-V1.0-java",
-        "android.hardware.configstore-V1.0-java",
+        "android.hardware.configstore-V1.1-java",
         "android.hardware.contexthub-V1.0-java",
         "android.hardware.rebootescrow-V1-java",
         "android.hardware.soundtrigger-V2.3-java",
diff --git a/services/core/java/android/content/pm/OWNERS b/services/core/java/android/content/pm/OWNERS
index 5eed0b5..3993140 100644
--- a/services/core/java/android/content/pm/OWNERS
+++ b/services/core/java/android/content/pm/OWNERS
@@ -1 +1 @@
-include /core/java/android/content/pm/OWNERS
\ No newline at end of file
+include /PACKAGE_MANAGER_OWNERS
\ No newline at end of file
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 1e608f5..844ac86 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import static com.android.server.health.Utils.copyV1Battery;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -25,14 +26,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
-import android.hardware.health.V1_0.HealthInfo;
-import android.hardware.health.V2_0.IHealth;
-import android.hardware.health.V2_0.Result;
+import android.hardware.health.HealthInfo;
 import android.hardware.health.V2_1.BatteryCapacityLevel;
-import android.hardware.health.V2_1.Constants;
-import android.hardware.health.V2_1.IHealthInfoCallback;
-import android.hidl.manager.V1_0.IServiceManager;
-import android.hidl.manager.V1_0.IServiceNotification;
 import android.metrics.LogMaker;
 import android.os.BatteryManager;
 import android.os.BatteryManagerInternal;
@@ -44,7 +39,6 @@
 import android.os.DropBoxManager;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBatteryPropertiesRegistrar;
 import android.os.IBinder;
 import android.os.OsProtoEnums;
@@ -62,15 +56,14 @@
 import android.service.battery.BatteryServiceDumpProto;
 import android.sysprop.PowerProperties;
 import android.util.EventLog;
-import android.util.MutableInt;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.DumpUtils;
 import com.android.server.am.BatteryStatsService;
+import com.android.server.health.HealthServiceWrapper;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LogicalLight;
 
@@ -81,11 +74,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * <p>BatteryService monitors the charging status, and charge level of the device
@@ -149,7 +138,6 @@
 
     private HealthInfo mHealthInfo;
     private final HealthInfo mLastHealthInfo = new HealthInfo();
-    private android.hardware.health.V2_1.HealthInfo mHealthInfo2p1;
     private boolean mBatteryLevelCritical;
     private int mLastBatteryStatus;
     private int mLastBatteryHealth;
@@ -193,7 +181,6 @@
     private ActivityManagerInternal mActivityManagerInternal;
 
     private HealthServiceWrapper mHealthServiceWrapper;
-    private HealthHalCallback mHealthHalCallback;
     private BatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
     private ArrayDeque<Bundle> mBatteryLevelsEventQueue;
     private long mLastBatteryLevelChangedSentMs;
@@ -276,13 +263,9 @@
 
     private void registerHealthCallback() {
         traceBegin("HealthInitWrapper");
-        mHealthServiceWrapper = new HealthServiceWrapper();
-        mHealthHalCallback = new HealthHalCallback();
         // IHealth is lazily retrieved.
         try {
-            mHealthServiceWrapper.init(mHealthHalCallback,
-                    new HealthServiceWrapper.IServiceManagerSupplier() {},
-                    new HealthServiceWrapper.IHealthSupplier() {});
+            mHealthServiceWrapper = HealthServiceWrapper.create(this::update);
         } catch (RemoteException ex) {
             Slog.e(TAG, "health: cannot register callback. (RemoteException)");
             throw ex.rethrowFromSystemServer();
@@ -370,8 +353,8 @@
     }
 
     private boolean shouldShutdownLocked() {
-        if (mHealthInfo2p1.batteryCapacityLevel != BatteryCapacityLevel.UNSUPPORTED) {
-            return (mHealthInfo2p1.batteryCapacityLevel == BatteryCapacityLevel.CRITICAL);
+        if (mHealthInfo.batteryCapacityLevel != BatteryCapacityLevel.UNSUPPORTED) {
+            return (mHealthInfo.batteryCapacityLevel == BatteryCapacityLevel.CRITICAL);
         }
         if (mHealthInfo.batteryLevel > 0) {
             return false;
@@ -413,7 +396,7 @@
         // shut down gracefully if temperature is too high (> 68.0C by default)
         // wait until the system has booted before attempting to display the
         // shutdown dialog.
-        if (mHealthInfo.batteryTemperature > mShutdownBatteryTemperature) {
+        if (mHealthInfo.batteryTemperatureTenthsCelsius > mShutdownBatteryTemperature) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -430,51 +413,28 @@
         }
     }
 
-    private void update(android.hardware.health.V2_1.HealthInfo info) {
+    private void update(android.hardware.health.HealthInfo info) {
         traceBegin("HealthInfoUpdate");
 
-        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryChargeCounter",
-                info.legacy.legacy.batteryChargeCounter);
-        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent",
-                info.legacy.legacy.batteryCurrent);
-        Trace.traceCounter(Trace.TRACE_TAG_POWER, "PlugType",
-                plugType(info.legacy.legacy));
-        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryStatus",
-                info.legacy.legacy.batteryStatus);
+        Trace.traceCounter(
+                Trace.TRACE_TAG_POWER, "BatteryChargeCounter", info.batteryChargeCounterUah);
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent", info.batteryCurrentMicroamps);
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "PlugType", plugType(info));
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryStatus", info.batteryStatus);
 
         synchronized (mLock) {
             if (!mUpdatesStopped) {
-                mHealthInfo = info.legacy.legacy;
-                mHealthInfo2p1 = info;
+                mHealthInfo = info;
                 // Process the new values.
                 processValuesLocked(false);
                 mLock.notifyAll(); // for any waiters on new info
             } else {
-                copy(mLastHealthInfo, info.legacy.legacy);
+                copyV1Battery(mLastHealthInfo, info);
             }
         }
         traceEnd();
     }
 
-    private static void copy(HealthInfo dst, HealthInfo src) {
-        dst.chargerAcOnline = src.chargerAcOnline;
-        dst.chargerUsbOnline = src.chargerUsbOnline;
-        dst.chargerWirelessOnline = src.chargerWirelessOnline;
-        dst.maxChargingCurrent = src.maxChargingCurrent;
-        dst.maxChargingVoltage = src.maxChargingVoltage;
-        dst.batteryStatus = src.batteryStatus;
-        dst.batteryHealth = src.batteryHealth;
-        dst.batteryPresent = src.batteryPresent;
-        dst.batteryLevel = src.batteryLevel;
-        dst.batteryVoltage = src.batteryVoltage;
-        dst.batteryTemperature = src.batteryTemperature;
-        dst.batteryCurrent = src.batteryCurrent;
-        dst.batteryCycleCount = src.batteryCycleCount;
-        dst.batteryFullCharge = src.batteryFullCharge;
-        dst.batteryChargeCounter = src.batteryChargeCounter;
-        dst.batteryTechnology = src.batteryTechnology;
-    }
-
     private static int plugType(HealthInfo healthInfo) {
         if (healthInfo.chargerAcOnline) {
             return BatteryManager.BATTERY_PLUGGED_AC;
@@ -505,11 +465,16 @@
 
         // Let the battery stats keep track of the current level.
         try {
-            mBatteryStats.setBatteryState(mHealthInfo.batteryStatus, mHealthInfo.batteryHealth,
-                    mPlugType, mHealthInfo.batteryLevel, mHealthInfo.batteryTemperature,
-                    mHealthInfo.batteryVoltage, mHealthInfo.batteryChargeCounter,
-                    mHealthInfo.batteryFullCharge,
-                    mHealthInfo2p1.batteryChargeTimeToFullNowSeconds);
+            mBatteryStats.setBatteryState(
+                    mHealthInfo.batteryStatus,
+                    mHealthInfo.batteryHealth,
+                    mPlugType,
+                    mHealthInfo.batteryLevel,
+                    mHealthInfo.batteryTemperatureTenthsCelsius,
+                    mHealthInfo.batteryVoltageMillivolts,
+                    mHealthInfo.batteryChargeCounterUah,
+                    mHealthInfo.batteryFullChargeUah,
+                    mHealthInfo.batteryChargeTimeToFullNowSeconds);
         } catch (RemoteException e) {
             // Should never happen.
         }
@@ -517,17 +482,18 @@
         shutdownIfNoPowerLocked();
         shutdownIfOverTempLocked();
 
-        if (force || (mHealthInfo.batteryStatus != mLastBatteryStatus ||
-                mHealthInfo.batteryHealth != mLastBatteryHealth ||
-                mHealthInfo.batteryPresent != mLastBatteryPresent ||
-                mHealthInfo.batteryLevel != mLastBatteryLevel ||
-                mPlugType != mLastPlugType ||
-                mHealthInfo.batteryVoltage != mLastBatteryVoltage ||
-                mHealthInfo.batteryTemperature != mLastBatteryTemperature ||
-                mHealthInfo.maxChargingCurrent != mLastMaxChargingCurrent ||
-                mHealthInfo.maxChargingVoltage != mLastMaxChargingVoltage ||
-                mHealthInfo.batteryChargeCounter != mLastChargeCounter ||
-                mInvalidCharger != mLastInvalidCharger)) {
+        if (force
+                || (mHealthInfo.batteryStatus != mLastBatteryStatus
+                        || mHealthInfo.batteryHealth != mLastBatteryHealth
+                        || mHealthInfo.batteryPresent != mLastBatteryPresent
+                        || mHealthInfo.batteryLevel != mLastBatteryLevel
+                        || mPlugType != mLastPlugType
+                        || mHealthInfo.batteryVoltageMillivolts != mLastBatteryVoltage
+                        || mHealthInfo.batteryTemperatureTenthsCelsius != mLastBatteryTemperature
+                        || mHealthInfo.maxChargingCurrentMicroamps != mLastMaxChargingCurrent
+                        || mHealthInfo.maxChargingVoltageMicrovolts != mLastMaxChargingVoltage
+                        || mHealthInfo.batteryChargeCounterUah != mLastChargeCounter
+                        || mInvalidCharger != mLastInvalidCharger)) {
 
             if (mPlugType != mLastPlugType) {
                 if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -584,8 +550,11 @@
             if (mHealthInfo.batteryLevel != mLastBatteryLevel) {
                 // Don't do this just from voltage or temperature changes, that is
                 // too noisy.
-                EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
-                        mHealthInfo.batteryLevel, mHealthInfo.batteryVoltage, mHealthInfo.batteryTemperature);
+                EventLog.writeEvent(
+                        EventLogTags.BATTERY_LEVEL,
+                        mHealthInfo.batteryLevel,
+                        mHealthInfo.batteryVoltageMillivolts,
+                        mHealthInfo.batteryTemperatureTenthsCelsius);
             }
             if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
                     mPlugType == BATTERY_PLUGGED_NONE) {
@@ -691,11 +660,11 @@
             mLastBatteryPresent = mHealthInfo.batteryPresent;
             mLastBatteryLevel = mHealthInfo.batteryLevel;
             mLastPlugType = mPlugType;
-            mLastBatteryVoltage = mHealthInfo.batteryVoltage;
-            mLastBatteryTemperature = mHealthInfo.batteryTemperature;
-            mLastMaxChargingCurrent = mHealthInfo.maxChargingCurrent;
-            mLastMaxChargingVoltage = mHealthInfo.maxChargingVoltage;
-            mLastChargeCounter = mHealthInfo.batteryChargeCounter;
+            mLastBatteryVoltage = mHealthInfo.batteryVoltageMillivolts;
+            mLastBatteryTemperature = mHealthInfo.batteryTemperatureTenthsCelsius;
+            mLastMaxChargingCurrent = mHealthInfo.maxChargingCurrentMicroamps;
+            mLastMaxChargingVoltage = mHealthInfo.maxChargingVoltageMicrovolts;
+            mLastChargeCounter = mHealthInfo.batteryChargeCounterUah;
             mLastBatteryLevelCritical = mBatteryLevelCritical;
             mLastInvalidCharger = mInvalidCharger;
         }
@@ -718,13 +687,17 @@
         intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
         intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
         intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
-        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage);
-        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperature);
+        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltageMillivolts);
+        intent.putExtra(
+                BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperatureTenthsCelsius);
         intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mHealthInfo.batteryTechnology);
         intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
-        intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mHealthInfo.maxChargingCurrent);
-        intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mHealthInfo.maxChargingVoltage);
-        intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounter);
+        intent.putExtra(
+                BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mHealthInfo.maxChargingCurrentMicroamps);
+        intent.putExtra(
+                BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE,
+                mHealthInfo.maxChargingVoltageMicrovolts);
+        intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
         if (DEBUG) {
             Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE
                     + ", info:" + mHealthInfo.toString());
@@ -744,9 +717,9 @@
         event.putBoolean(BatteryManager.EXTRA_BATTERY_LOW, mSentLowBatteryBroadcast);
         event.putInt(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
         event.putInt(BatteryManager.EXTRA_PLUGGED, mPlugType);
-        event.putInt(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage);
-        event.putInt(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperature);
-        event.putInt(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounter);
+        event.putInt(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltageMillivolts);
+        event.putInt(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperatureTenthsCelsius);
+        event.putInt(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
         event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now);
 
         boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty();
@@ -938,7 +911,7 @@
                 }
                 try {
                     if (!mUpdatesStopped) {
-                        copy(mLastHealthInfo, mHealthInfo);
+                        copyV1Battery(mLastHealthInfo, mHealthInfo);
                     }
                     boolean update = true;
                     switch (key) {
@@ -961,10 +934,10 @@
                             mHealthInfo.batteryLevel = Integer.parseInt(value);
                             break;
                         case "counter":
-                            mHealthInfo.batteryChargeCounter = Integer.parseInt(value);
+                            mHealthInfo.batteryChargeCounterUah = Integer.parseInt(value);
                             break;
                         case "temp":
-                            mHealthInfo.batteryTemperature = Integer.parseInt(value);
+                            mHealthInfo.batteryTemperatureTenthsCelsius = Integer.parseInt(value);
                             break;
                         case "invalid":
                             mInvalidCharger = Integer.parseInt(value);
@@ -1008,7 +981,7 @@
 
     private void setChargerAcOnline(boolean online, boolean forceUpdate) {
         if (!mUpdatesStopped) {
-            copy(mLastHealthInfo, mHealthInfo);
+            copyV1Battery(mLastHealthInfo, mHealthInfo);
         }
         mHealthInfo.chargerAcOnline = online;
         mUpdatesStopped = true;
@@ -1017,7 +990,7 @@
 
     private void setBatteryLevel(int level, boolean forceUpdate) {
         if (!mUpdatesStopped) {
-            copy(mLastHealthInfo, mHealthInfo);
+            copyV1Battery(mLastHealthInfo, mHealthInfo);
         }
         mHealthInfo.batteryLevel = level;
         mUpdatesStopped = true;
@@ -1026,7 +999,7 @@
 
     private void unplugBattery(boolean forceUpdate, PrintWriter pw) {
         if (!mUpdatesStopped) {
-            copy(mLastHealthInfo, mHealthInfo);
+            copyV1Battery(mLastHealthInfo, mHealthInfo);
         }
         mHealthInfo.chargerAcOnline = false;
         mHealthInfo.chargerUsbOnline = false;
@@ -1038,7 +1011,7 @@
     private void resetBattery(boolean forceUpdate, @Nullable PrintWriter pw) {
         if (mUpdatesStopped) {
             mUpdatesStopped = false;
-            copy(mHealthInfo, mLastHealthInfo);
+            copyV1Battery(mHealthInfo, mLastHealthInfo);
             Binder.withCleanCallingIdentity(() -> processValuesLocked(forceUpdate, pw));
         }
         if (mBatteryInputSuspended) {
@@ -1073,16 +1046,16 @@
                 pw.println("  AC powered: " + mHealthInfo.chargerAcOnline);
                 pw.println("  USB powered: " + mHealthInfo.chargerUsbOnline);
                 pw.println("  Wireless powered: " + mHealthInfo.chargerWirelessOnline);
-                pw.println("  Max charging current: " + mHealthInfo.maxChargingCurrent);
-                pw.println("  Max charging voltage: " + mHealthInfo.maxChargingVoltage);
-                pw.println("  Charge counter: " + mHealthInfo.batteryChargeCounter);
+                pw.println("  Max charging current: " + mHealthInfo.maxChargingCurrentMicroamps);
+                pw.println("  Max charging voltage: " + mHealthInfo.maxChargingVoltageMicrovolts);
+                pw.println("  Charge counter: " + mHealthInfo.batteryChargeCounterUah);
                 pw.println("  status: " + mHealthInfo.batteryStatus);
                 pw.println("  health: " + mHealthInfo.batteryHealth);
                 pw.println("  present: " + mHealthInfo.batteryPresent);
                 pw.println("  level: " + mHealthInfo.batteryLevel);
                 pw.println("  scale: " + BATTERY_SCALE);
-                pw.println("  voltage: " + mHealthInfo.batteryVoltage);
-                pw.println("  temperature: " + mHealthInfo.batteryTemperature);
+                pw.println("  voltage: " + mHealthInfo.batteryVoltageMillivolts);
+                pw.println("  temperature: " + mHealthInfo.batteryTemperatureTenthsCelsius);
                 pw.println("  technology: " + mHealthInfo.batteryTechnology);
             } else {
                 Shell shell = new Shell();
@@ -1105,16 +1078,23 @@
                 batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_WIRELESS;
             }
             proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
-            proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mHealthInfo.maxChargingCurrent);
-            proto.write(BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE, mHealthInfo.maxChargingVoltage);
-            proto.write(BatteryServiceDumpProto.CHARGE_COUNTER, mHealthInfo.batteryChargeCounter);
+            proto.write(
+                    BatteryServiceDumpProto.MAX_CHARGING_CURRENT,
+                    mHealthInfo.maxChargingCurrentMicroamps);
+            proto.write(
+                    BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE,
+                    mHealthInfo.maxChargingVoltageMicrovolts);
+            proto.write(
+                    BatteryServiceDumpProto.CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
             proto.write(BatteryServiceDumpProto.STATUS, mHealthInfo.batteryStatus);
             proto.write(BatteryServiceDumpProto.HEALTH, mHealthInfo.batteryHealth);
             proto.write(BatteryServiceDumpProto.IS_PRESENT, mHealthInfo.batteryPresent);
             proto.write(BatteryServiceDumpProto.LEVEL, mHealthInfo.batteryLevel);
             proto.write(BatteryServiceDumpProto.SCALE, BATTERY_SCALE);
-            proto.write(BatteryServiceDumpProto.VOLTAGE, mHealthInfo.batteryVoltage);
-            proto.write(BatteryServiceDumpProto.TEMPERATURE, mHealthInfo.batteryTemperature);
+            proto.write(BatteryServiceDumpProto.VOLTAGE, mHealthInfo.batteryVoltageMillivolts);
+            proto.write(
+                    BatteryServiceDumpProto.TEMPERATURE,
+                    mHealthInfo.batteryTemperatureTenthsCelsius);
             proto.write(BatteryServiceDumpProto.TECHNOLOGY, mHealthInfo.batteryTechnology);
         }
         proto.flush();
@@ -1186,64 +1166,6 @@
         }
     }
 
-    private final class HealthHalCallback extends IHealthInfoCallback.Stub
-            implements HealthServiceWrapper.Callback {
-        @Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
-            android.hardware.health.V2_1.HealthInfo propsLatest =
-                    new android.hardware.health.V2_1.HealthInfo();
-            propsLatest.legacy = props;
-
-            propsLatest.batteryCapacityLevel = BatteryCapacityLevel.UNSUPPORTED;
-            propsLatest.batteryChargeTimeToFullNowSeconds =
-                Constants.BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;
-
-            BatteryService.this.update(propsLatest);
-        }
-
-        @Override public void healthInfoChanged_2_1(android.hardware.health.V2_1.HealthInfo props) {
-            BatteryService.this.update(props);
-        }
-
-        // on new service registered
-        @Override public void onRegistration(IHealth oldService, IHealth newService,
-                String instance) {
-            if (newService == null) return;
-
-            traceBegin("HealthUnregisterCallback");
-            try {
-                if (oldService != null) {
-                    int r = oldService.unregisterCallback(this);
-                    if (r != Result.SUCCESS) {
-                        Slog.w(TAG, "health: cannot unregister previous callback: " +
-                                Result.toString(r));
-                    }
-                }
-            } catch (RemoteException ex) {
-                Slog.w(TAG, "health: cannot unregister previous callback (transaction error): "
-                            + ex.getMessage());
-            } finally {
-                traceEnd();
-            }
-
-            traceBegin("HealthRegisterCallback");
-            try {
-                int r = newService.registerCallback(this);
-                if (r != Result.SUCCESS) {
-                    Slog.w(TAG, "health: cannot register callback: " + Result.toString(r));
-                    return;
-                }
-                // registerCallback does NOT guarantee that update is called
-                // immediately, so request a manual update here.
-                newService.update();
-            } catch (RemoteException ex) {
-                Slog.e(TAG, "health: cannot register callback (transaction error): "
-                        + ex.getMessage());
-            } finally {
-                traceEnd();
-            }
-        }
-    }
-
     private final class BinderService extends Binder {
         @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -1267,71 +1189,11 @@
     private final class BatteryPropertiesRegistrar extends IBatteryPropertiesRegistrar.Stub {
         @Override
         public int getProperty(int id, final BatteryProperty prop) throws RemoteException {
-            traceBegin("HealthGetProperty");
-            try {
-                IHealth service = mHealthServiceWrapper.getLastService();
-                if (service == null) throw new RemoteException("no health service");
-                final MutableInt outResult = new MutableInt(Result.NOT_SUPPORTED);
-                switch(id) {
-                    case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
-                        service.getChargeCounter((int result, int value) -> {
-                            outResult.value = result;
-                            if (result == Result.SUCCESS) prop.setLong(value);
-                        });
-                        break;
-                    case BatteryManager.BATTERY_PROPERTY_CURRENT_NOW:
-                        service.getCurrentNow((int result, int value) -> {
-                            outResult.value = result;
-                            if (result == Result.SUCCESS) prop.setLong(value);
-                        });
-                        break;
-                    case BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE:
-                        service.getCurrentAverage((int result, int value) -> {
-                            outResult.value = result;
-                            if (result == Result.SUCCESS) prop.setLong(value);
-                        });
-                        break;
-                    case BatteryManager.BATTERY_PROPERTY_CAPACITY:
-                        service.getCapacity((int result, int value) -> {
-                            outResult.value = result;
-                            if (result == Result.SUCCESS) prop.setLong(value);
-                        });
-                        break;
-                    case BatteryManager.BATTERY_PROPERTY_STATUS:
-                        service.getChargeStatus((int result, int value) -> {
-                            outResult.value = result;
-                            if (result == Result.SUCCESS) prop.setLong(value);
-                        });
-                        break;
-                    case BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
-                        service.getEnergyCounter((int result, long value) -> {
-                            outResult.value = result;
-                            if (result == Result.SUCCESS) prop.setLong(value);
-                        });
-                        break;
-                }
-                return outResult.value;
-            } finally {
-                traceEnd();
-            }
+            return mHealthServiceWrapper.getProperty(id, prop);
         }
         @Override
         public void scheduleUpdate() throws RemoteException {
-            mHealthServiceWrapper.getHandlerThread().getThreadHandler().post(() -> {
-                traceBegin("HealthScheduleUpdate");
-                try {
-                    IHealth service = mHealthServiceWrapper.getLastService();
-                    if (service == null) {
-                        Slog.e(TAG, "no health service");
-                        return;
-                    }
-                    service.update();
-                } catch (RemoteException ex) {
-                    Slog.e(TAG, "Cannot call update on health HAL", ex);
-                } finally {
-                    traceEnd();
-                }
-            });
+            mHealthServiceWrapper.scheduleUpdate();
         }
     }
 
@@ -1360,14 +1222,14 @@
         @Override
         public int getBatteryChargeCounter() {
             synchronized (mLock) {
-                return mHealthInfo.batteryChargeCounter;
+                return mHealthInfo.batteryChargeCounterUah;
             }
         }
 
         @Override
         public int getBatteryFullCharge() {
             synchronized (mLock) {
-                return mHealthInfo.batteryFullCharge;
+                return mHealthInfo.batteryFullChargeUah;
             }
         }
 
@@ -1420,191 +1282,4 @@
             BatteryService.this.suspendBatteryInput();
         }
     }
-
-    /**
-     * HealthServiceWrapper wraps the internal IHealth service and refreshes the service when
-     * necessary.
-     *
-     * On new registration of IHealth service, {@link #onRegistration onRegistration} is called and
-     * the internal service is refreshed.
-     * On death of an existing IHealth service, the internal service is NOT cleared to avoid
-     * race condition between death notification and new service notification. Hence,
-     * a caller must check for transaction errors when calling into the service.
-     *
-     * @hide Should only be used internally.
-     */
-    public static final class HealthServiceWrapper {
-        private static final String TAG = "HealthServiceWrapper";
-        public static final String INSTANCE_HEALTHD = "backup";
-        public static final String INSTANCE_VENDOR = "default";
-        // All interesting instances, sorted by priority high -> low.
-        private static final List<String> sAllInstances =
-                Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD);
-
-        private final IServiceNotification mNotification = new Notification();
-        private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceHwbinder");
-        // These variables are fixed after init.
-        private Callback mCallback;
-        private IHealthSupplier mHealthSupplier;
-        private String mInstanceName;
-
-        // Last IHealth service received.
-        private final AtomicReference<IHealth> mLastService = new AtomicReference<>();
-
-        /**
-         * init should be called after constructor. For testing purposes, init is not called by
-         * constructor.
-         */
-        public HealthServiceWrapper() {
-        }
-
-        public IHealth getLastService() {
-            return mLastService.get();
-        }
-
-        /**
-         * See {@link #init(Callback, IServiceManagerSupplier, IHealthSupplier)}
-         */
-        public void init() throws RemoteException, NoSuchElementException {
-            init(/* callback= */null, new HealthServiceWrapper.IServiceManagerSupplier() {},
-                    new HealthServiceWrapper.IHealthSupplier() {});
-        }
-
-        /**
-         * Start monitoring registration of new IHealth services. Only instances that are in
-         * {@code sAllInstances} and in device / framework manifest are used. This function should
-         * only be called once.
-         *
-         * mCallback.onRegistration() is called synchronously (aka in init thread) before
-         * this method returns if callback is not null.
-         *
-         * @throws RemoteException transaction error when talking to IServiceManager
-         * @throws NoSuchElementException if one of the following cases:
-         *         - No service manager;
-         *         - none of {@code sAllInstances} are in manifests (i.e. not
-         *           available on this device), or none of these instances are available to current
-         *           process.
-         * @throws NullPointerException when supplier is null
-         */
-        void init(@Nullable Callback callback,
-                  IServiceManagerSupplier managerSupplier,
-                  IHealthSupplier healthSupplier)
-                throws RemoteException, NoSuchElementException, NullPointerException {
-            if (managerSupplier == null || healthSupplier == null) {
-                throw new NullPointerException();
-            }
-            IServiceManager manager;
-
-            mHealthSupplier = healthSupplier;
-
-            // Initialize mLastService and call callback for the first time (in init thread)
-            IHealth newService = null;
-            for (String name : sAllInstances) {
-                traceBegin("HealthInitGetService_" + name);
-                try {
-                    newService = healthSupplier.get(name);
-                } catch (NoSuchElementException ex) {
-                    /* ignored, handled below */
-                } finally {
-                    traceEnd();
-                }
-                if (newService != null) {
-                    mInstanceName = name;
-                    mLastService.set(newService);
-                    break;
-                }
-            }
-
-            if (mInstanceName == null || newService == null) {
-                throw new NoSuchElementException(String.format(
-                        "No IHealth service instance among %s is available. Perhaps no permission?",
-                        sAllInstances.toString()));
-            }
-
-            if (callback != null) {
-                mCallback = callback;
-                mCallback.onRegistration(null, newService, mInstanceName);
-            }
-
-            // Register for future service registrations
-            traceBegin("HealthInitRegisterNotification");
-            mHandlerThread.start();
-            try {
-                managerSupplier.get().registerForNotifications(
-                        IHealth.kInterfaceName, mInstanceName, mNotification);
-            } finally {
-                traceEnd();
-            }
-            Slog.i(TAG, "health: HealthServiceWrapper listening to instance " + mInstanceName);
-        }
-
-        @VisibleForTesting
-        HandlerThread getHandlerThread() {
-            return mHandlerThread;
-        }
-
-        interface Callback {
-            /**
-             * This function is invoked asynchronously when a new and related IServiceNotification
-             * is received.
-             * @param service the recently retrieved service from IServiceManager.
-             * Can be a dead service before service notification of a new service is delivered.
-             * Implementation must handle cases for {@link RemoteException}s when calling
-             * into service.
-             * @param instance instance name.
-             */
-            void onRegistration(IHealth oldService, IHealth newService, String instance);
-        }
-
-        /**
-         * Supplier of services.
-         * Must not return null; throw {@link NoSuchElementException} if a service is not available.
-         */
-        interface IServiceManagerSupplier {
-            default IServiceManager get() throws NoSuchElementException, RemoteException {
-                return IServiceManager.getService();
-            }
-        }
-        /**
-         * Supplier of services.
-         * Must not return null; throw {@link NoSuchElementException} if a service is not available.
-         */
-        interface IHealthSupplier {
-            default IHealth get(String name) throws NoSuchElementException, RemoteException {
-                return IHealth.getService(name, true /* retry */);
-            }
-        }
-
-        private class Notification extends IServiceNotification.Stub {
-            @Override
-            public final void onRegistration(String interfaceName, String instanceName,
-                    boolean preexisting) {
-                if (!IHealth.kInterfaceName.equals(interfaceName)) return;
-                if (!mInstanceName.equals(instanceName)) return;
-
-                // This runnable only runs on mHandlerThread and ordering is ensured, hence
-                // no locking is needed inside the runnable.
-                mHandlerThread.getThreadHandler().post(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            IHealth newService = mHealthSupplier.get(mInstanceName);
-                            IHealth oldService = mLastService.getAndSet(newService);
-
-                            // preexisting may be inaccurate (race). Check for equality here.
-                            if (Objects.equals(newService, oldService)) return;
-
-                            Slog.i(TAG, "health: new instance registered " + mInstanceName);
-                            // #init() may be called with null callback. Skip null callbacks.
-                            if (mCallback == null) return;
-                            mCallback.onRegistration(oldService, newService, mInstanceName);
-                        } catch (NoSuchElementException | RemoteException ex) {
-                            Slog.e(TAG, "health: Cannot get instance '" + mInstanceName
-                                    + "': " + ex.getMessage() + ". Perhaps no permission?");
-                        }
-                    }
-                });
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index d6ee951..aeb8143 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -58,13 +58,13 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Range;
-import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
+import com.android.net.module.util.BinderUtils;
 import com.android.net.module.util.NetdUtils;
 import com.android.net.module.util.PermissionUtils;
 
@@ -1056,9 +1056,9 @@
 
     public void systemReady() {
         if (isNetdAlive()) {
-            Slog.d(TAG, "IpSecService is ready");
+            Log.d(TAG, "IpSecService is ready");
         } else {
-            Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
+            Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
         }
     }
 
@@ -1332,7 +1332,7 @@
             final INetd netd = mSrvConfig.getNetdInstance();
             netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
 
-            Binder.withCleanCallingIdentity(() -> {
+            BinderUtils.withCleanCallingIdentity(() -> {
                 NetdUtils.setInterfaceUp(netd, intfName);
             });
 
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 3ea0ce1..c7e9068 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -59,9 +59,6 @@
 import android.net.RouteInfo;
 import android.net.TetherStatsParcel;
 import android.net.UidRangeParcel;
-import android.net.shared.NetdUtils;
-import android.net.shared.RouteUtils;
-import android.net.shared.RouteUtils.ModifyOperation;
 import android.net.util.NetdService;
 import android.os.BatteryStats;
 import android.os.Binder;
@@ -88,6 +85,8 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.Preconditions;
+import com.android.net.module.util.NetdUtils;
+import com.android.net.module.util.NetdUtils.ModifyOperation;
 
 import com.google.android.collect.Maps;
 
@@ -831,13 +830,13 @@
     @Override
     public void addRoute(int netId, RouteInfo route) {
         NetworkStack.checkNetworkStackPermission(mContext);
-        RouteUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
+        NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
     }
 
     @Override
     public void removeRoute(int netId, RouteInfo route) {
         NetworkStack.checkNetworkStackPermission(mContext);
-        RouteUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
+        NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
     }
 
     private ArrayList<String> readRouteList(String filename) {
@@ -1785,7 +1784,7 @@
     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
         modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
         // modifyInterfaceInNetwork already check calling permission.
-        RouteUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
+        NetdUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
     }
 
     @Override
@@ -1796,7 +1795,7 @@
     @Override
     public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
         NetworkStack.checkNetworkStackPermission(mContext);
-        return RouteUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
+        return NetdUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index c11c4de..5ed6c86 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -47,6 +47,7 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.telecom.TelecomManager;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SrvccState;
@@ -1029,7 +1030,6 @@
             return;
         }
 
-        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             // register
             IBinder b = callback.asBinder();
@@ -1052,21 +1052,24 @@
             // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
             // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
             if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+                if (DBG) {
+                    log("invalid subscription id, use default id");
+                }
                 r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
             } else {//APP specify subID
                 r.subId = subId;
             }
-            r.phoneId = phoneId;
+            r.phoneId = getPhoneIdFromSubId(r.subId);
             r.eventList = events;
 
             if (DBG) {
-                log("listen:  Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
+                log("listen:  Register r=" + r + " r.subId=" + r.subId + " r.phoneId=" + r.phoneId);
             }
-            if (notifyNow && validatePhoneId(phoneId)) {
+            if (notifyNow && validatePhoneId(r.phoneId)) {
                 if (events.contains(TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)){
                     try {
-                        if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
-                        ServiceState rawSs = new ServiceState(mServiceState[phoneId]);
+                        if (VDBG) log("listen: call onSSC state=" + mServiceState[r.phoneId]);
+                        ServiceState rawSs = new ServiceState(mServiceState[r.phoneId]);
                         if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                             r.callback.onServiceStateChanged(rawSs);
                         } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
@@ -1082,8 +1085,8 @@
                 }
                 if (events.contains(TelephonyCallback.EVENT_SIGNAL_STRENGTH_CHANGED)) {
                     try {
-                        if (mSignalStrength[phoneId] != null) {
-                            int gsmSignalStrength = mSignalStrength[phoneId]
+                        if (mSignalStrength[r.phoneId] != null) {
+                            int gsmSignalStrength = mSignalStrength[r.phoneId]
                                     .getGsmSignalStrength();
                             r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
                                     : gsmSignalStrength));
@@ -1096,7 +1099,7 @@
                         TelephonyCallback.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) {
                     try {
                         r.callback.onMessageWaitingIndicatorChanged(
-                                mMessageWaiting[phoneId]);
+                                mMessageWaiting[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
@@ -1105,7 +1108,7 @@
                         TelephonyCallback.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) {
                     try {
                         r.callback.onCallForwardingIndicatorChanged(
-                                mCallForwarding[phoneId]);
+                                mCallForwarding[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
@@ -1113,11 +1116,11 @@
                 if (validateEventAndUserLocked(
                         r, TelephonyCallback.EVENT_CELL_LOCATION_CHANGED)) {
                     try {
-                        if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
+                        if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[r.phoneId]);
                         if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
                                 && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                             // null will be translated to empty CellLocation object in client.
-                            r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
+                            r.callback.onCellLocationChanged(mCellIdentity[r.phoneId]);
                         }
                     } catch (RemoteException ex) {
                         remove(r.binder);
@@ -1125,49 +1128,38 @@
                 }
                 if (events.contains(TelephonyCallback.EVENT_LEGACY_CALL_STATE_CHANGED)) {
                     try {
-                        r.callback.onLegacyCallStateChanged(mCallState[phoneId],
-                                getCallIncomingNumber(r, phoneId));
+                        r.callback.onLegacyCallStateChanged(mCallState[r.phoneId],
+                                getCallIncomingNumber(r, r.phoneId));
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_CALL_STATE_CHANGED)) {
                     try {
-                        r.callback.onCallStateChanged(mCallState[phoneId]);
+                        r.callback.onCallStateChanged(mCallState[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED)) {
                     try {
-                        r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
-                                mDataConnectionNetworkType[phoneId]);
+                        r.callback.onDataConnectionStateChanged(mDataConnectionState[r.phoneId],
+                                mDataConnectionNetworkType[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_DATA_ACTIVITY_CHANGED)) {
                     try {
-                        r.callback.onDataActivity(mDataActivity[phoneId]);
+                        r.callback.onDataActivity(mDataActivity[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)) {
                     try {
-                        if (mSignalStrength[phoneId] != null) {
-                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
-                        }
-                    } catch (RemoteException ex) {
-                        remove(r.binder);
-                    }
-                }
-                if (events.contains(
-                        TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
-                    updateReportSignalStrengthDecision(r.subId);
-                    try {
-                        if (mSignalStrength[phoneId] != null) {
-                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+                        if (mSignalStrength[r.phoneId] != null) {
+                            r.callback.onSignalStrengthsChanged(mSignalStrength[r.phoneId]);
                         }
                     } catch (RemoteException ex) {
                         remove(r.binder);
@@ -1176,11 +1168,13 @@
                 if (validateEventAndUserLocked(
                         r, TelephonyCallback.EVENT_CELL_INFO_CHANGED)) {
                     try {
-                        if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
-                                + mCellInfo.get(phoneId));
+                        if (DBG_LOC) {
+                            log("listen: mCellInfo[" + r.phoneId + "] = "
+                                    + mCellInfo.get(r.phoneId));
+                        }
                         if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
                                 && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
-                            r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+                            r.callback.onCellInfoChanged(mCellInfo.get(r.phoneId));
                         }
                     } catch (RemoteException ex) {
                         remove(r.binder);
@@ -1188,22 +1182,22 @@
                 }
                 if (events.contains(TelephonyCallback.EVENT_PRECISE_CALL_STATE_CHANGED)) {
                     try {
-                        r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
+                        r.callback.onPreciseCallStateChanged(mPreciseCallState[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_CALL_DISCONNECT_CAUSE_CHANGED)) {
                     try {
-                        r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
-                                mCallPreciseDisconnectCause[phoneId]);
+                        r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[r.phoneId],
+                                mCallPreciseDisconnectCause[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)) {
                     try {
-                        r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
+                        r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(r.phoneId));
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
@@ -1212,7 +1206,7 @@
                         TelephonyCallback.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)) {
                     try {
                         for (PreciseDataConnectionState pdcs
-                                : mPreciseDataConnectionStates.get(phoneId).values()) {
+                                : mPreciseDataConnectionStates.get(r.phoneId).values()) {
                             r.callback.onPreciseDataConnectionStateChanged(pdcs);
                         }
                     } catch (RemoteException ex) {
@@ -1229,29 +1223,29 @@
                 if (events.contains(TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED)) {
                     try {
                         r.callback.onVoiceActivationStateChanged(
-                                mVoiceActivationState[phoneId]);
+                                mVoiceActivationState[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_DATA_ACTIVATION_STATE_CHANGED)) {
                     try {
-                        r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]);
+                        r.callback.onDataActivationStateChanged(mDataActivationState[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) {
                     try {
-                        r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
+                        r.callback.onUserMobileDataStateChanged(mUserMobileDataState[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED)) {
                     try {
-                        if (mTelephonyDisplayInfos[phoneId] != null) {
-                            r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]);
+                        if (mTelephonyDisplayInfos[r.phoneId] != null) {
+                            r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[r.phoneId]);
                         }
                     } catch (RemoteException ex) {
                         remove(r.binder);
@@ -1288,20 +1282,20 @@
                 }
                 if (events.contains(TelephonyCallback.EVENT_SRVCC_STATE_CHANGED)) {
                     try {
-                        r.callback.onSrvccStateChanged(mSrvccState[phoneId]);
+                        r.callback.onSrvccStateChanged(mSrvccState[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)) {
                     try {
-                        r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+                        r.callback.onCallAttributesChanged(mCallAttributes[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
                 if (events.contains(TelephonyCallback.EVENT_BARRING_INFO_CHANGED)) {
-                    BarringInfo barringInfo = mBarringInfo.get(phoneId);
+                    BarringInfo barringInfo = mBarringInfo.get(r.phoneId);
                     BarringInfo biNoLocation = barringInfo != null
                             ? barringInfo.createLocationInfoSanitizedCopy() : null;
                     if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
@@ -1319,8 +1313,8 @@
                         r.callback.onPhysicalChannelConfigChanged(
                                 shouldSanitizeLocationForPhysicalChannelConfig(r)
                                         ? getLocationSanitizedConfigs(
-                                                mPhysicalChannelConfigs.get(phoneId))
-                                        : mPhysicalChannelConfigs.get(phoneId));
+                                                mPhysicalChannelConfigs.get(r.phoneId))
+                                        : mPhysicalChannelConfigs.get(r.phoneId));
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
@@ -1329,7 +1323,7 @@
                         TelephonyCallback.EVENT_DATA_ENABLED_CHANGED)) {
                     try {
                         r.callback.onDataEnabledChanged(
-                                mIsDataEnabled[phoneId], mDataEnabledReason[phoneId]);
+                                mIsDataEnabled[r.phoneId], mDataEnabledReason[r.phoneId]);
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
@@ -1337,9 +1331,9 @@
                 if (events.contains(
                         TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED)) {
                     try {
-                        if (mLinkCapacityEstimateLists.get(phoneId) != null) {
+                        if (mLinkCapacityEstimateLists.get(r.phoneId) != null) {
                             r.callback.onLinkCapacityEstimateChanged(mLinkCapacityEstimateLists
-                                    .get(phoneId));
+                                    .get(r.phoneId));
                         }
                     } catch (RemoteException ex) {
                         remove(r.binder);
@@ -1349,27 +1343,6 @@
         }
     }
 
-    private void updateReportSignalStrengthDecision(int subscriptionId) {
-        synchronized (mRecords) {
-            TelephonyManager telephonyManager = (TelephonyManager) mContext
-                    .getSystemService(Context.TELEPHONY_SERVICE);
-            for (Record r : mRecords) {
-                // If any of the system clients wants to always listen to signal strength,
-                // we need to set it on.
-                if (r.matchTelephonyCallbackEvent(
-                        TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
-                    telephonyManager.createForSubscriptionId(subscriptionId)
-                            .setAlwaysReportSignalStrength(true);
-                    return;
-                }
-            }
-            // If none of the system clients wants to always listen to signal strength,
-            // we need to set it off.
-            telephonyManager.createForSubscriptionId(subscriptionId)
-                    .setAlwaysReportSignalStrength(false);
-        }
-    }
-
     private String getCallIncomingNumber(Record record, int phoneId) {
         // Only reveal the incoming number if the record has read call log permission.
         return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : "";
@@ -1453,14 +1426,6 @@
                     }
 
                     mRecords.remove(i);
-
-                    // Every time a client that is registrating to always receive the signal
-                    // strength is removed from registry records, we need to check if
-                    // the signal strength decision needs to update on its slot.
-                    if (r.matchTelephonyCallbackEvent(
-                            TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
-                        updateReportSignalStrengthDecision(r.subId);
-                    }
                     return;
                 }
             }
@@ -1581,7 +1546,7 @@
                     }
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
 
                         try {
                             ServiceState stateToSend;
@@ -1643,7 +1608,7 @@
                         if ((activationType == SIM_ACTIVATION_TYPE_VOICE)
                                 && r.matchTelephonyCallbackEvent(
                                         TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
-                                && idMatch(r.subId, subId, phoneId)) {
+                                && idMatch(r, subId, phoneId)) {
                             if (DBG) {
                                 log("notifyVoiceActivationStateForPhoneId: callback.onVASC r=" + r
                                         + " subId=" + subId + " phoneId=" + phoneId
@@ -1654,7 +1619,7 @@
                         if ((activationType == SIM_ACTIVATION_TYPE_DATA)
                                 && r.matchTelephonyCallbackEvent(
                                         TelephonyCallback.EVENT_DATA_ACTIVATION_STATE_CHANGED)
-                                && idMatch(r.subId, subId, phoneId)) {
+                                && idMatch(r, subId, phoneId)) {
                             if (DBG) {
                                 log("notifyDataActivationStateForPhoneId: callback.onDASC r=" + r
                                         + " subId=" + subId + " phoneId=" + phoneId
@@ -1692,11 +1657,9 @@
                         log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId
                                 + " phoneId=" + phoneId + " ss=" + signalStrength);
                     }
-                    if ((r.matchTelephonyCallbackEvent(
+                    if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)
-                            || r.matchTelephonyCallbackEvent(
-                            TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (DBG) {
                                 log("notifySignalStrengthForPhoneId: callback.onSsS r=" + r
@@ -1710,7 +1673,7 @@
                     }
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_SIGNAL_STRENGTH_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             int gsmSignalStrength = signalStrength.getGsmSignalStrength();
                             int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
@@ -1757,7 +1720,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onCarrierNetworkChange(active);
                         } catch (RemoteException ex) {
@@ -1789,7 +1752,7 @@
                 for (Record r : mRecords) {
                     if (validateEventAndUserLocked(
                             r, TelephonyCallback.EVENT_CELL_INFO_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)
+                            && idMatch(r, subId, phoneId)
                             && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
                                     && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
                         try {
@@ -1823,7 +1786,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onMessageWaitingIndicatorChanged(mwi);
                         } catch (RemoteException ex) {
@@ -1850,7 +1813,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_USER_MOBILE_DATA_STATE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onUserMobileDataStateChanged(state);
                         } catch (RemoteException ex) {
@@ -1889,7 +1852,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED)
-                            && idMatchWithoutDefaultPhoneCheck(r.subId, subId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (!mConfigurationProvider.isDisplayInfoNrAdvancedSupported(
                                     r.callingPackage, Binder.getCallingUserHandle())) {
@@ -1940,7 +1903,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onCallForwardingIndicatorChanged(cfi);
                         } catch (RemoteException ex) {
@@ -1969,7 +1932,7 @@
                     // Notify by correct subId.
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_DATA_ACTIVITY_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onDataActivity(state);
                         } catch (RemoteException ex) {
@@ -1998,42 +1961,8 @@
 
         ApnSetting apnSetting = preciseState.getApnSetting();
 
-        int apnTypes = apnSetting.getApnTypeBitmask();
-        int state = preciseState.getState();
-        int networkType = preciseState.getNetworkType();
-
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
-                // We only call the callback when the change is for default APN type.
-                if ((ApnSetting.TYPE_DEFAULT & apnTypes) != 0
-                        && (mDataConnectionState[phoneId] != state
-                        || mDataConnectionNetworkType[phoneId] != networkType)) {
-                    String str = "onDataConnectionStateChanged("
-                            + TelephonyUtils.dataStateToString(state)
-                            + ", " + getNetworkTypeName(networkType)
-                            + ") subId=" + subId + ", phoneId=" + phoneId;
-                    log(str);
-                    mLocalLog.log(str);
-                    for (Record r : mRecords) {
-                        if (r.matchTelephonyCallbackEvent(
-                                TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED)
-                                && idMatch(r.subId, subId, phoneId)) {
-                            try {
-                                if (DBG) {
-                                    log("Notify data connection state changed on sub: " + subId);
-                                }
-                                r.callback.onDataConnectionStateChanged(state, networkType);
-                            } catch (RemoteException ex) {
-                                mRemoveList.add(r.binder);
-                            }
-                        }
-                    }
-                    handleRemoveListLocked();
-
-                    mDataConnectionState[phoneId] = state;
-                    mDataConnectionNetworkType[phoneId] = networkType;
-                }
-
                 Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(),
                         preciseState.getApnSetting());
                 PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId)
@@ -2042,7 +1971,7 @@
                     for (Record r : mRecords) {
                         if (r.matchTelephonyCallbackEvent(
                                 TelephonyCallback.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)
-                                && idMatch(r.subId, subId, phoneId)) {
+                                && idMatch(r, subId, phoneId)) {
                             try {
                                 r.callback.onPreciseDataConnectionStateChanged(preciseState);
                             } catch (RemoteException ex) {
@@ -2065,6 +1994,73 @@
                 if (preciseState.getState() != TelephonyManager.DATA_DISCONNECTED) {
                     mPreciseDataConnectionStates.get(phoneId).put(key, preciseState);
                 }
+
+                // Note that below is just the workaround for reporting the correct data connection
+                // state. The actual fix should be put in the new data stack in T.
+                // TODO: Remove the code below in T.
+
+                // Collect all possible candidate data connection state for internet. Key is the
+                // data connection state, value is the precise data connection state.
+                Map<Integer, PreciseDataConnectionState> internetConnections = new ArrayMap<>();
+                if (preciseState.getState() == TelephonyManager.DATA_DISCONNECTED
+                        && preciseState.getApnSetting().getApnTypes()
+                        .contains(ApnSetting.TYPE_DEFAULT)) {
+                    internetConnections.put(TelephonyManager.DATA_DISCONNECTED, preciseState);
+                }
+                for (Map.Entry<Pair<Integer, ApnSetting>, PreciseDataConnectionState> entry :
+                        mPreciseDataConnectionStates.get(phoneId).entrySet()) {
+                    if (entry.getKey().first == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
+                            && entry.getKey().second.getApnTypes()
+                            .contains(ApnSetting.TYPE_DEFAULT)) {
+                        internetConnections.put(entry.getValue().getState(), entry.getValue());
+                    }
+                }
+
+                // If any internet data is in connected state, then report connected, then check
+                // suspended, connecting, disconnecting, and disconnected. The order is very
+                // important.
+                int[] statesInPriority = new int[]{TelephonyManager.DATA_CONNECTED,
+                        TelephonyManager.DATA_SUSPENDED, TelephonyManager.DATA_CONNECTING,
+                        TelephonyManager.DATA_DISCONNECTING,
+                        TelephonyManager.DATA_DISCONNECTED};
+                int state = TelephonyManager.DATA_DISCONNECTED;
+                int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+                for (int s : statesInPriority) {
+                    if (internetConnections.containsKey(s)) {
+                        state = s;
+                        networkType = internetConnections.get(s).getNetworkType();
+                        break;
+                    }
+                }
+
+                if (mDataConnectionState[phoneId] != state
+                        || mDataConnectionNetworkType[phoneId] != networkType) {
+                    String str = "onDataConnectionStateChanged("
+                            + TelephonyUtils.dataStateToString(state)
+                            + ", " + TelephonyManager.getNetworkTypeName(networkType)
+                            + ") subId=" + subId + ", phoneId=" + phoneId;
+                    log(str);
+                    mLocalLog.log(str);
+                    for (Record r : mRecords) {
+                        if (r.matchTelephonyCallbackEvent(
+                                TelephonyCallback.EVENT_DATA_CONNECTION_STATE_CHANGED)
+                                && idMatch(r, subId, phoneId)) {
+                            try {
+                                if (DBG) {
+                                    log("Notify data connection state changed on sub: " + subId);
+                                }
+                                r.callback.onDataConnectionStateChanged(state, networkType);
+                            } catch (RemoteException ex) {
+                                mRemoveList.add(r.binder);
+                            }
+                        }
+                    }
+
+                    mDataConnectionState[phoneId] = state;
+                    mDataConnectionNetworkType[phoneId] = networkType;
+
+                    handleRemoveListLocked();
+                }
             }
         }
     }
@@ -2089,7 +2085,7 @@
                 for (Record r : mRecords) {
                     if (validateEventAndUserLocked(
                             r, TelephonyCallback.EVENT_CELL_LOCATION_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)
+                            && idMatch(r, subId, phoneId)
                             && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
                                     && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
                         try {
@@ -2143,7 +2139,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_PRECISE_CALL_STATE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
                         } catch (RemoteException ex) {
@@ -2152,7 +2148,7 @@
                     }
                     if (notifyCallAttributes && r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
                         } catch (RemoteException ex) {
@@ -2177,7 +2173,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_CALL_DISCONNECT_CAUSE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
                                     mCallPreciseDisconnectCause[phoneId]);
@@ -2202,7 +2198,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyImsCallDisconnectCause: mImsReasonInfo="
@@ -2234,7 +2230,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_SRVCC_STATE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifySrvccStateChanged: mSrvccState=" + state + " r=" + r);
@@ -2263,7 +2259,7 @@
                     }
                     if ((r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_OEM_HOOK_RAW))
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onOemHookRawEvent(rawData);
                         } catch (RemoteException ex) {
@@ -2343,7 +2339,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onRadioPowerStateChanged(state);
                         } catch (RemoteException ex) {
@@ -2372,7 +2368,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
                             if (VDBG) {
@@ -2459,7 +2455,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
                         } catch (RemoteException ex) {
@@ -2490,7 +2486,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_REGISTRATION_FAILURE)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onRegistrationFailed(
                                     checkFineLocationAccess(r, Build.VERSION_CODES.BASE)
@@ -2533,7 +2529,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_BARRING_INFO_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyBarringInfo: mBarringInfo="
@@ -2578,7 +2574,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyPhysicalChannelConfig: mPhysicalChannelConfigs="
@@ -2645,7 +2641,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_DATA_ENABLED_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onDataEnabledChanged(enabled, reason);
                         } catch (RemoteException ex) {
@@ -2680,7 +2676,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             if (VDBG) {
                                 log("notifyAllowedNetworkTypesChanged: reason= " + reason
@@ -2722,7 +2718,7 @@
                 for (Record r : mRecords) {
                     if (r.matchTelephonyCallbackEvent(
                             TelephonyCallback.EVENT_LINK_CAPACITY_ESTIMATE_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
+                            && idMatch(r, subId, phoneId)) {
                         try {
                             r.callback.onLinkCapacityEstimateChanged(linkCapacityEstimateList);
                         } catch (RemoteException ex) {
@@ -3115,11 +3111,6 @@
                     android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
         }
 
-        if ((events.contains(TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null);
-        }
-
         if (isPrivilegedPhoneStatePermissionRequired(events)) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
@@ -3172,33 +3163,24 @@
     }
 
     /**
-     * If the registrant specified a subId, then we should only notify it if subIds match.
-     * If the registrant registered with DEFAULT subId, we should notify only when the related subId
-     * is default subId (which could be INVALID if there's no default subId).
+     * Match the sub id or phone id of the event to the record
      *
-     * This should be the correct way to check record ID match. in idMatch the record's phoneId is
-     * speculated based on subId passed by the registrant so it's not a good reference.
-     * But to avoid triggering potential regression only replace idMatch with it when an issue with
-     * idMatch is reported. Eventually this should replace all instances of idMatch.
+     * We follow the rules below:
+     * 1) If sub id of the event is invalid, phone id should be used.
+     * 2) The event on default sub should be notified to the records
+     * which register the default sub id.
+     * 3) Sub id should be exactly matched for all other cases.
      */
-    private boolean idMatchWithoutDefaultPhoneCheck(int subIdInRecord, int subIdToNotify) {
-        if (subIdInRecord == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-            return (subIdToNotify == mDefaultSubId);
-        } else {
-            return (subIdInRecord == subIdToNotify);
-        }
-    }
+    boolean idMatch(Record r, int subId, int phoneId) {
 
-    boolean idMatch(int rSubId, int subId, int phoneId) {
-
-        if(subId < 0) {
-            // Invalid case, we need compare phoneId with default one.
-            return (mDefaultPhoneId == phoneId);
+        if (subId < 0) {
+            // Invalid case, we need compare phoneId.
+            return (r.phoneId == phoneId);
         }
-        if(rSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+        if (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
             return (subId == mDefaultSubId);
         } else {
-            return (rSubId == subId);
+            return (r.subId == subId);
         }
     }
 
@@ -3289,9 +3271,7 @@
             }
         }
 
-        if (events.contains(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)
-                || events.contains(
-                TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
+        if (events.contains(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)) {
             try {
                 if (mSignalStrength[phoneId] != null) {
                     SignalStrength signalStrength = mSignalStrength[phoneId];
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index a03425c..b48e21e 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -681,7 +681,7 @@
         intentFilter = new IntentFilter();
         intentFilter.addAction(LockdownVpnTracker.ACTION_LOCKDOWN_RESET);
         mUserAllContext.registerReceiver(
-                mIntentReceiver, intentFilter, NETWORK_STACK, mHandler);
+                mIntentReceiver, intentFilter, NETWORK_STACK, mHandler, Context.RECEIVER_EXPORTED);
     }
 
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 731f7fe..ab2147d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1834,6 +1834,11 @@
                                 + ", skipping since the account already exists");
                         return false;
                     }
+                    if (accounts.accountsDb.findAllDeAccounts().size() > 100) {
+                        Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
+                                + ", skipping since more than 50 accounts on device exist");
+                        return false;
+                    }
                     long accountId = accounts.accountsDb.insertCeAccount(account, password);
                     if (accountId < 0) {
                         Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 3ccacd8..c5ac390 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -94,6 +94,8 @@
         DeviceConfig.NAMESPACE_STATSD_NATIVE,
         DeviceConfig.NAMESPACE_STATSD_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+        DeviceConfig.NAMESPACE_TETHERING,
+        DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE,
         DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
     };
 
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 0cd2e3d..c97ad55 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -60,6 +60,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
@@ -70,6 +71,7 @@
 import com.android.server.SystemService;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -81,6 +83,8 @@
     private static final String SETTING_HIDL_DISABLED =
             "com.android.server.biometrics.AuthService.hidlDisabled";
     private static final int DEFAULT_HIDL_DISABLED = 0;
+    private static final String SYSPROP_FIRST_API_LEVEL = "ro.board.first_api_level";
+    private static final String SYSPROP_API_LEVEL = "ro.board.api_level";
 
     private final Injector mInjector;
 
@@ -623,7 +627,16 @@
 
         final SensorConfig[] hidlConfigs;
         if (!mInjector.isHidlDisabled(getContext())) {
-            final String[] configStrings = mInjector.getConfiguration(getContext());
+            final int firstApiLevel = SystemProperties.getInt(SYSPROP_FIRST_API_LEVEL, 0);
+            final int apiLevel = SystemProperties.getInt(SYSPROP_API_LEVEL, firstApiLevel);
+            String[] configStrings = mInjector.getConfiguration(getContext());
+            if (configStrings.length == 0 && apiLevel == Build.VERSION_CODES.R) {
+                // For backwards compatibility with R where biometrics could work without being
+                // configured in config_biometric_sensors. In the absence of a vendor provided
+                // configuration, we assume the weakest biometric strength (i.e. convenience).
+                Slog.w(TAG, "Found R vendor partition without config_biometric_sensors");
+                configStrings = generateRSdkCompatibleConfiguration();
+            }
             hidlConfigs = new SensorConfig[configStrings.length];
             for (int i = 0; i < configStrings.length; ++i) {
                 hidlConfigs[i] = new SensorConfig(configStrings[i]);
@@ -639,6 +652,31 @@
     }
 
     /**
+     * Generates an array of string configs with entries that correspond to the biometric features
+     * declared on the device. Returns an empty array if no biometric features are declared.
+     * Biometrics are assumed to be of the weakest strength class, i.e. convenience.
+     */
+    private @NonNull String[] generateRSdkCompatibleConfiguration() {
+        final PackageManager pm = getContext().getPackageManager();
+        final ArrayList<String> modalities = new ArrayList<>();
+        if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+            modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FINGERPRINT));
+        }
+        if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+            modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FACE));
+        }
+        final String strength = String.valueOf(Authenticators.BIOMETRIC_CONVENIENCE);
+        final String[] configStrings = new String[modalities.size()];
+        for (int i = 0; i < modalities.size(); ++i) {
+            final String id = String.valueOf(i);
+            final String modality = modalities.get(i);
+            configStrings[i] = String.join(":" /* delimiter */, id, modality, strength);
+        }
+        Slog.d(TAG, "Generated config_biometric_sensors: " + Arrays.toString(configStrings));
+        return configStrings;
+    }
+
+    /**
      * Registers HIDL and AIDL authenticators for all of the available modalities.
      *
      * @param hidlSensors Array of {@link SensorConfig} configuration for all of the HIDL sensors
diff --git a/services/core/java/com/android/server/compat/OWNERS b/services/core/java/com/android/server/compat/OWNERS
index cfd0a4b..ee3086a 100644
--- a/services/core/java/com/android/server/compat/OWNERS
+++ b/services/core/java/com/android/server/compat/OWNERS
@@ -1,6 +1 @@
-# Use this reviewer by default.
-platform-compat-eng+reviews@google.com
-
-andreionea@google.com
-mathewi@google.com
-satayev@google.com
+include tools/platform-compat:/OWNERS
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 091e6c4..a56a8ea 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -227,7 +227,7 @@
             subscriberId = tele.getSubscriberId();
             mNetworkTemplate = new NetworkTemplate(
                     NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
-                    null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+                    null, NetworkStats.METERED_YES, NetworkStats.ROAMING_ALL,
                     NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
                     SUBSCRIBER_ID_MATCH_RULE_EXACT);
             mUsageCallback = new UsageCallback() {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 243a336b..bf4ef48 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -126,6 +126,7 @@
 import libcore.io.IoUtils;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -195,6 +196,7 @@
 
     private final Context mContext;
     private final ConnectivityManager mConnectivityManager;
+    private final AppOpsManager mAppOpsManager;
     // The context is for specific user which is created from mUserId
     private final Context mUserIdContext;
     @VisibleForTesting final Dependencies mDeps;
@@ -407,6 +409,46 @@
         public boolean isInterfacePresent(final Vpn vpn, final String iface) {
             return vpn.jniCheck(iface) != 0;
         }
+
+        /**
+         * @see ParcelFileDescriptor#adoptFd(int)
+         */
+        public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) {
+            return ParcelFileDescriptor.adoptFd(jniCreate(vpn, mtu));
+        }
+
+        /**
+         * Call native method to create the VPN interface and return the FileDescriptor of /dev/tun.
+         */
+        public int jniCreate(Vpn vpn, int mtu) {
+            return vpn.jniCreate(mtu);
+        }
+
+        /**
+         * Call native method to get the interface name of VPN.
+         */
+        public String jniGetName(Vpn vpn, int fd) {
+            return vpn.jniGetName(fd);
+        }
+
+        /**
+         * Call native method to set the VPN addresses and return the number of addresses.
+         */
+        public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) {
+            return vpn.jniSetAddresses(interfaze, addresses);
+        }
+
+        /**
+         * @see IoUtils#setBlocking(FileDescriptor, boolean)
+         */
+        public void setBlocking(FileDescriptor fd, boolean blocking) {
+            try {
+                IoUtils.setBlocking(fd, blocking);
+            } catch (IOException e) {
+                throw new IllegalStateException(
+                        "Cannot set tunnel's fd as blocking=" + blocking, e);
+            }
+        }
     }
 
     public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
@@ -431,6 +473,7 @@
         mVpnProfileStore = vpnProfileStore;
         mContext = context;
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
         mDeps = deps;
         mNms = netService;
@@ -826,7 +869,6 @@
             VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage);
             if (profile != null) {
                 startVpnProfilePrivileged(profile, alwaysOnPackage);
-
                 // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was
                 // correctly parsed, and the VPN has started running in a different thread. The only
                 // other possibility is that the above call threw an exception, which will be
@@ -974,9 +1016,15 @@
                 } catch (Exception e) {
                     // ignore
                 }
+                mAppOpsManager.finishOp(
+                        AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null);
                 mContext.unbindService(mConnection);
                 cleanupVpnStateLocked();
             } else if (mVpnRunner != null) {
+                if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
+                    mAppOpsManager.finishOp(
+                            AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null);
+                }
                 // cleanupVpnStateLocked() is called from mVpnRunner.exit()
                 mVpnRunner.exit();
             }
@@ -1041,10 +1089,8 @@
                     return false;
             }
 
-            final AppOpsManager appOpMgr =
-                    (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
             for (final String appOpStr : toChange) {
-                appOpMgr.setMode(
+                mAppOpsManager.setMode(
                         appOpStr,
                         uid,
                         packageName,
@@ -1366,9 +1412,9 @@
         Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids();
 
         // Configure the interface. Abort if any of these steps fails.
-        ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
+        final ParcelFileDescriptor tun = mDeps.adoptFd(this, config.mtu);
         try {
-            String interfaze = jniGetName(tun.getFd());
+            final String interfaze = mDeps.jniGetName(this, tun.getFd());
 
             // TEMP use the old jni calls until there is support for netd address setting
             StringBuilder builder = new StringBuilder();
@@ -1376,7 +1422,7 @@
                 builder.append(" ");
                 builder.append(address);
             }
-            if (jniSetAddresses(interfaze, builder.toString()) < 1) {
+            if (mDeps.jniSetAddresses(this, interfaze, builder.toString()) < 1) {
                 throw new IllegalArgumentException("At least one address must be specified");
             }
             Connection connection = new Connection();
@@ -1422,11 +1468,11 @@
                 jniReset(oldInterface);
             }
 
-            try {
-                IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
-            } catch (IOException e) {
-                throw new IllegalStateException(
-                        "Cannot set tunnel's fd as blocking=" + config.blocking, e);
+            mDeps.setBlocking(tun.getFileDescriptor(), config.blocking);
+            // Record that the VPN connection is established by an app which uses VpnService API.
+            if (oldNetworkAgent != mNetworkAgent) {
+                mAppOpsManager.startOp(
+                        AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null, null);
             }
         } catch (RuntimeException e) {
             IoUtils.closeQuietly(tun);
@@ -1781,9 +1827,17 @@
             synchronized (Vpn.this) {
                 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
                     if (mConnection != null) {
+                        mAppOpsManager.finishOp(
+                                AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage,
+                                null);
                         mContext.unbindService(mConnection);
                         cleanupVpnStateLocked();
                     } else if (mVpnRunner != null) {
+                        if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
+                            mAppOpsManager.finishOp(
+                                    AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage,
+                                    null);
+                        }
                         // cleanupVpnStateLocked() is called from mVpnRunner.exit()
                         mVpnRunner.exit();
                     }
@@ -3254,8 +3308,7 @@
      *
      * @param packageName the package name of the app provisioning this profile
      */
-    public synchronized void startVpnProfile(
-            @NonNull String packageName) {
+    public synchronized void startVpnProfile(@NonNull String packageName) {
         requireNonNull(packageName, "No package name provided");
 
         enforceNotRestrictedUser();
@@ -3318,6 +3371,13 @@
                     Log.d(TAG, "Unknown VPN profile type: " + profile.type);
                     break;
             }
+
+            // Record that the VPN connection is established by an app which uses VpnManager API.
+            if (!VpnConfig.LEGACY_VPN.equals(packageName)) {
+                mAppOpsManager.startOp(
+                        AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null,
+                        null);
+            }
         } catch (GeneralSecurityException e) {
             // Reset mConfig
             mConfig = null;
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index d66d7ee..329a696 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -512,7 +512,10 @@
      */
     public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
         synchronized (mLock) {
-            mAlwaysRespectAppRequest = enabled;
+            if (mAlwaysRespectAppRequest != enabled) {
+                mAlwaysRespectAppRequest = enabled;
+                notifyDesiredDisplayModeSpecsChangedLocked();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index a2cb78d..c27293c 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -209,6 +209,12 @@
     void init() {
         assertRunOnServiceThread();
         mPreferredAddress = getPreferredAddress();
+        if (mHandler.hasMessages(MSG_DISABLE_DEVICE_TIMEOUT)) {
+            // Remove and trigger the queued message for clearing all actions when going to standby.
+            // This is necessary because the device may wake up before the message is triggered.
+            mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT);
+            handleDisableDeviceTimeout();
+        }
         mPendingActionClearedCallback = null;
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index e5a8a17d..a571dc0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -3131,7 +3131,7 @@
                 Slog.v(TAG, "On standby-action cleared:" + device.mDeviceType);
                 devices.remove(device);
                 if (devices.isEmpty()) {
-                    onStandbyCompleted(standbyAction);
+                    onPendingActionsCleared(standbyAction);
                     // We will not clear local devices here, since some OEM/SOC will keep passing
                     // the received packets until the application processor enters to the sleep
                     // actually.
@@ -3193,10 +3193,17 @@
         mHdmiCecNetwork.clearLocalDevices();
     }
 
+    /**
+     * Normally called after all devices have cleared their pending actions, to execute the final
+     * phase of the standby flow.
+     *
+     * This can also be called during wakeup, when pending actions are cleared after failing to be
+     * cleared during standby. In this case, it does not execute the standby flow.
+     */
     @ServiceThreadOnly
-    private void onStandbyCompleted(int standbyAction) {
+    private void onPendingActionsCleared(int standbyAction) {
         assertRunOnServiceThread();
-        Slog.v(TAG, "onStandbyCompleted");
+        Slog.v(TAG, "onPendingActionsCleared");
 
         if (!mPowerStatusController.isPowerStatusTransientToStandby()) {
             return;
diff --git a/services/core/java/com/android/server/health/HealthHalCallbackHidl.java b/services/core/java/com/android/server/health/HealthHalCallbackHidl.java
new file mode 100644
index 0000000..7a66980
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthHalCallbackHidl.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.health;
+
+import static android.hardware.health.Translate.h2aTranslate;
+
+import android.annotation.NonNull;
+import android.hardware.health.V2_0.IHealth;
+import android.hardware.health.V2_0.Result;
+import android.hardware.health.V2_1.BatteryCapacityLevel;
+import android.hardware.health.V2_1.Constants;
+import android.hardware.health.V2_1.IHealthInfoCallback;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.Slog;
+
+/**
+ * On service registration, {@link HealthServiceWrapperHidl.Callback#onRegistration} is called,
+ * which registers {@code this}, a {@link IHealthInfoCallback}, to the health service.
+ *
+ * <p>When the health service has updates to health info, {@link HealthInfoCallback#update} is
+ * called.
+ *
+ * @hide
+ */
+class HealthHalCallbackHidl extends IHealthInfoCallback.Stub
+        implements HealthServiceWrapperHidl.Callback {
+
+    private static final String TAG = HealthHalCallbackHidl.class.getSimpleName();
+
+    private static void traceBegin(String name) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
+    }
+
+    private static void traceEnd() {
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    private HealthInfoCallback mCallback;
+
+    HealthHalCallbackHidl(@NonNull HealthInfoCallback callback) {
+        mCallback = callback;
+    }
+
+    @Override
+    public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
+        android.hardware.health.V2_1.HealthInfo propsLatest =
+                new android.hardware.health.V2_1.HealthInfo();
+        propsLatest.legacy = props;
+
+        propsLatest.batteryCapacityLevel = BatteryCapacityLevel.UNSUPPORTED;
+        propsLatest.batteryChargeTimeToFullNowSeconds =
+                Constants.BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;
+
+        mCallback.update(h2aTranslate(propsLatest));
+    }
+
+    @Override
+    public void healthInfoChanged_2_1(android.hardware.health.V2_1.HealthInfo props) {
+        mCallback.update(h2aTranslate(props));
+    }
+
+    // on new service registered
+    @Override
+    public void onRegistration(IHealth oldService, IHealth newService, String instance) {
+        if (newService == null) return;
+
+        traceBegin("HealthUnregisterCallback");
+        try {
+            if (oldService != null) {
+                int r = oldService.unregisterCallback(this);
+                if (r != Result.SUCCESS) {
+                    Slog.w(
+                            TAG,
+                            "health: cannot unregister previous callback: " + Result.toString(r));
+                }
+            }
+        } catch (RemoteException ex) {
+            Slog.w(
+                    TAG,
+                    "health: cannot unregister previous callback (transaction error): "
+                            + ex.getMessage());
+        } finally {
+            traceEnd();
+        }
+
+        traceBegin("HealthRegisterCallback");
+        try {
+            int r = newService.registerCallback(this);
+            if (r != Result.SUCCESS) {
+                Slog.w(TAG, "health: cannot register callback: " + Result.toString(r));
+                return;
+            }
+            // registerCallback does NOT guarantee that update is called
+            // immediately, so request a manual update here.
+            newService.update();
+        } catch (RemoteException ex) {
+            Slog.e(TAG, "health: cannot register callback (transaction error): " + ex.getMessage());
+        } finally {
+            traceEnd();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/health/HealthInfoCallback.java b/services/core/java/com/android/server/health/HealthInfoCallback.java
new file mode 100644
index 0000000..c2a77fc
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthInfoCallback.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.health;
+
+/**
+ * A wrapper over HIDL / AIDL IHealthInfoCallback.
+ *
+ * @hide
+ */
+public interface HealthInfoCallback {
+    /**
+     * Signals to the client that health info is changed.
+     *
+     * @param props the new health info.
+     */
+    void update(android.hardware.health.HealthInfo props);
+}
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapper.java b/services/core/java/com/android/server/health/HealthServiceWrapper.java
new file mode 100644
index 0000000..9b97554
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthServiceWrapper.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.health;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.BatteryProperty;
+import android.os.HandlerThread;
+import android.os.IBatteryPropertiesRegistrar;
+import android.os.RemoteException;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.NoSuchElementException;
+
+/**
+ * HealthServiceWrapper wraps the internal IHealth service and refreshes the service when necessary.
+ * This is essentially a wrapper over IHealth that is useful for BatteryService.
+ *
+ * <p>The implementation may be backed by a HIDL or AIDL HAL.
+ *
+ * <p>On new registration of IHealth service, the internal service is refreshed. On death of an
+ * existing IHealth service, the internal service is NOT cleared to avoid race condition between
+ * death notification and new service notification. Hence, a caller must check for transaction
+ * errors when calling into the service.
+ *
+ * @hide Should only be used internally.
+ */
+public abstract class HealthServiceWrapper {
+    /** @return the handler thread. Exposed for testing. */
+    @VisibleForTesting
+    abstract HandlerThread getHandlerThread();
+
+    /**
+     * Calls into get*() functions in the health HAL. This reads into the kernel interfaces
+     * directly.
+     *
+     * @see IBatteryPropertiesRegistrar#getProperty
+     */
+    public abstract int getProperty(int id, BatteryProperty prop) throws RemoteException;
+
+    /**
+     * Calls update() in the health HAL.
+     *
+     * @see IBatteryPropertiesRegistrar#scheduleUpdate
+     */
+    public abstract void scheduleUpdate() throws RemoteException;
+
+    /**
+     * Calls into getHealthInfo() in the health HAL. This returns a cached value in the health HAL
+     * implementation.
+     *
+     * @return health info. {@code null} if no health HAL service. {@code null} if any
+     *     service-specific error when calling {@code getHealthInfo}, e.g. it is unsupported.
+     * @throws RemoteException for any transaction-level errors
+     */
+    public abstract android.hardware.health.HealthInfo getHealthInfo() throws RemoteException;
+
+    /**
+     * Create a new HealthServiceWrapper instance.
+     *
+     * @param healthInfoCallback the callback to call when health info changes
+     * @return the new HealthServiceWrapper instance, which may be backed by HIDL or AIDL service.
+     * @throws RemoteException transaction errors
+     * @throws NoSuchElementException no HIDL or AIDL service is available
+     */
+    public static HealthServiceWrapper create(@Nullable HealthInfoCallback healthInfoCallback)
+            throws RemoteException, NoSuchElementException {
+        return create(
+                healthInfoCallback == null ? null : new HealthHalCallbackHidl(healthInfoCallback),
+                new HealthServiceWrapperHidl.IServiceManagerSupplier() {},
+                new HealthServiceWrapperHidl.IHealthSupplier() {});
+    }
+
+    /**
+     * Create a new HealthServiceWrapper instance for testing.
+     *
+     * @param hidlRegCallback callback for HIDL service registration, or {@code null} if the client
+     *     does not care about HIDL service registration notifications
+     * @param hidlServiceManagerSupplier supplier of HIDL service manager
+     * @param hidlHealthSupplier supplier of HIDL health HAL
+     * @return the new HealthServiceWrapper instance, which may be backed by HIDL or AIDL service.
+     */
+    @VisibleForTesting
+    static @NonNull HealthServiceWrapper create(
+            @Nullable HealthServiceWrapperHidl.Callback hidlRegCallback,
+            @NonNull HealthServiceWrapperHidl.IServiceManagerSupplier hidlServiceManagerSupplier,
+            @NonNull HealthServiceWrapperHidl.IHealthSupplier hidlHealthSupplier)
+            throws RemoteException, NoSuchElementException {
+        return new HealthServiceWrapperHidl(
+                hidlRegCallback, hidlServiceManagerSupplier, hidlHealthSupplier);
+    }
+}
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapperHidl.java b/services/core/java/com/android/server/health/HealthServiceWrapperHidl.java
new file mode 100644
index 0000000..0301174
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthServiceWrapperHidl.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.health;
+
+import static android.hardware.health.Translate.h2aTranslate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.health.HealthInfo;
+import android.hardware.health.V2_0.IHealth;
+import android.hardware.health.V2_0.Result;
+import android.hidl.manager.V1_0.IServiceManager;
+import android.hidl.manager.V1_0.IServiceNotification;
+import android.os.BatteryManager;
+import android.os.BatteryProperty;
+import android.os.HandlerThread;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.MutableInt;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Implement {@link HealthServiceWrapper} backed by the HIDL HAL.
+ *
+ * @hide
+ */
+final class HealthServiceWrapperHidl extends HealthServiceWrapper {
+    private static final String TAG = "HealthServiceWrapperHidl";
+    public static final String INSTANCE_VENDOR = "default";
+
+    private final IServiceNotification mNotification = new Notification();
+    private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceHwbinder");
+    // These variables are fixed after init.
+    private Callback mCallback;
+    private IHealthSupplier mHealthSupplier;
+    private String mInstanceName;
+
+    // Last IHealth service received.
+    private final AtomicReference<IHealth> mLastService = new AtomicReference<>();
+
+    private static void traceBegin(String name) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
+    }
+
+    private static void traceEnd() {
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    @Override
+    public int getProperty(int id, final BatteryProperty prop) throws RemoteException {
+        traceBegin("HealthGetProperty");
+        try {
+            IHealth service = mLastService.get();
+            if (service == null) throw new RemoteException("no health service");
+            final MutableInt outResult = new MutableInt(Result.NOT_SUPPORTED);
+            switch (id) {
+                case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
+                    service.getChargeCounter(
+                            (int result, int value) -> {
+                                outResult.value = result;
+                                if (result == Result.SUCCESS) prop.setLong(value);
+                            });
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CURRENT_NOW:
+                    service.getCurrentNow(
+                            (int result, int value) -> {
+                                outResult.value = result;
+                                if (result == Result.SUCCESS) prop.setLong(value);
+                            });
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE:
+                    service.getCurrentAverage(
+                            (int result, int value) -> {
+                                outResult.value = result;
+                                if (result == Result.SUCCESS) prop.setLong(value);
+                            });
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CAPACITY:
+                    service.getCapacity(
+                            (int result, int value) -> {
+                                outResult.value = result;
+                                if (result == Result.SUCCESS) prop.setLong(value);
+                            });
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_STATUS:
+                    service.getChargeStatus(
+                            (int result, int value) -> {
+                                outResult.value = result;
+                                if (result == Result.SUCCESS) prop.setLong(value);
+                            });
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
+                    service.getEnergyCounter(
+                            (int result, long value) -> {
+                                outResult.value = result;
+                                if (result == Result.SUCCESS) prop.setLong(value);
+                            });
+                    break;
+            }
+            return outResult.value;
+        } finally {
+            traceEnd();
+        }
+    }
+
+    @Override
+    public void scheduleUpdate() throws RemoteException {
+        getHandlerThread()
+                .getThreadHandler()
+                .post(
+                        () -> {
+                            traceBegin("HealthScheduleUpdate");
+                            try {
+                                IHealth service = mLastService.get();
+                                if (service == null) {
+                                    Slog.e(TAG, "no health service");
+                                    return;
+                                }
+                                service.update();
+                            } catch (RemoteException ex) {
+                                Slog.e(TAG, "Cannot call update on health HAL", ex);
+                            } finally {
+                                traceEnd();
+                            }
+                        });
+    }
+
+    private static class Mutable<T> {
+        public T value;
+    }
+
+    @Override
+    public HealthInfo getHealthInfo() throws RemoteException {
+        IHealth service = mLastService.get();
+        if (service == null) return null;
+        final Mutable<HealthInfo> ret = new Mutable<>();
+        service.getHealthInfo(
+                (result, value) -> {
+                    if (result == Result.SUCCESS) {
+                        ret.value = h2aTranslate(value.legacy);
+                    }
+                });
+        return ret.value;
+    }
+
+    /**
+     * Start monitoring registration of new IHealth services. Only instance {@link #INSTANCE_VENDOR}
+     * and in device / framework manifest are used. This function should only be called once.
+     *
+     * <p>mCallback.onRegistration() is called synchronously (aka in init thread) before this method
+     * returns if callback is not null.
+     *
+     * @throws RemoteException transaction error when talking to IServiceManager
+     * @throws NoSuchElementException if one of the following cases: - No service manager; - {@link
+     *     #INSTANCE_VENDOR} is not in manifests (i.e. not available on this device), or none of
+     *     these instances are available to current process.
+     * @throws NullPointerException when supplier is null
+     */
+    @VisibleForTesting
+    HealthServiceWrapperHidl(
+            @Nullable Callback callback,
+            @NonNull IServiceManagerSupplier managerSupplier,
+            @NonNull IHealthSupplier healthSupplier)
+            throws RemoteException, NoSuchElementException, NullPointerException {
+        if (managerSupplier == null || healthSupplier == null) {
+            throw new NullPointerException();
+        }
+        mHealthSupplier = healthSupplier;
+
+        // Initialize mLastService and call callback for the first time (in init thread)
+        IHealth newService = null;
+        traceBegin("HealthInitGetService_" + INSTANCE_VENDOR);
+        try {
+            newService = healthSupplier.get(INSTANCE_VENDOR);
+        } catch (NoSuchElementException ex) {
+            /* ignored, handled below */
+        } finally {
+            traceEnd();
+        }
+        if (newService != null) {
+            mInstanceName = INSTANCE_VENDOR;
+            mLastService.set(newService);
+        }
+
+        if (mInstanceName == null || newService == null) {
+            throw new NoSuchElementException(
+                    String.format(
+                            "IHealth service instance %s isn't available. Perhaps no permission?",
+                            INSTANCE_VENDOR));
+        }
+
+        if (callback != null) {
+            mCallback = callback;
+            mCallback.onRegistration(null, newService, mInstanceName);
+        }
+
+        // Register for future service registrations
+        traceBegin("HealthInitRegisterNotification");
+        mHandlerThread.start();
+        try {
+            managerSupplier
+                    .get()
+                    .registerForNotifications(IHealth.kInterfaceName, mInstanceName, mNotification);
+        } finally {
+            traceEnd();
+        }
+        Slog.i(TAG, "health: HealthServiceWrapper listening to instance " + mInstanceName);
+    }
+
+    @VisibleForTesting
+    public HandlerThread getHandlerThread() {
+        return mHandlerThread;
+    }
+
+    /** Service registration callback. */
+    interface Callback {
+        /**
+         * This function is invoked asynchronously when a new and related IServiceNotification is
+         * received.
+         *
+         * @param service the recently retrieved service from IServiceManager. Can be a dead service
+         *     before service notification of a new service is delivered. Implementation must handle
+         *     cases for {@link RemoteException}s when calling into service.
+         * @param instance instance name.
+         */
+        void onRegistration(IHealth oldService, IHealth newService, String instance);
+    }
+
+    /**
+     * Supplier of services. Must not return null; throw {@link NoSuchElementException} if a service
+     * is not available.
+     */
+    interface IServiceManagerSupplier {
+        default IServiceManager get() throws NoSuchElementException, RemoteException {
+            return IServiceManager.getService();
+        }
+    }
+
+    /**
+     * Supplier of services. Must not return null; throw {@link NoSuchElementException} if a service
+     * is not available.
+     */
+    interface IHealthSupplier {
+        default IHealth get(String name) throws NoSuchElementException, RemoteException {
+            return IHealth.getService(name, true /* retry */);
+        }
+    }
+
+    private class Notification extends IServiceNotification.Stub {
+        @Override
+        public final void onRegistration(
+                String interfaceName, String instanceName, boolean preexisting) {
+            if (!IHealth.kInterfaceName.equals(interfaceName)) return;
+            if (!mInstanceName.equals(instanceName)) return;
+
+            // This runnable only runs on mHandlerThread and ordering is ensured, hence
+            // no locking is needed inside the runnable.
+            mHandlerThread
+                    .getThreadHandler()
+                    .post(
+                            new Runnable() {
+                                @Override
+                                public void run() {
+                                    try {
+                                        IHealth newService = mHealthSupplier.get(mInstanceName);
+                                        IHealth oldService = mLastService.getAndSet(newService);
+
+                                        // preexisting may be inaccurate (race). Check for equality
+                                        // here.
+                                        if (Objects.equals(newService, oldService)) return;
+
+                                        Slog.i(
+                                                TAG,
+                                                "health: new instance registered " + mInstanceName);
+                                        // #init() may be called with null callback. Skip null
+                                        // callbacks.
+                                        if (mCallback == null) return;
+                                        mCallback.onRegistration(
+                                                oldService, newService, mInstanceName);
+                                    } catch (NoSuchElementException | RemoteException ex) {
+                                        Slog.e(
+                                                TAG,
+                                                "health: Cannot get instance '"
+                                                        + mInstanceName
+                                                        + "': "
+                                                        + ex.getMessage()
+                                                        + ". Perhaps no permission?");
+                                    }
+                                }
+                            });
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/health/OWNERS b/services/core/java/com/android/server/health/OWNERS
new file mode 100644
index 0000000..81522fc
--- /dev/null
+++ b/services/core/java/com/android/server/health/OWNERS
@@ -0,0 +1 @@
+file:platform/hardware/interfaces:/health/aidl/OWNERS
diff --git a/services/core/java/com/android/server/health/Utils.java b/services/core/java/com/android/server/health/Utils.java
new file mode 100644
index 0000000..a8c978c
--- /dev/null
+++ b/services/core/java/com/android/server/health/Utils.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.health;
+
+/**
+ * Utils for {@link om.android.server.BatteryService} to deal with health info structs.
+ *
+ * @hide
+ */
+public class Utils {
+    private Utils() {}
+
+    /**
+     * Copy health info struct.
+     *
+     * @param dst destination
+     * @param src source
+     */
+    public static void copy(
+            android.hardware.health.V1_0.HealthInfo dst,
+            android.hardware.health.V1_0.HealthInfo src) {
+        dst.chargerAcOnline = src.chargerAcOnline;
+        dst.chargerUsbOnline = src.chargerUsbOnline;
+        dst.chargerWirelessOnline = src.chargerWirelessOnline;
+        dst.maxChargingCurrent = src.maxChargingCurrent;
+        dst.maxChargingVoltage = src.maxChargingVoltage;
+        dst.batteryStatus = src.batteryStatus;
+        dst.batteryHealth = src.batteryHealth;
+        dst.batteryPresent = src.batteryPresent;
+        dst.batteryLevel = src.batteryLevel;
+        dst.batteryVoltage = src.batteryVoltage;
+        dst.batteryTemperature = src.batteryTemperature;
+        dst.batteryCurrent = src.batteryCurrent;
+        dst.batteryCycleCount = src.batteryCycleCount;
+        dst.batteryFullCharge = src.batteryFullCharge;
+        dst.batteryChargeCounter = src.batteryChargeCounter;
+        dst.batteryTechnology = src.batteryTechnology;
+    }
+
+    /**
+     * Copy battery fields of {@link android.hardware.health.HealthInfo} V1. This excludes
+     * non-battery fields like {@link android.hardware.health.HealthInfo#diskStats diskStats} and
+     * {@link android.hardware.health.HealthInfo#storageInfos storageInfos}
+     *
+     * @param dst destination
+     * @param src source
+     */
+    public static void copyV1Battery(
+            android.hardware.health.HealthInfo dst, android.hardware.health.HealthInfo src) {
+        dst.chargerAcOnline = src.chargerAcOnline;
+        dst.chargerUsbOnline = src.chargerUsbOnline;
+        dst.chargerWirelessOnline = src.chargerWirelessOnline;
+        dst.maxChargingCurrentMicroamps = src.maxChargingCurrentMicroamps;
+        dst.maxChargingVoltageMicrovolts = src.maxChargingVoltageMicrovolts;
+        dst.batteryStatus = src.batteryStatus;
+        dst.batteryHealth = src.batteryHealth;
+        dst.batteryPresent = src.batteryPresent;
+        dst.batteryLevel = src.batteryLevel;
+        dst.batteryVoltageMillivolts = src.batteryVoltageMillivolts;
+        dst.batteryTemperatureTenthsCelsius = src.batteryTemperatureTenthsCelsius;
+        dst.batteryCurrentMicroamps = src.batteryCurrentMicroamps;
+        dst.batteryCycleCount = src.batteryCycleCount;
+        dst.batteryFullChargeUah = src.batteryFullChargeUah;
+        dst.batteryChargeCounterUah = src.batteryChargeCounterUah;
+        dst.batteryTechnology = src.batteryTechnology;
+        dst.batteryCurrentAverageMicroamps = src.batteryCurrentAverageMicroamps;
+        dst.batteryCapacityLevel = src.batteryCapacityLevel;
+        dst.batteryChargeTimeToFullNowSeconds = src.batteryChargeTimeToFullNowSeconds;
+        dst.batteryFullChargeDesignCapacityUah = src.batteryFullChargeDesignCapacityUah;
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index dc95533..3e52f5e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2582,14 +2582,12 @@
         }
 
         if (mCurToken != null) {
-            try {
-                if (DEBUG) {
-                    Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
-                            + mCurTokenDisplayId);
-                }
-                mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
-            } catch (RemoteException e) {
+            if (DEBUG) {
+                Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
+                        + mCurTokenDisplayId);
             }
+            mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */,
+                    false /* animateExit */, mCurTokenDisplayId);
             // Set IME window status as invisible when unbind current method.
             mImeWindowVis = 0;
             mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS
index c09ade9..00cd700 100644
--- a/services/core/java/com/android/server/inputmethod/OWNERS
+++ b/services/core/java/com/android/server/inputmethod/OWNERS
@@ -5,3 +5,4 @@
 tarandeep@google.com
 lumark@google.com
 roosa@google.com
+wilsonwu@google.com
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index 28ae6a4..a15fc3e 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -1,11 +1,7 @@
 set noparent
 
-codewiz@google.com
-jchalard@google.com
+include platform/packages/modules/Connectivity:/OWNERS
+
 jsharkey@android.com
-junyulai@google.com
-lorenzo@google.com
-reminv@google.com
-satk@google.com
 sudheersai@google.com
 yamasani@google.com
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 3019439..5643873 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -215,7 +215,7 @@
     private static final DefaultCrossProfileIntentFilter RECOGNIZE_SPEECH =
             new DefaultCrossProfileIntentFilter.Builder(
                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
-                    /* flags= */0,
+                    /* flags= */ ONLY_IF_NO_MATCH_FOUND,
                     /* letsPersonalDataIntoProfile= */ false)
                     .addAction(ACTION_RECOGNIZE_SPEECH)
                     .addCategory(Intent.CATEGORY_DEFAULT)
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 3233819..1bdc9f3 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -3,27 +3,25 @@
 jsharkey@android.com
 jsharkey@google.com
 narayan@google.com
-patb@google.com
 svetoslavganov@android.com
 svetoslavganov@google.com
-toddke@android.com
-toddke@google.com
+include /PACKAGE_MANAGER_OWNERS
 
 # apex support
 per-file ApexManager.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
 per-file StagingManager.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
 
 # dex
-per-file AbstractStatsBase.java = calin@google.com, ngeoffray@google.com
-per-file BackgroundDexOptService.java = calin@google.com, ngeoffray@google.com
-per-file CompilerStats.java = calin@google.com, ngeoffray@google.com
-per-file DynamicCodeLoggingService.java = alanstokes@google.com, calin@google.com, ngeoffray@google.com
-per-file InstructionSets.java = calin@google.com, ngeoffray@google.com
-per-file OtaDexoptService.java = calin@google.com, ngeoffray@google.com
-per-file OtaDexoptShellCommand.java = calin@google.com, ngeoffray@google.com
-per-file PackageDexOptimizer.java = calin@google.com, ngeoffray@google.com
-per-file PackageManagerServiceCompilerMapping.java = calin@google.com, ngeoffray@google.com
-per-file PackageUsage.java = calin@google.com, ngeoffray@google.com
+per-file AbstractStatsBase.java = file:dex/OWNERS
+per-file BackgroundDexOptService.java = file:dex/OWNERS
+per-file CompilerStats.java = file:dex/OWNERS
+per-file DynamicCodeLoggingService.java = file:dex/OWNERS
+per-file InstructionSets.java = file:dex/OWNERS
+per-file OtaDexoptService.java = file:dex/OWNERS
+per-file OtaDexoptShellCommand.java = file:dex/OWNERS
+per-file PackageDexOptimizer.java = file:dex/OWNERS
+per-file PackageManagerServiceCompilerMapping.java = file:dex/OWNERS
+per-file PackageUsage.java = file:dex/OWNERS
 
 # multi user / cross profile
 per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f6acad0..1a0a885 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7337,9 +7337,16 @@
 
             // Parse overlay configuration files to set default enable state, mutability, and
             // priority of system overlays.
+            final ArrayMap<String, File> apkInApexPreInstalledPaths = new ArrayMap<>();
+            for (ApexManager.ActiveApexInfo apexInfo : mApexManager.getActiveApexInfos()) {
+                for (String packageName : mApexManager.getApksInApex(apexInfo.apexModuleName)) {
+                    apkInApexPreInstalledPaths.put(packageName, apexInfo.preInstalledApexPath);
+                }
+            }
             mOverlayConfig = OverlayConfig.initializeSystemInstance(
                     consumer -> mPmInternal.forEachPackage(
-                            pkg -> consumer.accept(pkg, pkg.isSystem())));
+                            pkg -> consumer.accept(pkg, pkg.isSystem(),
+                              apkInApexPreInstalledPaths.get(pkg.getPackageName()))));
 
             // Prune any system packages that no longer exist.
             final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
@@ -21911,7 +21918,7 @@
         for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
             ScanPartition sp = SYSTEM_PARTITIONS.get(i);
             if (apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
-                    sp.getFolder().getAbsolutePath())) {
+                    sp.getFolder().getAbsolutePath() + File.separator)) {
                 return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX);
             }
         }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index c2c35b7..08a7215 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -1255,6 +1255,9 @@
                     info.diskImagePath = ai.modulePath;
                     info.versionCode = ai.versionCode;
                     info.versionName = ai.versionName;
+                    info.hasBootClassPathJars = ai.hasBootClassPathJars;
+                    info.hasDex2OatBootClassPathJars = ai.hasDex2OatBootClassPathJars;
+                    info.hasSystemServerClassPathJars = ai.hasSystemServerClassPathJars;
                     return info;
                 }
             }
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index dab980a..7bea018 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -213,6 +213,7 @@
         NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_CONNECT);
         NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN);
         NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.UWB_RANGING);
+        NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.NEARBY_WIFI_DEVICES);
     }
 
     private static final int MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS = 1;
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index 8c1a90c..fc0ee23 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -1,7 +1,3 @@
 include platform/frameworks/base:/core/java/android/permission/OWNERS
 
-per-file DefaultPermissionGrantPolicy.java = hackbod@android.com
-per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com
-per-file DefaultPermissionGrantPolicy.java = toddke@google.com
-per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
-per-file DefaultPermissionGrantPolicy.java = patb@google.com
+per-file DefaultPermissionGrantPolicy.java = file:platform/frameworks/base:/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index cda4806..94e551a 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -480,9 +480,10 @@
             r.append("DUP:");
             r.append(permissionInfo.name);
         }
-        if (permission.isRuntime() && (ownerChanged || wasNonRuntime)) {
-            // If this is a runtime permission and the owner has changed, or this wasn't a runtime
-            // permission, then permission state should be cleaned up
+        if ((permission.isInternal() && ownerChanged)
+                || (permission.isRuntime() && (ownerChanged || wasNonRuntime))) {
+            // If this is an internal/runtime permission and the owner has changed, or this wasn't a
+            // runtime permission, then permission state should be cleaned up.
             permission.mDefinitionChanged = true;
         }
         if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
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 1133faa..7b12709 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1643,7 +1643,8 @@
             isRolePermission = permission.isRole();
         }
         final boolean mayRevokeRolePermission = isRolePermission
-                && mayManageRolePermission(callingUid);
+                // Allow ourselves to revoke role permissions due to definition changes.
+                && (callingUid == Process.myUid() || mayManageRolePermission(callingUid));
 
         final boolean isRuntimePermission;
         synchronized (mLock) {
@@ -2321,11 +2322,13 @@
 
         for (int permNum = 0; permNum < numPermissions; permNum++) {
             final String permName = permissionsToRevoke.get(permNum);
+            final boolean isInternalPermission;
             synchronized (mLock) {
                 final Permission bp = mRegistry.getPermission(permName);
-                if (bp == null || !bp.isRuntime()) {
+                if (bp == null || !(bp.isInternal() || bp.isRuntime())) {
                     continue;
                 }
+                isInternalPermission = bp.isInternal();
             }
             mPackageManagerInt.forEachPackage(pkg -> {
                 final String packageName = pkg.getPackageName();
@@ -2345,12 +2348,18 @@
                     if (permissionState == PackageManager.PERMISSION_GRANTED
                             && (flags & flagMask) == 0) {
                         final int uid = UserHandle.getUid(userId, appId);
-                        EventLog.writeEvent(0x534e4554, "154505240", uid,
-                                "Revoking permission " + permName + " from package "
-                                        + packageName + " due to definition change");
-                        EventLog.writeEvent(0x534e4554, "168319670", uid,
-                                "Revoking permission " + permName + " from package "
-                                        + packageName + " due to definition change");
+                        if (isInternalPermission) {
+                            EventLog.writeEvent(0x534e4554, "195338390", uid,
+                                    "Revoking permission " + permName + " from package "
+                                            + packageName + " due to definition change");
+                        } else {
+                            EventLog.writeEvent(0x534e4554, "154505240", uid,
+                                    "Revoking permission " + permName + " from package "
+                                            + packageName + " due to definition change");
+                            EventLog.writeEvent(0x534e4554, "168319670", uid,
+                                    "Revoking permission " + permName + " from package "
+                                            + packageName + " due to definition change");
+                        }
                         Slog.e(TAG, "Revoking permission " + permName + " from package "
                                 + packageName + " due to definition change");
                         try {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e408822..4a97720 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2666,6 +2666,24 @@
                 Slog.wtf(TAG, "KEYCODE_VOICE_ASSIST should be handled in"
                         + " interceptKeyBeforeQueueing");
                 return key_consumed;
+            case KeyEvent.KEYCODE_VIDEO_APP_1:
+            case KeyEvent.KEYCODE_VIDEO_APP_2:
+            case KeyEvent.KEYCODE_VIDEO_APP_3:
+            case KeyEvent.KEYCODE_VIDEO_APP_4:
+            case KeyEvent.KEYCODE_VIDEO_APP_5:
+            case KeyEvent.KEYCODE_VIDEO_APP_6:
+            case KeyEvent.KEYCODE_VIDEO_APP_7:
+            case KeyEvent.KEYCODE_VIDEO_APP_8:
+            case KeyEvent.KEYCODE_FEATURED_APP_1:
+            case KeyEvent.KEYCODE_FEATURED_APP_2:
+            case KeyEvent.KEYCODE_FEATURED_APP_3:
+            case KeyEvent.KEYCODE_FEATURED_APP_4:
+            case KeyEvent.KEYCODE_DEMO_APP_1:
+            case KeyEvent.KEYCODE_DEMO_APP_2:
+            case KeyEvent.KEYCODE_DEMO_APP_3:
+            case KeyEvent.KEYCODE_DEMO_APP_4:
+                Slog.wtf(TAG, "KEYCODE_APP_X should be handled in interceptKeyBeforeQueueing");
+                return key_consumed;
             case KeyEvent.KEYCODE_SYSRQ:
                 if (down && repeatCount == 0) {
                     mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
@@ -3773,6 +3791,26 @@
                 }
                 break;
             }
+            case KeyEvent.KEYCODE_VIDEO_APP_1:
+            case KeyEvent.KEYCODE_VIDEO_APP_2:
+            case KeyEvent.KEYCODE_VIDEO_APP_3:
+            case KeyEvent.KEYCODE_VIDEO_APP_4:
+            case KeyEvent.KEYCODE_VIDEO_APP_5:
+            case KeyEvent.KEYCODE_VIDEO_APP_6:
+            case KeyEvent.KEYCODE_VIDEO_APP_7:
+            case KeyEvent.KEYCODE_VIDEO_APP_8:
+            case KeyEvent.KEYCODE_FEATURED_APP_1:
+            case KeyEvent.KEYCODE_FEATURED_APP_2:
+            case KeyEvent.KEYCODE_FEATURED_APP_3:
+            case KeyEvent.KEYCODE_FEATURED_APP_4:
+            case KeyEvent.KEYCODE_DEMO_APP_1:
+            case KeyEvent.KEYCODE_DEMO_APP_2:
+            case KeyEvent.KEYCODE_DEMO_APP_3:
+            case KeyEvent.KEYCODE_DEMO_APP_4: {
+                // Just drop if keys are not intercepted for direct key.
+                result &= ~ACTION_PASS_TO_USER;
+                break;
+            }
         }
 
         // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users.
diff --git a/services/core/java/com/android/server/security/OWNERS b/services/core/java/com/android/server/security/OWNERS
index e6f5826..5c2d5ba 100644
--- a/services/core/java/com/android/server/security/OWNERS
+++ b/services/core/java/com/android/server/security/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36824
 
+per-file *AttestationVerification* = file:/core/java/android/security/attestationverification/OWNERS
 per-file FileIntegrityService.java = victorhsieh@google.com
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java
index 6366280..7ffff93 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java
@@ -429,15 +429,7 @@
     private static @NonNull
     HidlMemory parcelFileDescriptorToHidlMemory(@Nullable ParcelFileDescriptor data, int dataSize) {
         if (dataSize > 0) {
-            // Extract a dup of the underlying FileDescriptor out of data.
-            FileDescriptor fd = new FileDescriptor();
-            try {
-                ParcelFileDescriptor dup = data.dup();
-                fd.setInt$(dup.detachFd());
-                return HidlMemoryUtil.fileDescriptorToHidlMemory(fd, dataSize);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
+            return HidlMemoryUtil.fileDescriptorToHidlMemory(data.getFileDescriptor(), dataSize);
         } else {
             return HidlMemoryUtil.fileDescriptorToHidlMemory(null, 0);
         }
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 61770ea..1ef2025 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -29,6 +29,7 @@
 import static android.net.NetworkIdentity.OEM_PRIVATE;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkStats.ROAMING_ALL;
 import static android.net.NetworkTemplate.MATCH_ETHERNET;
 import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
@@ -91,7 +92,6 @@
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.health.V2_0.IHealth;
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsService;
 import android.net.INetworkStatsSession;
@@ -189,13 +189,13 @@
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.role.RoleManagerLocal;
-import com.android.server.BatteryService;
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalManagerRegistry;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
 import com.android.server.am.MemoryStatUtil.MemoryStat;
+import com.android.server.health.HealthServiceWrapper;
 import com.android.server.notification.NotificationManagerService;
 import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
 import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
@@ -225,6 +225,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.MissingResourceException;
+import java.util.NoSuchElementException;
 import java.util.Random;
 import java.util.Set;
 import java.util.UUID;
@@ -353,7 +354,7 @@
     private File mBaseDir;
 
     @GuardedBy("mHealthHalLock")
-    private BatteryService.HealthServiceWrapper mHealthService;
+    private HealthServiceWrapper mHealthService;
 
     @Nullable
     @GuardedBy("mCpuTimePerThreadFreqLock")
@@ -798,10 +799,9 @@
                 KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
 
         // Initialize HealthService
-        mHealthService = new BatteryService.HealthServiceWrapper();
         try {
-            mHealthService.init();
-        } catch (RemoteException e) {
+            mHealthService = HealthServiceWrapper.create(null);
+        } catch (RemoteException | NoSuchElementException e) {
             Slog.e(TAG, "failed to initialize healthHalWrapper");
         }
 
@@ -1340,7 +1340,7 @@
     @Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
         final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
                 ? NetworkTemplate.buildTemplateMobileWithRatType(
-                /*subscriptionId=*/null, NETWORK_TYPE_ALL)
+                /*subscriptionId=*/null, NETWORK_TYPE_ALL, METERED_YES)
                 : NetworkTemplate.buildTemplateWifiWildcard();
         return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
     }
@@ -1380,7 +1380,8 @@
         final List<NetworkStatsExt> ret = new ArrayList<>();
         for (final int ratType : getAllCollapsedRatTypes()) {
             final NetworkTemplate template =
-                    buildTemplateMobileWithRatType(subInfo.subscriberId, ratType);
+                    buildTemplateMobileWithRatType(subInfo.subscriberId, ratType,
+                    METERED_YES);
             final NetworkStats stats =
                     getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
             if (stats != null) {
@@ -1601,7 +1602,7 @@
 
     int pullBluetoothBytesTransferLocked(int atomTag, List<StatsEvent> pulledData) {
         BluetoothActivityEnergyInfo info = fetchBluetoothData();
-        if (info == null || info.getUidTraffic() == null) {
+        if (info == null) {
             return StatsManager.PULL_SKIP;
         }
         for (UidTraffic traffic : info.getUidTraffic()) {
@@ -2059,7 +2060,7 @@
         if (info == null) {
             return StatsManager.PULL_SKIP;
         }
-        pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, info.getTimeStamp(),
+        pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, info.getTimestampMillis(),
                 info.getBluetoothStackState(), info.getControllerTxTimeMillis(),
                 info.getControllerRxTimeMillis(), info.getControllerIdleTimeMillis(),
                 info.getControllerEnergyUsed()));
@@ -3973,38 +3974,40 @@
     }
 
     int pullHealthHalLocked(int atomTag, List<StatsEvent> pulledData) {
-        IHealth healthService = mHealthService.getLastService();
-        if (healthService == null) {
+        if (mHealthService == null) {
             return StatsManager.PULL_SKIP;
         }
+        android.hardware.health.HealthInfo healthInfo;
         try {
-            healthService.getHealthInfo((result, value) -> {
-                int pulledValue;
-                switch(atomTag) {
-                    case FrameworkStatsLog.BATTERY_LEVEL:
-                        pulledValue = value.legacy.batteryLevel;
-                        break;
-                    case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY:
-                        pulledValue = value.legacy.batteryChargeCounter;
-                        break;
-                    case FrameworkStatsLog.FULL_BATTERY_CAPACITY:
-                        pulledValue = value.legacy.batteryFullCharge;
-                        break;
-                    case FrameworkStatsLog.BATTERY_VOLTAGE:
-                        pulledValue = value.legacy.batteryVoltage;
-                        break;
-                    case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
-                        pulledValue = value.legacy.batteryCycleCount;
-                        break;
-                    default:
-                        throw new IllegalStateException("Invalid atomTag in healthHal puller: "
-                                + atomTag);
-                }
-                pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, pulledValue));
-            });
+            healthInfo = mHealthService.getHealthInfo();
         } catch (RemoteException | IllegalStateException e) {
             return StatsManager.PULL_SKIP;
         }
+        if (healthInfo == null) {
+            return StatsManager.PULL_SKIP;
+        }
+
+        int pulledValue;
+        switch (atomTag) {
+            case FrameworkStatsLog.BATTERY_LEVEL:
+                pulledValue = healthInfo.batteryLevel;
+                break;
+            case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY:
+                pulledValue = healthInfo.batteryChargeCounterUah;
+                break;
+            case FrameworkStatsLog.FULL_BATTERY_CAPACITY:
+                pulledValue = healthInfo.batteryFullChargeUah;
+                break;
+            case FrameworkStatsLog.BATTERY_VOLTAGE:
+                pulledValue = healthInfo.batteryVoltageMillivolts;
+                break;
+            case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
+                pulledValue = healthInfo.batteryCycleCount;
+                break;
+            default:
+                return StatsManager.PULL_SKIP;
+        }
+        pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, pulledValue));
         return StatsManager.PULL_SUCCESS;
     }
 
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 92e0845..f57a852 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -1075,17 +1075,22 @@
             }
             if (shouldRecreateAudioPatch) {
                 mCommittedVolume = volume;
-                if (mAudioPatch != null) {
-                    mAudioManager.releaseAudioPatch(mAudioPatch);
-                }
-                mAudioManager.createAudioPatch(
+                // only recreate if  something was updated or audioPath is null
+                if (mAudioPatch == null || sinkUpdated ||sourceUpdated ) {
+                    if (mAudioPatch != null) {
+                        mAudioManager.releaseAudioPatch(mAudioPatch);
+                        audioPatchArray[0] = null;
+                    }
+                    mAudioManager.createAudioPatch(
                         audioPatchArray,
                         new AudioPortConfig[] { sourceConfig },
                         sinkConfigs.toArray(new AudioPortConfig[sinkConfigs.size()]));
-                mAudioPatch = audioPatchArray[0];
-                if (sourceGainConfig != null) {
-                    mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig);
+                    mAudioPatch = audioPatchArray[0];
                 }
+             }
+
+            if (sourceGainConfig != null) {
+                mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig);
             }
         }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 9760e45..b9ceec1 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -2315,10 +2315,9 @@
         public void requestChannelBrowsable(Uri channelUri, int userId)
                 throws RemoteException {
             final String callingPackageName = getCallingPackageName();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "requestChannelBrowsable");
             final long identity = Binder.clearCallingIdentity();
-            final int callingUid = Binder.getCallingUid();
-            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
-                userId, "requestChannelBrowsable");
             try {
                 Intent intent = new Intent(TvContract.ACTION_CHANNEL_BROWSABLE_REQUESTED);
                 List<ResolveInfo> list = getContext().getPackageManager()
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 7dec4e7..1c46ac8 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -98,6 +98,7 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -1663,8 +1664,6 @@
                             } /* validationStatusCallback */);
 
             agent.register();
-            agent.setUnderlyingNetworks(
-                    mUnderlying == null ? null : Collections.singletonList(mUnderlying.network));
             agent.markConnected();
 
             return agent;
@@ -2039,6 +2038,7 @@
                         "Unknown transport type or missing TransportInfo/NetworkSpecifier for"
                                 + " non-null underlying network");
             }
+            builder.setUnderlyingNetworks(List.of(underlying.network));
         } else {
             Slog.wtf(
                     TAG,
@@ -2049,7 +2049,8 @@
         return builder.build();
     }
 
-    private static LinkProperties buildConnectedLinkProperties(
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    LinkProperties buildConnectedLinkProperties(
             @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig,
             @NonNull IpSecTunnelInterface tunnelIface,
             @NonNull VcnChildSessionConfiguration childConfig,
@@ -2077,6 +2078,13 @@
 
             lp.setTcpBufferSizes(underlyingLp.getTcpBufferSizes());
             underlyingMtu = underlyingLp.getMtu();
+
+            // WiFi LinkProperties uses DHCP as the sole source of MTU information, and as a result
+            // often lists MTU as 0 (see b/184678973). Use the interface MTU as retrieved by
+            // NetworkInterface APIs.
+            if (underlyingMtu == 0 && underlyingLp.getInterfaceName() != null) {
+                underlyingMtu = mDeps.getUnderlyingIfaceMtu(underlyingLp.getInterfaceName());
+            }
         } else {
             Slog.wtf(
                     TAG,
@@ -2418,6 +2426,17 @@
         public long getElapsedRealTime() {
             return SystemClock.elapsedRealtime();
         }
+
+        /** Gets the MTU for the given underlying interface. */
+        public int getUnderlyingIfaceMtu(String ifaceName) {
+            try {
+                final NetworkInterface underlyingIface = NetworkInterface.getByName(ifaceName);
+                return underlyingIface == null ? 0 : underlyingIface.getMTU();
+            } catch (IOException e) {
+                Slog.d(TAG, "Could not get MTU of underlying network", e);
+                return 0;
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 308df2f..d1f2177 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -140,6 +140,7 @@
 import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
 import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
 import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.ActivityRecordProto.MIN_ASPECT_RATIO;
 import static com.android.server.wm.ActivityRecordProto.NAME;
 import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
 import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
@@ -656,6 +657,12 @@
     boolean mLastImeShown;
 
     /**
+     * When set to true, the IME insets will be frozen until the next app becomes IME input target.
+     * @see InsetsPolicy#adjustVisibilityForIme
+     */
+    boolean mImeInsetsFrozenUntilStartInput;
+
+    /**
      * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
      * to help AR know that the app is in the process of closing but hasn't yet started closing on
      * the WM side.
@@ -1343,13 +1350,7 @@
         }
         final Task rootTask = getRootTask();
 
-        // If we reparent, make sure to remove ourselves from the old animation registry.
-        if (mAnimatingActivityRegistry != null) {
-            mAnimatingActivityRegistry.notifyFinished(this);
-        }
-        mAnimatingActivityRegistry = rootTask != null
-                ? rootTask.getAnimatingActivityRegistry()
-                : null;
+        updateAnimatingActivityRegistry();
 
         if (task == mLastParentBeforePip) {
             // Activity's reparented back from pip, clear the links once established
@@ -1363,6 +1364,7 @@
         }
         if (newTask != null && isState(RESUMED)) {
             newTask.setResumedActivity(this, "onParentChanged");
+            mImeInsetsFrozenUntilStartInput = false;
         }
 
         if (rootTask != null && rootTask.topRunningActivity() == this) {
@@ -1373,6 +1375,20 @@
         }
     }
 
+    void updateAnimatingActivityRegistry() {
+        final Task rootTask = getRootTask();
+        final AnimatingActivityRegistry registry = rootTask != null
+                ? rootTask.getAnimatingActivityRegistry()
+                : null;
+
+        // If we reparent, make sure to remove ourselves from the old animation registry.
+        if (mAnimatingActivityRegistry != null && mAnimatingActivityRegistry != registry) {
+            mAnimatingActivityRegistry.notifyFinished(this);
+        }
+
+        mAnimatingActivityRegistry = registry;
+    }
+
     /**
      * Sets {@link #mLastParentBeforePip} to the current parent Task, it's caller's job to ensure
      * {@link #getTask()} is set before this is called.
@@ -4759,6 +4775,7 @@
                     && imeInputTarget.getWindow().mActivityRecord == this
                     && mDisplayContent.mInputMethodWindow != null
                     && mDisplayContent.mInputMethodWindow.isVisible();
+            mImeInsetsFrozenUntilStartInput = true;
         }
 
         final DisplayContent displayContent = getDisplayContent();
@@ -5877,6 +5894,14 @@
             // closing activity having to wait until idle timeout to be stopped or destroyed if the
             // next activity won't report idle (e.g. repeated view animation).
             mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded();
+
+            // If the activity is visible, but no windows are eligible to start input, unfreeze
+            // to avoid permanently frozen IME insets.
+            if (mImeInsetsFrozenUntilStartInput && getWindow(
+                    win -> WindowManager.LayoutParams.mayUseInputMethod(win.mAttrs.flags))
+                    == null) {
+                mImeInsetsFrozenUntilStartInput = false;
+            }
         }
     }
 
@@ -7792,6 +7817,13 @@
         }
     }
 
+    @Override
+    void onResize() {
+        // Reset freezing IME insets flag when the activity resized.
+        mImeInsetsFrozenUntilStartInput = false;
+        super.onResize();
+    }
+
     /** Returns true if the configuration is compatible with this activity. */
     boolean isConfigurationCompatible(Configuration config) {
         final int orientation = getRequestedOrientation();
@@ -8641,6 +8673,7 @@
         }
         proto.write(PIP_AUTO_ENTER_ENABLED, pictureInPictureArgs.isAutoEnterEnabled());
         proto.write(IN_SIZE_COMPAT_MODE, inSizeCompatMode());
+        proto.write(MIN_ASPECT_RATIO, info.getMinAspectRatio());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index dbc1116..9335846 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1165,10 +1165,10 @@
         }
     }
 
-    WindowToken removeWindowToken(IBinder binder) {
+    WindowToken removeWindowToken(IBinder binder, boolean animateExit) {
         final WindowToken token = mTokenMap.remove(binder);
         if (token != null && token.asActivityRecord() == null) {
-            token.setExiting();
+            token.setExiting(animateExit);
         }
         return token;
     }
@@ -1252,7 +1252,7 @@
     }
 
     void removeAppToken(IBinder binder) {
-        final WindowToken token = removeWindowToken(binder);
+        final WindowToken token = removeWindowToken(binder, true /* animateExit */);
         if (token == null) {
             Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
             return;
@@ -3971,6 +3971,9 @@
     void updateImeInputAndControlTarget(WindowState target) {
         if (mImeInputTarget != target) {
             ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
+            if (target != null && target.mActivityRecord != null) {
+                target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
+            }
             setImeInputTarget(target);
             updateImeControlTarget();
         }
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index f2f1926..a8e1c1c 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -211,7 +211,7 @@
     InsetsState getInsetsForWindow(WindowState target) {
         final InsetsState originalState = mStateController.getInsetsForWindow(target);
         final InsetsState state = adjustVisibilityForTransientTypes(originalState);
-        return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
+        return adjustVisibilityForIme(target, state, state == originalState);
     }
 
     /**
@@ -241,16 +241,37 @@
         return state;
     }
 
-    // Navigation bar insets is always visible to IME.
-    private static InsetsState adjustVisibilityForIme(InsetsState originalState,
+    private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
             boolean copyState) {
-        final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
-        if (originalNavSource != null && !originalNavSource.isVisible()) {
-            final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
-            final InsetsSource navSource = new InsetsSource(originalNavSource);
-            navSource.setVisible(true);
-            state.addSource(navSource);
-            return state;
+        if (w.mIsImWindow) {
+            // Navigation bar insets is always visible to IME.
+            final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
+            if (originalNavSource != null && !originalNavSource.isVisible()) {
+                final InsetsState state = copyState ? new InsetsState(originalState)
+                        : originalState;
+                final InsetsSource navSource = new InsetsSource(originalNavSource);
+                navSource.setVisible(true);
+                state.addSource(navSource);
+                return state;
+            }
+        } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
+            // 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 (shouldImeAttachedToApp && originalImeSource != null) {
+                final boolean imeVisibility =
+                        w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME);
+                final InsetsState state = copyState ? new InsetsState(originalState)
+                        : originalState;
+                final InsetsSource imeSource = new InsetsSource(originalImeSource);
+                imeSource.setVisible(imeVisibility);
+                state.addSource(imeSource);
+                return state;
+            }
         }
         return originalState;
     }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index fe1020c..a7216da 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -190,8 +190,7 @@
 
         if (keyguardChanged) {
             // Irrelevant to AOD.
-            dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */,
-                    false /* turningScreenOn */);
+            dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */);
             mKeyguardGoingAway = false;
             if (keyguardShowing) {
                 mDismissalRequested = false;
@@ -385,6 +384,8 @@
                 mService.continueWindowLayout();
             }
         }
+        dismissMultiWindowModeForTaskIfNeeded(topActivity != null
+                ? topActivity.getRootTask() : null);
     }
 
     /**
@@ -410,21 +411,6 @@
         }
     }
 
-    /**
-     * Called when somebody wants to turn screen on.
-     */
-    private void handleTurnScreenOn(int displayId) {
-        if (displayId != DEFAULT_DISPLAY) {
-            return;
-        }
-
-        mTaskSupervisor.wakeUp("handleTurnScreenOn");
-        if (mKeyguardShowing && canDismissKeyguard()) {
-            mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
-            mDismissalRequested = true;
-        }
-    }
-
     boolean isDisplayOccluded(int displayId) {
         return getDisplayState(displayId).mOccluded;
     }
@@ -438,11 +424,9 @@
     }
 
     private void dismissMultiWindowModeForTaskIfNeeded(
-            @Nullable Task currentTaskControllingOcclusion, boolean turningScreenOn) {
-        // If turningScreenOn is true, it means that the visibility state has changed from
-        // currentTaskControllingOcclusion and we should update windowing mode.
+            @Nullable Task currentTaskControllingOcclusion) {
         // TODO(b/113840485): Handle docked stack for individual display.
-        if (!turningScreenOn && (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY))) {
+        if (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY)) {
             return;
         }
 
@@ -581,26 +565,17 @@
                     && controller.mWindowManager.isKeyguardSecure(
                     controller.mService.getCurrentUserId());
 
-            boolean occludingChange = false;
-            boolean turningScreenOn = false;
             if (mTopTurnScreenOnActivity != lastTurnScreenOnActivity
                     && mTopTurnScreenOnActivity != null
                     && !mService.mWindowManager.mPowerManager.isInteractive()
-                    && (mRequestDismissKeyguard || occludedByActivity
-                        || controller.canDismissKeyguard())) {
-                turningScreenOn = true;
-                controller.handleTurnScreenOn(mDisplayId);
+                    && (mRequestDismissKeyguard || occludedByActivity)) {
+                controller.mTaskSupervisor.wakeUp("handleTurnScreenOn");
                 mTopTurnScreenOnActivity.setCurrentLaunchCanTurnScreenOn(false);
             }
 
             if (lastOccluded != mOccluded) {
-                occludingChange = true;
                 controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
             }
-
-            if (occludingChange || turningScreenOn) {
-                controller.dismissMultiWindowModeForTaskIfNeeded(task, turningScreenOn);
-            }
         }
 
         /**
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 516be55..9634855 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1464,6 +1464,9 @@
         adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
 
         mRootWindowContainer.updateUIDsPresentOnDisplay();
+
+        // Ensure all animations are finished at same time in split-screen mode.
+        forAllActivities(ActivityRecord::updateAnimatingActivityRegistry);
     }
 
     void cleanUpActivityReferences(ActivityRecord r) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index e743710..a518222 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -118,6 +118,11 @@
      */
     private final boolean mIsRunningOnWear;
 
+    /**
+     * Flag indicating if device configuration has disabled app snapshots.
+     */
+    private final boolean mConfigDisableTaskSnapshots;
+
     TaskSnapshotController(WindowManagerService service) {
         mService = service;
         mPersister = new TaskSnapshotPersister(mService, Environment::getDataSystemCeDirectory);
@@ -131,6 +136,8 @@
             PackageManager.FEATURE_WATCH);
         mHighResTaskSnapshotScale = mService.mContext.getResources().getFloat(
                 com.android.internal.R.dimen.config_highResTaskSnapshotScale);
+        mConfigDisableTaskSnapshots = mService.mContext.getResources().getBoolean(
+                            com.android.internal.R.bool.config_disableTaskSnapshots);
     }
 
     void systemReady() {
@@ -488,7 +495,8 @@
     }
 
     boolean shouldDisableSnapshots() {
-        return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT;
+        return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT
+            || mConfigDisableTaskSnapshots;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 194f48f..b54e8b7 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -66,8 +66,8 @@
     }
 
     @Override
-    void setExiting() {
-        super.setExiting();
+    void setExiting(boolean animateExit) {
+        super.setExiting(animateExit);
         mDisplayContent.mWallpaperController.removeWallpaperToken(this);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 47087cf..4fac05c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -445,8 +445,21 @@
      * @param removeWindows Whether to also remove the windows associated with the token.
      * @param displayId The display to remove the token from.
      */
+    public final void removeWindowToken(android.os.IBinder token, boolean removeWindows,
+            int displayId) {
+        removeWindowToken(token, removeWindows, true /* animateExit */, displayId);
+    }
+
+    /**
+     * Removes a window token.
+     *
+     * @param token The toke to remove.
+     * @param removeWindows Whether to also remove the windows associated with the token.
+     * @param animateExit Whether to play the windows exit animation after the token removal.
+     * @param displayId The display to remove the token from.
+     */
     public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows,
-            int displayId);
+            boolean animateExit, int displayId);
 
     /**
      * Registers a listener to be notified about app transition events.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1ec9187..3421b28 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -167,8 +167,10 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
-import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs;
 import android.hardware.configstore.V1_0.OptionalBool;
+import android.hardware.configstore.V1_1.DisplayOrientation;
+import android.hardware.configstore.V1_1.ISurfaceFlingerConfigs;
+import android.hardware.configstore.V1_1.OptionalDisplayOrientation;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputManager;
@@ -220,6 +222,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Choreographer;
 import android.view.Display;
+import android.view.DisplayAddress;
 import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IAppTransitionAnimationSpecsFuture;
@@ -465,6 +468,8 @@
      */
     static final boolean ENABLE_FIXED_ROTATION_TRANSFORM =
             SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true);
+    private @Surface.Rotation int mPrimaryDisplayOrientation = Surface.ROTATION_0;
+    private DisplayAddress mPrimaryDisplayPhysicalAddress;
 
     // Enums for animation scale update types.
     @Retention(RetentionPolicy.SOURCE)
@@ -2461,16 +2466,21 @@
             configChanged = displayContent.updateOrientation();
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
 
-            final DisplayInfo rotatedDisplayInfo =
-                    win.mToken.getFixedRotationTransformDisplayInfo();
-            if (rotatedDisplayInfo != null) {
-                outSurfaceControl.setTransformHint(rotatedDisplayInfo.rotation);
-            } else {
-                // We have to update the transform hint of display here, but we need to get if from
-                // SurfaceFlinger, so set it as rotation of display for most cases, then
-                // SurfaceFlinger would still update the transform hint of display in next frame.
-                outSurfaceControl.setTransformHint(displayContent.getDisplayInfo().rotation);
+            final DisplayInfo displayInfo = win.getDisplayInfo();
+            int transformHint = displayInfo.rotation;
+            // If the window is on the primary display, use the panel orientation to adjust the
+            // transform hint
+            final boolean isPrimaryDisplay = displayInfo.address != null &&
+                    displayInfo.address.equals(mPrimaryDisplayPhysicalAddress);
+            if (isPrimaryDisplay) {
+                transformHint = (transformHint + mPrimaryDisplayOrientation) % 4;
             }
+            outSurfaceControl.setTransformHint(transformHint);
+            ProtoLog.v(WM_DEBUG_ORIENTATION,
+                    "Passing transform hint %d for window %s%s",
+                    transformHint, win,
+                    isPrimaryDisplay ? " on primary display with orientation "
+                            + mPrimaryDisplayOrientation : "");
 
             if (toBeDisplayed && win.mIsWallpaper) {
                 displayContent.mWallpaperController.updateWallpaperOffset(win, false /* sync */);
@@ -2816,6 +2826,31 @@
 
     }
 
+    void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
+            int displayId) {
+        synchronized (mGlobalLock) {
+            final DisplayContent dc = mRoot.getDisplayContent(displayId);
+
+            if (dc == null) {
+                ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
+                        + " for non-exiting displayId=%d", binder, displayId);
+                return;
+            }
+            final WindowToken token = dc.removeWindowToken(binder, animateExit);
+            if (token == null) {
+                ProtoLog.w(WM_ERROR,
+                        "removeWindowToken: Attempted to remove non-existing token: %s",
+                        binder);
+                return;
+            }
+
+            if (removeWindows) {
+                token.removeAllWindowsIfPossible();
+            }
+            dc.getInputMonitor().updateInputWindowsLw(true /* force */);
+        }
+    }
+
     @Override
     public void removeWindowToken(IBinder binder, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
@@ -2823,23 +2858,7 @@
         }
         final long origId = Binder.clearCallingIdentity();
         try {
-            synchronized (mGlobalLock) {
-                final DisplayContent dc = mRoot.getDisplayContent(displayId);
-
-                if (dc == null) {
-                    ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
-                            + " for non-exiting displayId=%d", binder, displayId);
-                    return;
-                }
-                final WindowToken token = dc.removeWindowToken(binder);
-                if (token == null) {
-                    ProtoLog.w(WM_ERROR,
-                            "removeWindowToken: Attempted to remove non-existing token: %s",
-                            binder);
-                    return;
-                }
-                dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
-            }
+            removeWindowToken(binder, false /* removeWindows */, true /* animateExit */, displayId);
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
@@ -4859,6 +4878,9 @@
         mTaskSnapshotController.systemReady();
         mHasWideColorGamutSupport = queryWideColorGamutSupport();
         mHasHdrSupport = queryHdrSupport();
+        mPrimaryDisplayOrientation = queryPrimaryDisplayOrientation();
+        mPrimaryDisplayPhysicalAddress =
+            DisplayAddress.fromPhysicalDisplayId(SurfaceControl.getPrimaryPhysicalDisplayId());
         UiThread.getHandler().post(mSettingsObserver::loadSettings);
         IVrManager vrManager = IVrManager.Stub.asInterface(
                 ServiceManager.getService(Context.VR_SERVICE));
@@ -4878,6 +4900,9 @@
         }
     }
 
+
+    // Keep logic in sync with SurfaceFlingerProperties.cpp
+    // Consider exposing properties via ISurfaceComposer instead.
     private static boolean queryWideColorGamutSupport() {
         boolean defaultValue = false;
         Optional<Boolean> hasWideColorProp = SurfaceFlingerProperties.has_wide_color_display();
@@ -4918,6 +4943,39 @@
         return false;
     }
 
+    private static @Surface.Rotation int queryPrimaryDisplayOrientation() {
+        Optional<SurfaceFlingerProperties.primary_display_orientation_values> prop =
+                SurfaceFlingerProperties.primary_display_orientation();
+        if (prop.isPresent()) {
+            switch (prop.get()) {
+                case ORIENTATION_90: return Surface.ROTATION_90;
+                case ORIENTATION_180: return Surface.ROTATION_180;
+                case ORIENTATION_270: return Surface.ROTATION_270;
+                case ORIENTATION_0:
+                default:
+                    return Surface.ROTATION_0;
+            }
+        }
+        try {
+            ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
+            OptionalDisplayOrientation primaryDisplayOrientation =
+                    surfaceFlinger.primaryDisplayOrientation();
+            if (primaryDisplayOrientation != null && primaryDisplayOrientation.specified) {
+                switch (primaryDisplayOrientation.value) {
+                    case DisplayOrientation.ORIENTATION_90: return Surface.ROTATION_90;
+                    case DisplayOrientation.ORIENTATION_180: return Surface.ROTATION_180;
+                    case DisplayOrientation.ORIENTATION_270: return Surface.ROTATION_270;
+                    case DisplayOrientation.ORIENTATION_0:
+                    default:
+                        return Surface.ROTATION_0;
+                }
+            }
+        } catch (Exception e) {
+            // Use default value if we can't talk to config store.
+        }
+        return Surface.ROTATION_0;
+    }
+
     void reportFocusChanged(IBinder oldToken, IBinder newToken) {
         WindowState lastFocus;
         WindowState newFocus;
@@ -7536,28 +7594,10 @@
         }
 
         @Override
-        public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
-            synchronized (mGlobalLock) {
-                if (removeWindows) {
-                    final DisplayContent dc = mRoot.getDisplayContent(displayId);
-                    if (dc == null) {
-                        ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
-                                + " for non-exiting displayId=%d", binder, displayId);
-                        return;
-                    }
-
-                    final WindowToken token = dc.removeWindowToken(binder);
-                    if (token == null) {
-                        ProtoLog.w(WM_ERROR,
-                                "removeWindowToken: Attempted to remove non-existing token: %s",
-                                binder);
-                        return;
-                    }
-
-                    token.removeAllWindowsIfPossible();
-                }
-                WindowManagerService.this.removeWindowToken(binder, displayId);
-            }
+        public void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
+                int displayId) {
+            WindowManagerService.this.removeWindowToken(binder, removeWindows, animateExit,
+                    displayId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 5540cc5..4857fb3 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1547,7 +1547,9 @@
                 // activity as it could lead to incorrect display metrics. For ex, IME services
                 // expect their config to match the config of the display with the IME window
                 // showing.
+                // If the configuration has been overridden by previous activity, empty it.
                 mIsActivityConfigOverrideAllowed = false;
+                unregisterActivityConfigurationListener();
                 break;
             default:
                 break;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c3fc995..5e042ef 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2180,11 +2180,18 @@
         }
     }
 
-    boolean onSetAppExiting() {
+    boolean onSetAppExiting(boolean animateExit) {
         final DisplayContent displayContent = getDisplayContent();
         boolean changed = false;
 
-        if (isVisibleNow()) {
+        if (!animateExit) {
+            // Hide the window permanently if no window exist animation is performed, so we can
+            // avoid the window surface becoming visible again unexpectedly during the next
+            // relayout.
+            mPermanentlyHidden = true;
+            hide(false /* doAnimation */, false /* requestAnim */);
+        }
+        if (isVisibleNow() && animateExit) {
             mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
             if (mWmService.mAccessibilityController != null) {
                 mWmService.mAccessibilityController.onWindowTransition(this, TRANSIT_EXIT);
@@ -2197,7 +2204,7 @@
 
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowState c = mChildren.get(i);
-            changed |= c.onSetAppExiting();
+            changed |= c.onSetAppExiting(animateExit);
         }
 
         return changed;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index fbfa400..3cbc67c 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -24,6 +24,7 @@
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -232,7 +233,7 @@
         }
     }
 
-    void setExiting() {
+    void setExiting(boolean animateExit) {
         if (isEmpty()) {
             super.removeImmediately();
             return;
@@ -247,11 +248,12 @@
 
         final int count = mChildren.size();
         boolean changed = false;
-        final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
+        final boolean delayed = isAnimating(TRANSITION | PARENTS)
+                || (isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION) && animateExit);
 
         for (int i = 0; i < count; i++) {
             final WindowState win = mChildren.get(i);
-            changed |= win.onSetAppExiting();
+            changed |= win.onSetAppExiting(animateExit);
         }
 
         final ActivityRecord app = asActivityRecord();
@@ -353,7 +355,7 @@
     @Override
     void removeImmediately() {
         if (mDisplayContent != null) {
-            mDisplayContent.removeWindowToken(token);
+            mDisplayContent.removeWindowToken(token, true /* animateExit */);
         }
         // Needs to occur after the token is removed from the display above to avoid attempt at
         // duplicate removal of this window container from it's parent.
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 2722b8d..710a304 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -165,7 +165,7 @@
         "android.hardware.power@1.1",
         "android.hardware.power-V2-cpp",
         "android.hardware.power.stats@1.0",
-        "android.hardware.power.stats-V1-ndk_platform",
+        "android.hardware.power.stats-V1-ndk",
         "android.hardware.thermal@1.0",
         "android.hardware.tv.input@1.0",
         "android.hardware.vibrator-V2-cpp",
@@ -178,7 +178,7 @@
         "android.frameworks.schedulerservice@1.0",
         "android.frameworks.sensorservice@1.0",
         "android.frameworks.stats@1.0",
-        "android.frameworks.stats-V1-ndk_platform",
+        "android.frameworks.stats-V1-ndk",
         "android.system.suspend.control-V1-cpp",
         "android.system.suspend.control.internal-cpp",
         "android.system.suspend-V1-ndk",
diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java
index 3a9b2dc..cb52e5f 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -19,6 +19,7 @@
 import static java.util.stream.Collectors.toMap;
 
 import android.Manifest;
+import android.content.ComponentName;
 import android.content.Context;
 import android.os.ISystemConfig;
 import android.util.ArrayMap;
@@ -87,14 +88,14 @@
         }
 
         @Override
-        public List<String> getEnabledComponentOverrides(String packageName) {
+        public List<ComponentName> getEnabledComponentOverrides(String packageName) {
             ArrayMap<String, Boolean> systemComponents = SystemConfig.getInstance()
                     .getComponentsEnabledStates(packageName);
-            List<String> enabledComponent = new ArrayList<>();
+            List<ComponentName> enabledComponent = new ArrayList<>();
             if (systemComponents != null) {
                 for (Map.Entry<String, Boolean> entry : systemComponents.entrySet()) {
                     if (Boolean.TRUE.equals(entry.getValue())) {
-                        enabledComponent.add(entry.getKey());
+                        enabledComponent.add(new ComponentName(packageName, entry.getKey()));
                     }
                 }
             }
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 09a831e..0c3f1dd 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -41,6 +41,7 @@
     sdk_version: "module_current",
     min_sdk_version: "30",
     libs: [
+        "framework-annotations-lib",
         "unsupportedappusage",
         "framework-wifi-util-lib",
         "framework-connectivity",
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index fdf23d3..4fb801e 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -23,7 +23,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ResolveInfo;
 import android.os.Handler;
 import android.os.IBinder.DeathRecipient;
 import android.os.Looper;
@@ -32,8 +31,6 @@
 import android.os.SystemProperties;
 import android.os.UpdateEngine;
 import android.os.UpdateEngineCallback;
-import android.os.UserHandle;
-import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.Log;
 
@@ -45,9 +42,6 @@
 import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 
@@ -306,79 +300,27 @@
             return;
         }
 
-        if (!getUploaderEnabledConfig(getContext())) {
-            return;
-        }
-
+        Context context = getContext();
         new Thread(() -> {
             try {
-                Context context = getContext();
-                final String uploaderPkg = getUploaderPackageName(context);
-                final String uploaderAction = getUploaderActionName(context);
-                String reportUuid = mIProfcollect.report();
+                // Prepare profile report
+                String reportName = mIProfcollect.report() + ".zip";
 
-                final int profileId = getBBProfileId();
-                String reportDir = "/data/user/" + profileId
-                        + "/com.google.android.apps.internal.betterbug/cache/";
-                String reportPath = reportDir + reportUuid + ".zip";
-
-                if (!Files.exists(Paths.get(reportDir))) {
-                    Log.i(LOG_TAG, "Destination directory does not exist, abort upload.");
+                if (!context.getResources().getBoolean(
+                        R.bool.config_profcollectReportUploaderEnabled)) {
+                    Log.i(LOG_TAG, "Upload is not enabled.");
                     return;
                 }
 
-                Intent uploadIntent =
-                        new Intent(uploaderAction)
-                        .setPackage(uploaderPkg)
-                        .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
-                        .putExtra("EXTRA_PACKAGE_NAME", getContext().getPackageName())
-                        .putExtra("EXTRA_PROFILE_PATH", reportPath)
-                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-
-                List<ResolveInfo> receivers =
-                        context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
-                if (receivers == null || receivers.isEmpty()) {
-                    Log.i(LOG_TAG, "No one to receive upload intent, abort upload.");
-                    return;
-                }
-                mIProfcollect.copy_report_to_bb(profileId, reportUuid);
-                context.sendBroadcast(uploadIntent);
-                mIProfcollect.delete_report(reportUuid);
+                // Upload the report
+                Intent intent = new Intent()
+                        .setPackage("com.android.shell")
+                        .setAction("com.android.shell.action.PROFCOLLECT_UPLOAD")
+                        .putExtra("filename", reportName);
+                context.sendBroadcast(intent);
             } catch (RemoteException e) {
                 Log.e(LOG_TAG, e.getMessage());
             }
         }).start();
     }
-
-    /**
-     * Get BetterBug's profile ID. It is the work profile ID, if it exists. Otherwise the system
-     * user ID.
-     *
-     * @return BetterBug's profile ID.
-     */
-    private int getBBProfileId() {
-        UserManager userManager = UserManager.get(getContext());
-        int[] profiles = userManager.getProfileIds(UserHandle.USER_SYSTEM, false);
-        for (int p : profiles) {
-            if (userManager.getUserInfo(p).isManagedProfile()) {
-                return p;
-            }
-        }
-        return UserHandle.USER_SYSTEM;
-    }
-
-    private boolean getUploaderEnabledConfig(Context context) {
-        return context.getResources().getBoolean(
-            R.bool.config_profcollectReportUploaderEnabled);
-    }
-
-    private String getUploaderPackageName(Context context) {
-        return context.getResources().getString(
-            R.string.config_defaultProfcollectReportUploaderApp);
-    }
-
-    private String getUploaderActionName(Context context) {
-        return context.getResources().getString(
-            R.string.config_defaultProfcollectReportUploaderAction);
-    }
 }
diff --git a/services/tests/PackageManagerServiceTests/OWNERS b/services/tests/PackageManagerServiceTests/OWNERS
index 182dfe8..86ae581 100644
--- a/services/tests/PackageManagerServiceTests/OWNERS
+++ b/services/tests/PackageManagerServiceTests/OWNERS
@@ -1,3 +1 @@
-chiuwinson@google.com
-patb@google.com
-toddke@google.com
+include /PACKAGE_MANAGER_OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
deleted file mode 100644
index cb12ba7..0000000
--- a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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 com.android.server;
-
-import static junit.framework.Assert.*;
-
-import static org.mockito.Mockito.*;
-
-import android.hardware.health.V2_0.IHealth;
-import android.hidl.manager.V1_0.IServiceManager;
-import android.hidl.manager.V1_0.IServiceNotification;
-import android.test.AndroidTestCase;
-
-import androidx.test.filters.SmallTest;
-
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.NoSuchElementException;
-
-public class BatteryServiceTest extends AndroidTestCase {
-
-    @Mock IServiceManager mMockedManager;
-    @Mock IHealth mMockedHal;
-    @Mock IHealth mMockedHal2;
-
-    @Mock BatteryService.HealthServiceWrapper.Callback mCallback;
-    @Mock BatteryService.HealthServiceWrapper.IServiceManagerSupplier mManagerSupplier;
-    @Mock BatteryService.HealthServiceWrapper.IHealthSupplier mHealthServiceSupplier;
-    BatteryService.HealthServiceWrapper mWrapper;
-
-    private static final String HEALTHD = BatteryService.HealthServiceWrapper.INSTANCE_HEALTHD;
-    private static final String VENDOR = BatteryService.HealthServiceWrapper.INSTANCE_VENDOR;
-
-    @Override
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Override
-    public void tearDown() {
-        if (mWrapper != null)
-            mWrapper.getHandlerThread().quitSafely();
-    }
-
-    public static <T> ArgumentMatcher<T> isOneOf(Collection<T> collection) {
-        return new ArgumentMatcher<T>() {
-            @Override public boolean matches(T e) {
-                return collection.contains(e);
-            }
-            @Override public String toString() {
-                return collection.toString();
-            }
-        };
-    }
-
-    private void initForInstances(String... instanceNamesArr) throws Exception {
-        final Collection<String> instanceNames = Arrays.asList(instanceNamesArr);
-        doAnswer((invocation) -> {
-                // technically, preexisting is ignored by
-                // BatteryService.HealthServiceWrapper.Notification, but still call it correctly.
-                sendNotification(invocation, true);
-                sendNotification(invocation, true);
-                sendNotification(invocation, false);
-                return null;
-            }).when(mMockedManager).registerForNotifications(
-                eq(IHealth.kInterfaceName),
-                argThat(isOneOf(instanceNames)),
-                any(IServiceNotification.class));
-
-        doReturn(mMockedManager).when(mManagerSupplier).get();
-        doReturn(mMockedHal)        // init calls this
-            .doReturn(mMockedHal)   // notification 1
-            .doReturn(mMockedHal)   // notification 2
-            .doReturn(mMockedHal2)  // notification 3
-            .doThrow(new RuntimeException("Should not call getService for more than 4 times"))
-            .when(mHealthServiceSupplier).get(argThat(isOneOf(instanceNames)));
-
-        mWrapper = new BatteryService.HealthServiceWrapper();
-    }
-
-    private void waitHandlerThreadFinish() throws Exception {
-        for (int i = 0; i < 5; i++) {
-            if (!mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks()) {
-                return;
-            }
-            Thread.sleep(300);
-        }
-        assertFalse(mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks());
-    }
-
-    private static void sendNotification(InvocationOnMock invocation, boolean preexisting)
-            throws Exception {
-        ((IServiceNotification)invocation.getArguments()[2]).onRegistration(
-                IHealth.kInterfaceName,
-                (String)invocation.getArguments()[1],
-                preexisting);
-    }
-
-    @SmallTest
-    public void testWrapPreferVendor() throws Exception {
-        initForInstances(VENDOR, HEALTHD);
-        mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
-        waitHandlerThreadFinish();
-        verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
-        verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
-        verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(VENDOR));
-    }
-
-    @SmallTest
-    public void testUseHealthd() throws Exception {
-        initForInstances(HEALTHD);
-        mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
-        waitHandlerThreadFinish();
-        verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(HEALTHD));
-        verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
-        verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(HEALTHD));
-    }
-
-    @SmallTest
-    public void testNoService() throws Exception {
-        initForInstances("unrelated");
-        try {
-            mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
-            fail("Expect NoSuchElementException");
-        } catch (NoSuchElementException ex) {
-            // expected
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java b/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
new file mode 100644
index 0000000..c97a67b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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 com.android.server.health;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.fail;
+
+import static org.mockito.Mockito.*;
+
+import android.hardware.health.V2_0.IHealth;
+import android.hidl.manager.V1_0.IServiceManager;
+import android.hidl.manager.V1_0.IServiceNotification;
+import android.os.RemoteException;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.NoSuchElementException;
+
+@RunWith(AndroidJUnit4.class)
+public class HealthServiceWrapperTest {
+
+    @Mock IServiceManager mMockedManager;
+    @Mock IHealth mMockedHal;
+    @Mock IHealth mMockedHal2;
+
+    @Mock HealthServiceWrapperHidl.Callback mCallback;
+    @Mock HealthServiceWrapperHidl.IServiceManagerSupplier mManagerSupplier;
+    @Mock HealthServiceWrapperHidl.IHealthSupplier mHealthServiceSupplier;
+    HealthServiceWrapper mWrapper;
+
+    private static final String VENDOR = HealthServiceWrapperHidl.INSTANCE_VENDOR;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @After
+    public void tearDown() {
+        if (mWrapper != null) mWrapper.getHandlerThread().quitSafely();
+    }
+
+    public static <T> ArgumentMatcher<T> isOneOf(Collection<T> collection) {
+        return new ArgumentMatcher<T>() {
+            @Override
+            public boolean matches(T e) {
+                return collection.contains(e);
+            }
+
+            @Override
+            public String toString() {
+                return collection.toString();
+            }
+        };
+    }
+
+    private void initForInstances(String... instanceNamesArr) throws Exception {
+        final Collection<String> instanceNames = Arrays.asList(instanceNamesArr);
+        doAnswer(
+                (invocation) -> {
+                    // technically, preexisting is ignored by
+                    // HealthServiceWrapperHidl.Notification, but still call it correctly.
+                    sendNotification(invocation, true);
+                    sendNotification(invocation, true);
+                    sendNotification(invocation, false);
+                    return null;
+                })
+                .when(mMockedManager)
+                .registerForNotifications(
+                        eq(IHealth.kInterfaceName),
+                        argThat(isOneOf(instanceNames)),
+                        any(IServiceNotification.class));
+
+        doReturn(mMockedManager).when(mManagerSupplier).get();
+        doReturn(mMockedHal) // init calls this
+                .doReturn(mMockedHal) // notification 1
+                .doReturn(mMockedHal) // notification 2
+                .doReturn(mMockedHal2) // notification 3
+                .doThrow(new RuntimeException("Should not call getService for more than 4 times"))
+                .when(mHealthServiceSupplier)
+                .get(argThat(isOneOf(instanceNames)));
+    }
+
+    private void waitHandlerThreadFinish() throws Exception {
+        for (int i = 0; i < 5; i++) {
+            if (!mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks()) {
+                return;
+            }
+            Thread.sleep(300);
+        }
+        assertFalse(mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks());
+    }
+
+    private static void sendNotification(InvocationOnMock invocation, boolean preexisting)
+            throws Exception {
+        ((IServiceNotification) invocation.getArguments()[2])
+                .onRegistration(
+                        IHealth.kInterfaceName, (String) invocation.getArguments()[1], preexisting);
+    }
+
+    private void createWrapper() throws RemoteException {
+        mWrapper = HealthServiceWrapper.create(mCallback, mManagerSupplier, mHealthServiceSupplier);
+    }
+
+    @SmallTest
+    @Test
+    public void testWrapPreferVendor() throws Exception {
+        initForInstances(VENDOR);
+        createWrapper();
+        waitHandlerThreadFinish();
+        verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
+        verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
+        verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(VENDOR));
+    }
+
+    @SmallTest
+    @Test
+    public void testNoService() throws Exception {
+        initForInstances("unrelated");
+        try {
+            createWrapper();
+            fail("Expect NoSuchElementException");
+        } catch (NoSuchElementException ex) {
+            // expected
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/health/OWNERS b/services/tests/servicestests/src/com/android/server/health/OWNERS
new file mode 100644
index 0000000..81522fc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/health/OWNERS
@@ -0,0 +1 @@
+file:platform/hardware/interfaces:/health/aidl/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
index b4fbf5f..184ea52 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
@@ -110,18 +110,20 @@
             @Override
             public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
                 try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
-                    t.setVisibility(leash, true /* visible */).apply();
+                    t.show(leash).apply();
                 }
                 int cookieIndex = -1;
                 if (trampoline.equals(taskInfo.baseActivity)) {
                     cookieIndex = 0;
                 } else if (main.equals(taskInfo.baseActivity)) {
                     cookieIndex = 1;
-                    mainLatch.countDown();
                 }
                 if (cookieIndex >= 0) {
                     appearedCookies[cookieIndex] = taskInfo.launchCookies.isEmpty()
                             ? null : taskInfo.launchCookies.get(0);
+                    if (cookieIndex == 1) {
+                        mainLatch.countDown();
+                    }
                 }
             }
         };
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 293e862a..6f04f17 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -39,6 +39,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -2816,6 +2817,73 @@
         assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
     }
 
+    @Test
+    public void testImeInsetsFrozenFlag_resetWhenReparented() {
+        final ActivityRecord activity = createActivityWithTask();
+        final WindowState app = createWindow(null, TYPE_APPLICATION, activity, "app");
+        final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
+        final Task newTask = new TaskBuilder(mSupervisor).build();
+        makeWindowVisible(app, imeWindow);
+        mDisplayContent.mInputMethodWindow = imeWindow;
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.setImeInputTarget(app);
+
+        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
+        app.mActivityRecord.commitVisibility(false, false);
+        assertTrue(app.mActivityRecord.mLastImeShown);
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Expect IME insets frozen state will reset when the activity is reparent to the new task.
+        activity.setState(RESUMED, "test");
+        activity.reparent(newTask, 0 /* top */, "test");
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+    }
+
+    @UseTestDisplay(addWindows = W_INPUT_METHOD)
+    @Test
+    public void testImeInsetsFrozenFlag_resetWhenResized() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        makeWindowVisibleAndDrawn(app, mImeWindow);
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.setImeInputTarget(app);
+
+        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
+        app.mActivityRecord.commitVisibility(false, false);
+        assertTrue(app.mActivityRecord.mLastImeShown);
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Expect IME insets frozen state will reset when the activity is reparent to the new task.
+        app.mActivityRecord.onResize();
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+    }
+
+    @UseTestDisplay(addWindows = W_INPUT_METHOD)
+    @Test
+    public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        makeWindowVisibleAndDrawn(app, mImeWindow);
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.setImeInputTarget(app);
+
+        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
+        app.mActivityRecord.commitVisibility(false, false);
+        app.mActivityRecord.onWindowsGone();
+
+        assertTrue(app.mActivityRecord.mLastImeShown);
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Expect IME insets frozen state will reset when the activity has no IME focusable window.
+        app.mActivityRecord.forAllWindowsUnchecked(w -> {
+            w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
+            return true;
+        }, true);
+
+        app.mActivityRecord.commitVisibility(true, false);
+        app.mActivityRecord.onWindowsVisible();
+
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+    }
+
     private void assertHasStartingWindow(ActivityRecord atoken) {
         assertNotNull(atoken.mStartingSurface);
         assertNotNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index a8e1753..8e7ba4bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -258,6 +258,7 @@
         final ActivityManagerInternal amInternal = mAmService.mInternal;
         spyOn(amInternal);
         doNothing().when(amInternal).trimApplications();
+        doNothing().when(amInternal).scheduleAppGcs();
         doNothing().when(amInternal).updateCpuStats();
         doNothing().when(amInternal).updateOomAdj();
         doNothing().when(amInternal).updateBatteryStats(any(), anyInt(), anyInt(), anyBoolean());
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 92b670e..d88ac25 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -891,6 +891,40 @@
         assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
     }
 
+    @Test
+    public void testAdjustImeInsetsVisibilityWhenSwitchingApps() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        final WindowState app2 = createWindow(null, TYPE_APPLICATION, "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 app requests IME with updating all windows Insets State when IME is above app.
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.setImeInputTarget(app);
+        assertTrue(mDisplayContent.shouldImeAttachedToApp());
+        controller.getImeSourceProvider().scheduleShowImePostLayout(app);
+        controller.getImeSourceProvider().getSource().setVisible(true);
+        controller.updateAboveInsetsState(imeWindow, false);
+
+        // Expect all app windows behind IME can receive IME insets visible.
+        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertTrue(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+
+        // Simulate app plays closing transition to app2.
+        app.mActivityRecord.commitVisibility(false, false);
+        assertTrue(app.mActivityRecord.mLastImeShown);
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Verify the IME insets is visible on app, but not for app2 during app task switching.
+        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+    }
+
     @UseTestDisplay(addWindows = { W_ACTIVITY })
     @Test
     public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index d048f1842..589f913 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -44,6 +45,7 @@
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 
 import java.util.function.BiFunction;
 
@@ -126,7 +128,7 @@
         final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
         final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
 
-        mDisplayContent.removeWindowToken(token.token);
+        mDisplayContent.removeWindowToken(token.token, true /* animateExit */);
         // Verify that the token is no longer mapped on the display
         assertNull(mDisplayContent.getWindowToken(token.token));
         // Verify that the token is still attached to its parent
@@ -261,4 +263,29 @@
         assertNotNull(app.getFrozenInsetsState());
         assertNull(mDisplayContent.mInputMethodWindow.getFrozenInsetsState());
     }
+
+    @Test
+    public void testRemoveWindowToken_noAnimateExitWhenSet() {
+        final TestWindowToken token = createTestWindowToken(0, mDisplayContent);
+        final WindowState win = createWindow(null, TYPE_APPLICATION, token, "win");
+        makeWindowVisible(win);
+        assertTrue(win.isOnScreen());
+        spyOn(win);
+        spyOn(win.mWinAnimator);
+        spyOn(win.mToken);
+
+        // Invoking removeWindowToken with setting no window exit animation and not remove window
+        // immediately. verify the window will hide without applying exit animation.
+        mWm.removeWindowToken(win.mToken.token, false /* removeWindows */, false /* animateExit */,
+                mDisplayContent.mDisplayId);
+        verify(win).onSetAppExiting(Mockito.eq(false) /* animateExit */);
+        verify(win).hide(false /* doAnimation */, false /* requestAnim */);
+        assertFalse(win.isOnScreen());
+        verify(win.mWinAnimator, Mockito.never()).applyAnimationLocked(TRANSIT_EXIT, false);
+        assertTrue(win.mToken.hasChild());
+
+        // Even though the window is being removed afterwards, it won't apply exit animation.
+        win.removeIfPossible();
+        verify(win.mWinAnimator, Mockito.never()).applyAnimationLocked(TRANSIT_EXIT, false);
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 7f24c36..1579aaf 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -765,6 +765,8 @@
 
             // send a sticky broadcast containing USB accessory handshake information
             Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_HANDSHAKE)
+                    .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+                        | Intent.FLAG_RECEIVER_FOREGROUND)
                     .putExtra(UsbManager.EXTRA_ACCESSORY_UEVENT_TIME,
                             mAccessoryConnectionStartTime)
                     .putExtra(UsbManager.EXTRA_ACCESSORY_STRING_COUNT,
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index cac716e..0ddd52d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -69,7 +69,14 @@
  * them know that the app has crashed and that their call was continued using the pre-loaded dialer
  * app.
  * <p>
- * Further, the pre-loaded dialer will ALWAYS be used when the user places an emergency call.
+ * The pre-loaded dialer will ALWAYS be used when the user places an emergency call, even if your
+ * app fills the {@link android.app.role.RoleManager#ROLE_DIALER} role.  To ensure an optimal
+ * experience when placing an emergency call, the default dialer should ALWAYS use
+ * {@link android.telecom.TelecomManager#placeCall(Uri, Bundle)} to place calls (including
+ * emergency calls).  This ensures that the platform is able to verify that the request came from
+ * the default dialer.  If a non-preloaded dialer app uses {@link Intent#ACTION_CALL} to place an
+ * emergency call, it will be raised to the preloaded dialer app using {@link Intent#ACTION_DIAL}
+ * for confirmation; this is a suboptimal user experience.
  * <p>
  * Below is an example manifest registration for an {@code InCallService}. The meta-data
  * {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} indicates that this particular
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 4df8a4b..4016ba7 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -1,6 +1,5 @@
 set noparent
 
-amitmahajan@google.com
 breadley@google.com
 fionaxu@google.com
 jackyu@google.com
@@ -8,10 +7,10 @@
 tgunn@google.com
 jminjie@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java
index ae597e0..2b355ae 100644
--- a/telephony/java/android/telephony/AvailableNetworkInfo.java
+++ b/telephony/java/android/telephony/AvailableNetworkInfo.java
@@ -16,11 +16,14 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.RadioAccessSpecifier;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -32,7 +35,6 @@
  * Network Service when passed through {@link TelephonyManager#updateAvailableNetworks}
  */
 public final class AvailableNetworkInfo implements Parcelable {
-
     /*
      * Defines number of priority level high.
      */
@@ -48,6 +50,14 @@
      */
     public static final int PRIORITY_LOW = 3;
 
+    /** @hide */
+    @IntDef({
+        PRIORITY_HIGH,
+        PRIORITY_MED,
+        PRIORITY_LOW,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AvailableNetworkInfoPriority {}
     /**
      * subscription Id of the available network. This value must be one of the entry retrieved from
      * {@link SubscriptionManager#getOpportunisticSubscriptions}
@@ -62,7 +72,7 @@
      * for network selection. If there are more than one subId with highest priority then the
      * network with highest RSRP is chosen.
      */
-    private int mPriority;
+    private @AvailableNetworkInfoPriority int mPriority;
 
     /**
      * Describes the List of PLMN ids (MCC-MNC) associated with mSubId.
@@ -77,8 +87,7 @@
      * Opportunistic network service will use these bands to scan.
      *
      * When no specific bands are specified (empty array or null) CBRS band
-     * {@link AccessNetworkConstants.EutranBand.BAND_48
-     * } will be used for network scan.
+     * {@link AccessNetworkConstants.EutranBand.BAND_48} will be used for network scan.
      *
      * See {@link AccessNetworkConstants} for details.
      *
@@ -94,7 +103,7 @@
      * If this entry is left empty, {@link RadioAcccessSpecifier}s with {@link AccessNetworkType}s
      * of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link
      * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed
-     * by Opportunistic network service.
+     * by Opportunistic network service for a network scan.
      */
     private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers;
 
@@ -117,6 +126,7 @@
      * network with highest RSRP is chosen.
      * @return priority level
      */
+    @AvailableNetworkInfoPriority
     public int getPriority() {
         return mPriority;
     }
@@ -149,15 +159,9 @@
      * Returns a list of {@link RadioAccessSpecifier} associated with the available network.
      * Opportunistic network service will use this to determine which bands to scan for.
      *
-     * the returned value is one of {@link AccessNetworkConstants.AccessNetworkType}. When no
-     * specific access network type is specified, {@link RadioAccessSpecifier}s with {@link
-     * AccessNetworkType}s of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link
-     * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed
-     * by Opportunistic network service.
      * @return the access network type associated with the available network.
-     * @hide
      */
-    public List<RadioAccessSpecifier>  getRadioAccessSpecifiers() {
+    public @NonNull List<RadioAccessSpecifier> getRadioAccessSpecifiers() {
         return (List<RadioAccessSpecifier>) mRadioAccessSpecifiers.clone();
     }
 
@@ -193,9 +197,9 @@
     }
 
     /** @hide */
-    private AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
-            @NonNull List<Integer> bands, @NonNull List<RadioAccessSpecifier>
-            radioAccessSpecifiers) {
+    private AvailableNetworkInfo(int subId, @AvailableNetworkInfoPriority int priority,
+            @NonNull List<String> mccMncs, @NonNull List<Integer> bands,
+            @NonNull List<RadioAccessSpecifier> radioAccessSpecifiers) {
         mSubId = subId;
         mPriority = priority;
         mMccMncs = new ArrayList<String>(mccMncs);
@@ -261,27 +265,39 @@
      *
      * <pre><code>
      *
-     * AvailableNetworkInfo aNI = new AvailableNetworkInfo.Builder()
-     *     .setSubId(1)
+     * AvailableNetworkInfo aNI = new AvailableNetworkInfo.Builder(subId)
      *     .setPriority(AvailableNetworkInfo.PRIORITY_MED)
+     *     .setRadioAccessSpecifiers(radioAccessSpecifiers)
+     *     .setMccMncs(mccMncs)
      *     .build();
      * </code></pre>
-     *
-     * @hide
      */
     public static final class Builder {
         private int mSubId = Integer.MIN_VALUE;
-        private int mPriority = AvailableNetworkInfo.PRIORITY_LOW;
+        private @AvailableNetworkInfoPriority int mPriority = AvailableNetworkInfo.PRIORITY_LOW;
         private ArrayList<String> mMccMncs = new ArrayList<>();
-        private ArrayList<Integer> mBands = new ArrayList<>();
         private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers = new ArrayList<>();
 
-        public @NonNull Builder setSubId(int subId) {
+        /**
+         *
+         */
+        /**
+         * Creates an AvailableNetworkInfo Builder with specified subscription id.
+         *
+         * @param subId of the availableNetwork.
+         */
+        public Builder(int subId) {
             mSubId = subId;
-            return this;
         }
 
-        public @NonNull Builder setPriority(int priority) {
+        /**
+         * Sets the priority for the subscription id.
+         *
+         * @param priority of the subscription id. See {@link AvailableNetworkInfo#getPriority} for
+         * more details
+         * @return the original Builder object.
+         */
+        public @NonNull Builder setPriority(@AvailableNetworkInfoPriority int priority) {
             if (priority > AvailableNetworkInfo.PRIORITY_LOW
                     || priority < AvailableNetworkInfo.PRIORITY_HIGH) {
                 throw new IllegalArgumentException("A valid priority must be set");
@@ -290,30 +306,48 @@
             return this;
         }
 
-        public @NonNull Builder setMccMncs(@NonNull ArrayList<String> mccMncs) {
-            Objects.requireNonNull(mccMncs, "A non-null ArrayList of mccmncs must be set. An empty "
-                    + "list is still accepted. Please read documentation in "
-                    + "AvailableNetworkService to see consequences of an empty Arraylist.");
-            mMccMncs = mccMncs;
+        /**
+         * Sets the list of mccmncs associated with the subscription id.
+         *
+         * @param mccMncs nonull list of mccmncs. An empty List is still accepted. Please read
+         * documentation in {@link AvailableNetworkInfo} to see consequences of an empty List.
+         * @return the original Builder object.
+         */
+        public @NonNull Builder setMccMncs(@NonNull List<String> mccMncs) {
+            Objects.requireNonNull(mccMncs, "A non-null List of mccmncs must be set. An empty "
+                    + "List is still accepted. Please read documentation in "
+                    + "AvailableNetworkInfo to see consequences of an empty List.");
+            mMccMncs = new ArrayList<>(mccMncs);
             return this;
         }
 
+        /**
+         * Sets the list of mccmncs associated with the subscription id.
+         *
+         * @param radioAccessSpecifiers nonull list of radioAccessSpecifiers. An empty List is still
+         * accepted. Please read documentation in {@link AvailableNetworkInfo} to see
+         * consequences of an empty List.
+         * @return the original Builder object.
+         */
         public @NonNull Builder setRadioAccessSpecifiers(
-                @NonNull ArrayList<RadioAccessSpecifier> radioAccessSpecifiers) {
-            Objects.requireNonNull(radioAccessSpecifiers, "A non-null ArrayList of "
-                    + "RadioAccessSpecifiers must be set. An empty list is still accepted. Please "
-                    + "read documentation in AvailableNetworkService to see consequences of an "
-                    + "empty Arraylist.");
-            mRadioAccessSpecifiers = radioAccessSpecifiers;
+                @NonNull List<RadioAccessSpecifier> radioAccessSpecifiers) {
+            Objects.requireNonNull(radioAccessSpecifiers, "A non-null List of "
+                    + "RadioAccessSpecifiers must be set. An empty List is still accepted. Please "
+                    + "read documentation in AvailableNetworkInfo to see consequences of an "
+                    + "empty List.");
+            mRadioAccessSpecifiers = new ArrayList<>(radioAccessSpecifiers);
             return this;
         }
 
+        /**
+         * @return an AvailableNetworkInfo object with all the fields previously set by the Builder.
+         */
         public @NonNull AvailableNetworkInfo build() {
             if (mSubId == Integer.MIN_VALUE) {
                 throw new IllegalArgumentException("A valid subId must be set");
             }
 
-            return new AvailableNetworkInfo(mSubId, mPriority, mMccMncs, mBands,
+            return new AvailableNetworkInfo(mSubId, mPriority, mMccMncs, new ArrayList<>(),
                     mRadioAccessSpecifiers);
         }
     }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 73e6c76..df1f132 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressAutoDoc;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -1879,6 +1880,20 @@
             "lte_plus_threshold_bandwidth_khz_int";
 
     /**
+     * The combined channel bandwidth threshold (non-inclusive) in KHz required to display the
+     * NR advanced (i.e. 5G+) data icon. It is 0 by default, meaning minimum bandwidth check is
+     * not enabled. Other factors like bands or frequency can also determine whether the NR
+     * advanced data icon is shown or not.
+     *
+     * @see #KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY
+     * @see #KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT
+     *
+     * @hide
+     */
+    public static final String KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT =
+            "nr_advanced_threshold_bandwidth_khz_int";
+
+    /**
      * The string is used to filter redundant string from PLMN Network Name that's supplied by
      * specific carrier.
      *
@@ -3543,6 +3558,17 @@
             "nr_advanced_capable_pco_id_int";
 
     /**
+     * Enabled NR advanced (i.e. 5G+) icon while roaming. The default value is {@code true}, meaming
+     * the same NR advanced logic used for home network will be used for roaming network as well.
+     * Set this to {@code false} will disable NR advanced icon while the device is roaming,
+     * regardless meeting NR advanced criteria or not.
+     *
+     * @hide
+     */
+    public static final String KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL =
+            "enable_nr_advanced_for_roaming_bool";
+
+    /**
      * This configuration allows the framework to use user data communication to detect Idle state,
      * and this is used on the 5G icon.
      *
@@ -3649,6 +3675,49 @@
             "show_wifi_calling_icon_in_status_bar_bool";
 
     /**
+     * Configuration to indicate that the carrier supports opportunistic data
+     * auto provisioning. Based on this flag, the device downloads and activates
+     * corresponding opportunistic profile.
+     */
+    public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL =
+            "carrier_supports_opp_data_auto_provisioning_bool";
+
+    /**
+     * SMDP+ server address for downloading opportunistic eSIM profile.
+     * FQDN (Fully Qualified Domain Name) of the SM-DP+ (e.g., smdp.gsma.com) restricted to the
+     * Alphanumeric mode character set defined in table 5 of ISO/IEC 18004 [15] excluding '$'.
+     */
+    public static final String KEY_SMDP_SERVER_ADDRESS_STRING =
+            "smdp_server_address_string";
+
+    /**
+     * This timer value is used in the eSIM Exponential Backoff download retry algorithm.
+     * Value should be in seconds.
+     * <OL>
+     *     <LI>When the first download failure occurs, retry download after BACKOFF_TIMER_VALUE
+     * seconds.</LI>
+     *
+     * <LI>If download fails again then, retry after either BACKOFF_TIMER_VALUE,
+     * 2xBACKOFF_TIMER_VALUE, or 3xBACKOFF_TIMER_VALUE seconds.</LI>
+     *
+     * <LI>In general after the cth failed attempt, retry after k * BACKOFF_TIMER_VALUE
+     * seconds, where k is a random integer between 1 and 2^c − 1. Max c value is
+     * {@link #KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT}</LI>
+     * </OL>
+     */
+    public static final String KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT =
+            "esim_download_retry_backoff_timer_sec_int";
+
+    /**
+     * If eSIM profile download fails then, the number of retry attempts by UE
+     * will be based on this configuration. If download still fails even after the
+     * MAX attempts configured by this item then the retry is postponed until next
+     * device bootup.
+     */
+    public static final String KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT =
+            "esim_max_download_retry_attempts_int";
+
+    /**
      * Controls RSRP threshold at which OpportunisticNetworkService will decide whether
      * the opportunistic network is good enough for internet data.
      */
@@ -3858,6 +3927,30 @@
     public static final String KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL =
             "enabled_4g_opportunistic_network_scan_bool";
 
+  /**
+   * Only relevant when the device supports opportunistic networks but does not support
+   * simultaneuous 5G+5G. Controls how long, in milliseconds, to wait before opportunistic network
+   * goes out of service before switching the 5G capability back to primary stack. The idea of
+   * waiting a few seconds is to minimize the calling of the expensive capability switching
+   * operation in the case where CBRS goes back into service shortly after going out of it.
+   *
+   * @hide
+   */
+  public static final String KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG =
+            "time_to_switch_back_to_primary_if_opportunistic_oos_long";
+
+  /**
+   * Only relevant when the device supports opportunistic networks but does not support
+   * simultaneuous 5G+5G. Controls how long, in milliseconds, after 5G capability has switched back
+   * to primary stack due to opportunistic network being OOS. The idea is to minimizing the
+   * 'ping-ponging' effect where device is constantly witching capability back and forth between
+   * primary and opportunistic stack.
+   *
+   * @hide
+   */
+  public static final String KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG
+          = "opportunistic_time_to_scan_after_capability_switch_to_primary_long";
+
     /**
      * Indicates zero or more emergency number prefix(es), because some carrier requires
      * if users dial an emergency number address with a specific prefix, the combination of the
@@ -5166,6 +5259,16 @@
             "display_no_data_notification_on_permanent_failure_bool";
 
     /**
+     * Boolean indicating if the VoNR setting is visible in the Call Settings menu.
+     * If true, the VoNR setting menu will be visible. If false, the menu will be gone.
+     *
+     * Disabled by default.
+     *
+     * @hide
+     */
+    public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool";
+
+    /**
      * Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes
      *
      * @hide
@@ -5560,6 +5663,7 @@
         sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
         sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
         sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
+        sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0);
         sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
                 new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA});
         sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
@@ -5655,6 +5759,7 @@
         sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
         sDefaults.putIntArray(KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY, new int[0]);
         sDefaults.putInt(KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT, 0);
+        sDefaults.putBoolean(KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL, true);
         sDefaults.putBoolean(KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, false);
         sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
         sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
@@ -5665,6 +5770,10 @@
         sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false);
         sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false);
+        sDefaults.putString(KEY_SMDP_SERVER_ADDRESS_STRING, "");
+        sDefaults.putInt(KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 5);
+        sDefaults.putInt(KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 60);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
         sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_MODERATE */
@@ -5708,6 +5817,10 @@
         /* Default value is 2 seconds. */
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000);
         sDefaults.putBoolean(KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL, true);
+        sDefaults.putInt(KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG, 60000);
+        sDefaults.putInt(
+                KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG,
+                120000);
         sDefaults.putAll(Gps.getDefaults());
         sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
                 new int[] {
@@ -5779,6 +5892,7 @@
         sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, "");
         sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
         sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
+        sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false);
     }
 
     /**
@@ -5847,12 +5961,15 @@
      * any carrier specific configuration has been applied.
      *
      * <p>Requires Permission:
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}, or the calling app
+     * has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges()}).
      *
      * @param subId the subscription ID, normally obtained from {@link SubscriptionManager}.
      * @return A {@link PersistableBundle} containing the config for the given subId, or default
      *         values for an invalid subId.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
     @Nullable
     public PersistableBundle getConfigForSubId(int subId) {
         try {
@@ -5941,10 +6058,13 @@
      * called to confirm whether any carrier specific configuration has been applied.
      *
      * <p>Requires Permission:
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}, or the calling app
+     * has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges()}).
      *
      * @see #getConfigForSubId
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
     @Nullable
     public PersistableBundle getConfig() {
         return getConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
@@ -5953,8 +6073,8 @@
     /**
      * Determines whether a configuration {@link PersistableBundle} obtained from
      * {@link #getConfig()} or {@link #getConfigForSubId(int)} corresponds to an identified carrier.
-     * <p>
-     * When an app receives the {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED}
+     *
+     * <p>When an app receives the {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED}
      * broadcast which informs it that the carrier configuration has changed, it is possible
      * that another reload of the carrier configuration has begun since the intent was sent.
      * In this case, the carrier configuration the app fetches (e.g. via {@link #getConfig()})
@@ -5963,14 +6083,12 @@
      * return true because it may belong to another previous identified carrier. Users should
      * always call {@link #getConfig()} or {@link #getConfigForSubId(int)} after receiving the
      * broadcast {@link #ACTION_CARRIER_CONFIG_CHANGED}.
-     * </p>
-     * <p>
-     * After using {@link #getConfig()} or {@link #getConfigForSubId(int)} an app should always
+     *
+     * <p>After using {@link #getConfig()} or {@link #getConfigForSubId(int)} an app should always
      * use this method to confirm whether any carrier specific configuration has been applied.
      * Especially when an app misses the broadcast {@link #ACTION_CARRIER_CONFIG_CHANGED} but it
      * still needs to get the current configuration, it must use this method to verify whether the
      * configuration is default or carrier overridden.
-     * </p>
      *
      * @param bundle the configuration bundle to be checked.
      * @return boolean true if any carrier specific configuration bundle has been applied, false
@@ -5982,19 +6100,20 @@
 
     /**
      * Calling this method triggers telephony services to fetch the current carrier configuration.
-     * <p>
-     * Normally this does not need to be called because the platform reloads config on its own.
+     *
+     * <p>Normally this does not need to be called because the platform reloads config on its own.
      * This should be called by a carrier service app if it wants to update config at an arbitrary
      * moment.
-     * </p>
-     * <p>Requires that the calling app has carrier privileges.
-     * <p>
-     * This method returns before the reload has completed, and
-     * {@link android.service.carrier.CarrierService#onLoadConfig} will be called from an
-     * arbitrary thread.
-     * </p>
-     * @see TelephonyManager#hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or the calling app
+     * has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges()}).
+     *
+     * <p>This method returns before the reload has completed, and {@link
+     * android.service.carrier.CarrierService#onLoadConfig} will be called from an arbitrary thread.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void notifyConfigChangedForSubId(int subId) {
         try {
             ICarrierConfigLoader loader = getICarrierConfigLoader();
@@ -6010,11 +6129,10 @@
     }
 
     /**
-     * Request the carrier config loader to update the cofig for phoneId.
-     * <p>
-     * Depending on simState, the config may be cleared or loaded from config app. This is only used
-     * by SubscriptionInfoUpdater.
-     * </p>
+     * Request the carrier config loader to update the config for phoneId.
+     *
+     * <p>Depending on simState, the config may be cleared or loaded from config app. This is only
+     * used by SubscriptionInfoUpdater.
      *
      * @hide
      */
@@ -6085,13 +6203,16 @@
      * Gets the configuration values for a component using its prefix.
      *
      * <p>Requires Permission:
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}, or the calling app
+     * has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges()}).
      *
      * @param prefix prefix of the component.
      * @param subId the subscription ID, normally obtained from {@link SubscriptionManager}.
      *
      * @see #getConfigForSubId
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
     @Nullable
     public PersistableBundle getConfigByComponentForSubId(@NonNull String prefix, int subId) {
         PersistableBundle configs = getConfigForSubId(subId);
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index d250088..95448c7 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -242,6 +242,11 @@
     }
 
     /**
+     * The physical cell ID which differentiates cells using the same radio channel.
+     *
+     * In GERAN, this value is the BSIC. The range is [0-63].
+     * Reference: 3GPP TS 3.03 section 4.2.2.
+     *
      * In UTRAN, this value is primary scrambling code. The range is [0, 511].
      * Reference: 3GPP TS 25.213 section 5.2.2.
      *
diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
index 41e24dd..2ff4ac5 100644
--- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
+++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
@@ -17,6 +17,8 @@
 package android.telephony;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -66,10 +68,15 @@
     private final IBinder mLiveToken;
 
     private SignalStrengthUpdateRequest(
-            @NonNull List<SignalThresholdInfo> signalThresholdInfos,
+            @Nullable List<SignalThresholdInfo> signalThresholdInfos,
             boolean isReportingRequestedWhileIdle,
             boolean isSystemThresholdReportingRequestedWhileIdle) {
-        validate(signalThresholdInfos);
+        // System app (like Bluetooth) can specify the request to report system thresholds while
+        // device is idle (with permission protection). In this case, the request doesn't need to
+        // provide a non-empty list of SignalThresholdInfo which is only asked for public apps.
+        if (!isSystemThresholdReportingRequestedWhileIdle) {
+            validate(signalThresholdInfos);
+        }
 
         mSignalThresholdInfos = signalThresholdInfos;
         mIsReportingRequestedWhileIdle = isReportingRequestedWhileIdle;
@@ -128,13 +135,15 @@
         /**
          * Set the builder object if require reporting on the system thresholds when device is idle.
          *
-         * This can only used by the system caller.
+         * <p>This can only used by the system caller. Requires permission
+         * {@link android.Manifest.permission#LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH}.
          *
          * @param isSystemThresholdReportingRequestedWhileIdle true if request reporting on the
          *                                                     system thresholds when device is idle
          * @return the builder to facilitate the chaining
          * @hide
          */
+        @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
         public @NonNull Builder setSystemThresholdReportingRequestedWhileIdle(
                 boolean isSystemThresholdReportingRequestedWhileIdle) {
             mIsSystemThresholdReportingRequestedWhileIdle =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 255a612..6ffdc6b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2945,7 +2945,12 @@
      * currently in use on the device for data transmission.
      *
      * If this object has been created with {@link #createForSubscriptionId}, applies to the given
-     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     * subId. Otherwise, applies to {@link SubscriptionManager#getActiveDataSubscriptionId()}.
+     *
+     * Note: Before {@link SubscriptionManager#getActiveDataSubscriptionId()} was introduced in API
+     * level 30, it was applied to {@link SubscriptionManager#getDefaultDataSubscriptionId()} which
+     * may be different now from {@link SubscriptionManager#getActiveDataSubscriptionId()}, e.g.
+     * when opportunistic network is providing cellular internet connection to the user.
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -12143,6 +12148,100 @@
     }
 
     /**
+     * No error. Operation succeeded.
+     * @hide
+     */
+    public static final int ENABLE_VONR_SUCCESS = 0;
+
+    /**
+     * Radio is not available.
+     * @hide
+     */
+    public static final int ENABLE_VONR_RADIO_NOT_AVAILABLE = 2;
+
+    /**
+     * Internal Radio error.
+     * @hide
+     */
+    public static final int ENABLE_VONR_RADIO_ERROR = 3;
+
+    /**
+     * Voice over NR enable/disable request is received when system is in invalid state.
+     * @hide
+     */
+    public static final int ENABLE_VONR_RADIO_INVALID_STATE = 4;
+
+    /**
+     * Voice over NR enable/disable request is not supported.
+     * @hide
+     */
+    public static final int ENABLE_VONR_REQUEST_NOT_SUPPORTED = 5;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"EnableVoNrResult"}, value = {
+            ENABLE_VONR_SUCCESS,
+            ENABLE_VONR_RADIO_NOT_AVAILABLE,
+            ENABLE_VONR_RADIO_ERROR,
+            ENABLE_VONR_RADIO_INVALID_STATE,
+            ENABLE_VONR_REQUEST_NOT_SUPPORTED})
+    public @interface EnableVoNrResult {}
+
+    /**
+     * Enable or disable Voice over NR (VoNR)
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param enabled  enable or disable VoNR.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public @EnableVoNrResult int setVoNrEnabled(boolean enabled) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.setVoNrEnabled(
+                        getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#setVoNrEnabled", e);
+        }
+
+        return ENABLE_VONR_RADIO_INVALID_STATE;
+    }
+
+    /**
+     * Is Voice over NR (VoNR) enabled.
+     * @return true if Voice over NR (VoNR) is enabled else false. Enabled state does not mean
+     *  voice call over NR is active or voice ove NR is available. It means the device is allowed to
+     *  register IMS over NR.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isVoNrEnabled() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isVoNrEnabled(getSubId());
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "isVoNrEnabled RemoteException", ex);
+            ex.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
+    /**
      * Carrier action to start or stop reporting default network available events.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
@@ -12420,26 +12519,6 @@
     }
 
     /**
-     * Enable or disable signal strength changes from radio will always be reported in any
-     * condition (e.g. screen is off). This is only allowed for System caller.
-     *
-     * @param isEnabled {@code true} for enabling; {@code false} for disabling.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void setAlwaysReportSignalStrength(boolean isEnabled) {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                telephony.setAlwaysReportSignalStrength(getSubId(), isEnabled);
-            }
-        } catch (RemoteException ex) {
-            Log.e(TAG, "setAlwaysReportSignalStrength RemoteException", ex);
-            ex.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
      * Get the most recently available signal strength information.
      *
      * Get the most recent SignalStrength information reported by the modem. Due
@@ -13542,15 +13621,18 @@
     }
 
     /**
-     * It indicates whether modem is enabled or not per slot.
-     * It's the corresponding status of TelephonyManager.enableModemForSlot.
+     * Indicates whether or not there is a modem stack enabled for the given SIM slot.
      *
      * <p>Requires Permission:
-     * READ_PRIVILEGED_PHONE_STATE or
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE},
+     * READ_PRIVILEGED_PHONE_STATE or that the calling app has carrier privileges (see
+     * {@link #hasCarrierPrivileges()}).
+     *
      * @param slotIndex which slot it's checking.
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
     public boolean isModemEnabledForSlot(int slotIndex) {
         try {
             ITelephony telephony = getITelephony();
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index e890acb..9572154 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -36,6 +36,7 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -152,16 +153,9 @@
                     throw new RuntimeException(
                         "Failed to find NetworkScanInfo with id " + message.arg2);
                 }
-                NetworkScanCallback callback = nsi.mCallback;
-                Executor executor = nsi.mExecutor;
-                if (callback == null) {
-                    throw new RuntimeException(
-                        "Failed to find NetworkScanCallback with id " + message.arg2);
-                }
-                if (executor == null) {
-                    throw new RuntimeException(
-                        "Failed to find Executor with id " + message.arg2);
-                }
+
+                final NetworkScanCallback callback = nsi.mCallback;
+                final Executor executor = nsi.mExecutor;
 
                 switch (message.what) {
                     case CALLBACK_RESTRICTED_SCAN_RESULTS:
@@ -246,17 +240,24 @@
             NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
             String callingPackage, @Nullable String callingFeatureId) {
         try {
+            Objects.requireNonNull(request, "Request was null");
+            Objects.requireNonNull(callback, "Callback was null");
+            Objects.requireNonNull(executor, "Executor was null");
             final ITelephony telephony = getITelephony();
             if (telephony == null) return null;
 
-            int scanId = telephony.requestNetworkScan(
-                    subId, request, mMessenger, new Binder(), callingPackage,
-                    callingFeatureId);
-            if (scanId == INVALID_SCAN_ID) {
-                Rlog.e(TAG, "Failed to initiate network scan");
-                return null;
-            }
+            // The lock must be taken before calling requestNetworkScan because the resulting
+            // scanId can be invoked asynchronously on another thread at any time after
+            // requestNetworkScan invoked, leaving a critical section between that call and adding
+            // the record to the ScanInfo cache.
             synchronized (mScanInfo) {
+                int scanId = telephony.requestNetworkScan(
+                        subId, request, mMessenger, new Binder(), callingPackage,
+                        callingFeatureId);
+                if (scanId == INVALID_SCAN_ID) {
+                    Rlog.e(TAG, "Failed to initiate network scan");
+                    return null;
+                }
                 // We link to death whenever a scan is started to ensure that we are linked
                 // at the point that phone process death might matter.
                 // We never unlink because:
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index be1502a..1ef04be 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -147,7 +147,12 @@
     }
 
     // Possible values for authentication types.
-    /** No authentication type. */
+    /**
+     * Authentication type is unknown.
+     * @hide
+     */
+    public static final int AUTH_TYPE_UNKNOWN = -1;
+    /** Authentication is not required. */
     public static final int AUTH_TYPE_NONE = 0;
     /** Authentication type for PAP. */
     public static final int AUTH_TYPE_PAP = 1;
@@ -357,6 +362,7 @@
 
     /** @hide */
     @IntDef(prefix = { "AUTH_TYPE_" }, value = {
+        AUTH_TYPE_UNKNOWN,
         AUTH_TYPE_NONE,
         AUTH_TYPE_PAP,
         AUTH_TYPE_CHAP,
@@ -498,7 +504,8 @@
     private final String mOperatorNumeric;
     private final int mProtocol;
     private final int mRoamingProtocol;
-    private final int mMtu;
+    private final int mMtuV4;
+    private final int mMtuV6;
 
     private final boolean mCarrierEnabled;
 
@@ -522,13 +529,25 @@
     private final int mSkip464Xlat;
 
     /**
-     * Returns the MTU size of the mobile interface to which the APN connected.
+     * Returns the MTU size of the IPv4 mobile interface to which the APN connected. Note this value
+     * is used only if MTU size is not provided in {@link DataCallResponse}.
      *
      * @return the MTU size of the APN
      * @hide
      */
-    public int getMtu() {
-        return mMtu;
+    public int getMtuV4() {
+        return mMtuV4;
+    }
+
+    /**
+     * Returns the MTU size of the IPv6 mobile interface to which the APN connected. Note this value
+     * is used only if MTU size is not provided in {@link DataCallResponse}.
+     *
+     * @return the MTU size of the APN
+     * @hide
+     */
+    public int getMtuV6() {
+        return mMtuV6;
     }
 
     /**
@@ -879,13 +898,18 @@
         this.mMmsProxyPort = builder.mMmsProxyPort;
         this.mUser = builder.mUser;
         this.mPassword = builder.mPassword;
-        this.mAuthType = builder.mAuthType;
+        this.mAuthType = (builder.mAuthType != AUTH_TYPE_UNKNOWN)
+                ? builder.mAuthType
+                : TextUtils.isEmpty(builder.mUser)
+                        ? AUTH_TYPE_NONE
+                        : AUTH_TYPE_PAP_OR_CHAP;
         this.mApnTypeBitmask = builder.mApnTypeBitmask;
         this.mId = builder.mId;
         this.mOperatorNumeric = builder.mOperatorNumeric;
         this.mProtocol = builder.mProtocol;
         this.mRoamingProtocol = builder.mRoamingProtocol;
-        this.mMtu = builder.mMtu;
+        this.mMtuV4 = builder.mMtuV4;
+        this.mMtuV6 = builder.mMtuV6;
         this.mCarrierEnabled = builder.mCarrierEnabled;
         this.mNetworkTypeBitmask = builder.mNetworkTypeBitmask;
         this.mProfileId = builder.mProfileId;
@@ -903,66 +927,6 @@
     /**
      * @hide
      */
-    public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
-            String apnName, String proxyAddress, int proxyPort, Uri mmsc,
-            String mmsProxyAddress, int mmsProxyPort, String user, String password,
-            int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
-            boolean carrierEnabled, int networkTypeBitmask, int profileId,
-            boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime, int mtu,
-            int mvnoType, String mvnoMatchData, int apnSetId, int carrierId, int skip464xlat) {
-        return new Builder()
-            .setId(id)
-            .setOperatorNumeric(operatorNumeric)
-            .setEntryName(entryName)
-            .setApnName(apnName)
-            .setProxyAddress(proxyAddress)
-            .setProxyPort(proxyPort)
-            .setMmsc(mmsc)
-            .setMmsProxyAddress(mmsProxyAddress)
-            .setMmsProxyPort(mmsProxyPort)
-            .setUser(user)
-            .setPassword(password)
-            .setAuthType(authType)
-            .setApnTypeBitmask(mApnTypeBitmask)
-            .setProtocol(protocol)
-            .setRoamingProtocol(roamingProtocol)
-            .setCarrierEnabled(carrierEnabled)
-            .setNetworkTypeBitmask(networkTypeBitmask)
-            .setProfileId(profileId)
-            .setModemCognitive(modemCognitive)
-            .setMaxConns(maxConns)
-            .setWaitTime(waitTime)
-            .setMaxConnsTime(maxConnsTime)
-            .setMtu(mtu)
-            .setMvnoType(mvnoType)
-            .setMvnoMatchData(mvnoMatchData)
-            .setApnSetId(apnSetId)
-            .setCarrierId(carrierId)
-            .setSkip464Xlat(skip464xlat)
-            .buildWithoutCheck();
-    }
-
-    /**
-     * @hide
-     */
-    public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
-            String apnName, String proxyAddress, int proxyPort, Uri mmsc,
-            String mmsProxyAddress, int mmsProxyPort, String user, String password,
-            int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
-            boolean carrierEnabled, int networkTypeBitmask, int profileId, boolean modemCognitive,
-            int maxConns, int waitTime, int maxConnsTime, int mtu, int mvnoType,
-            String mvnoMatchData) {
-        return makeApnSetting(id, operatorNumeric, entryName, apnName, proxyAddress, proxyPort,
-            mmsc, mmsProxyAddress, mmsProxyPort, user, password, authType, mApnTypeBitmask,
-            protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, profileId,
-            modemCognitive, maxConns, waitTime, maxConnsTime, mtu, mvnoType, mvnoMatchData,
-            Carriers.NO_APN_SET_ID, TelephonyManager.UNKNOWN_CARRIER_ID,
-            Carriers.SKIP_464XLAT_DEFAULT);
-    }
-
-    /**
-     * @hide
-     */
     public static ApnSetting makeApnSetting(Cursor cursor) {
         final int apnTypesBitmask = getApnTypesBitmaskFromString(
                 cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
@@ -975,272 +939,99 @@
                 ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
         }
 
-        return makeApnSetting(
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
-            cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
-            portFromString(cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
-            UriFromString(cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
-            cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
-            portFromString(cursor.getString(
-                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
-            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
-            apnTypesBitmask,
-            getProtocolIntFromString(
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
-            getProtocolIntFromString(
-                cursor.getString(cursor.getColumnIndexOrThrow(
-                    Telephony.Carriers.ROAMING_PROTOCOL))),
-            cursor.getInt(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.CARRIER_ENABLED)) == 1,
-            networkTypeBitmask,
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.MODEM_PERSIST)) == 1,
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNECTIONS)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME_RETRY)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
-            getMvnoTypeIntFromString(
-                cursor.getString(cursor.getColumnIndexOrThrow(
-                    Telephony.Carriers.MVNO_TYPE))),
-            cursor.getString(cursor.getColumnIndexOrThrow(
-                Telephony.Carriers.MVNO_MATCH_DATA)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)));
+        return new Builder()
+                .setId(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)))
+                .setOperatorNumeric(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)))
+                .setEntryName(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)))
+                .setApnName(cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)))
+                .setProxyAddress(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)))
+                .setProxyPort(portFromString(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))))
+                .setMmsc(UriFromString(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))))
+                .setMmsProxyAddress(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)))
+                .setMmsProxyPort(portFromString(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))))
+                .setUser(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)))
+                .setPassword(cursor.getString(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)))
+                .setAuthType(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)))
+                .setApnTypeBitmask(apnTypesBitmask)
+                .setProtocol(getProtocolIntFromString(
+                        cursor.getString(
+                                cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))))
+                .setRoamingProtocol(getProtocolIntFromString(
+                        cursor.getString(cursor.getColumnIndexOrThrow(
+                                Telephony.Carriers.ROAMING_PROTOCOL))))
+                .setCarrierEnabled(cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.CARRIER_ENABLED)) == 1)
+                .setNetworkTypeBitmask(networkTypeBitmask)
+                .setProfileId(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)))
+                .setModemCognitive(cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.MODEM_PERSIST)) == 1)
+                .setMaxConns(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNECTIONS)))
+                .setWaitTime(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME_RETRY)))
+                .setMaxConnsTime(cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS)))
+                .setMtuV4(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)))
+                .setMtuV6(UNSET_MTU) // TODO: Add corresponding support in telephony provider
+                .setMvnoType(getMvnoTypeIntFromString(
+                        cursor.getString(cursor.getColumnIndexOrThrow(
+                                Telephony.Carriers.MVNO_TYPE))))
+                .setMvnoMatchData(cursor.getString(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.MVNO_MATCH_DATA)))
+                .setApnSetId(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)))
+                .setCarrierId(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)))
+                .setSkip464Xlat(cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)))
+                .buildWithoutCheck();
     }
 
     /**
      * @hide
      */
     public static ApnSetting makeApnSetting(ApnSetting apn) {
-        return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
-            apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
-            apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
-            apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
-            apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
-            apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId,
-            apn.mCarrierId, apn.mSkip464Xlat);
-    }
-
-    /**
-     * Creates an ApnSetting object from a string.
-     *
-     * @param data the string to read.
-     *
-     * The string must be in one of two formats (newlines added for clarity,
-     * spaces are optional):
-     *
-     * v1 format:
-     *   <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...],
-     *
-     * v2 format:
-     *   [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *
-     * v3 format:
-     *   [ApnSettingV3] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>
-     *
-     * v4 format:
-     *   [ApnSettingV4] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>
-     *
-     * v5 format:
-     *   [ApnSettingV5] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>
-     *
-     * v6 format:
-     *   [ApnSettingV6] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>
-     *
-     * v7 format:
-     *   [ApnSettingV7] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
-     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
-     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
-     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
-     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>, <skip464xlat>
-     *
-     * Note that the strings generated by {@link #toString()} do not contain the username
-     * and password and thus cannot be read by this method.
-     *
-     * This method may return {@code null} if the input string is invalid.
-     *
-     * @hide
-     */
-    public static ApnSetting fromString(String data) {
-        if (data == null) return null;
-
-        int version;
-        // matches() operates on the whole string, so append .* to the regex.
-        if (data.matches(V7_FORMAT_REGEX + ".*")) {
-            version = 7;
-            data = data.replaceFirst(V7_FORMAT_REGEX, "");
-        } else if (data.matches(V6_FORMAT_REGEX + ".*")) {
-            version = 6;
-            data = data.replaceFirst(V6_FORMAT_REGEX, "");
-        } else if (data.matches(V5_FORMAT_REGEX + ".*")) {
-            version = 5;
-            data = data.replaceFirst(V5_FORMAT_REGEX, "");
-        } else if (data.matches(V4_FORMAT_REGEX + ".*")) {
-            version = 4;
-            data = data.replaceFirst(V4_FORMAT_REGEX, "");
-        } else if (data.matches(V3_FORMAT_REGEX + ".*")) {
-            version = 3;
-            data = data.replaceFirst(V3_FORMAT_REGEX, "");
-        } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
-            version = 2;
-            data = data.replaceFirst(V2_FORMAT_REGEX, "");
-        } else {
-            version = 1;
-        }
-
-        String[] a = data.split("\\s*,\\s*", -1);
-        if (a.length < 14) {
-            return null;
-        }
-
-        int authType;
-        try {
-            authType = Integer.parseInt(a[12]);
-        } catch (NumberFormatException e) {
-            authType = 0;
-        }
-
-        String[] typeArray;
-        String protocol, roamingProtocol;
-        boolean carrierEnabled;
-        int bearerBitmask = 0;
-        int networkTypeBitmask = 0;
-        int profileId = 0;
-        boolean modemCognitive = false;
-        int maxConns = 0;
-        int waitTime = 0;
-        int maxConnsTime = 0;
-        int mtu = UNSET_MTU;
-        String mvnoType = "";
-        String mvnoMatchData = "";
-        int apnSetId = Carriers.NO_APN_SET_ID;
-        int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
-        int skip464xlat = Carriers.SKIP_464XLAT_DEFAULT;
-        if (version == 1) {
-            typeArray = new String[a.length - 13];
-            System.arraycopy(a, 13, typeArray, 0, a.length - 13);
-            protocol = PROTOCOL_INT_MAP.get(PROTOCOL_IP);
-            roamingProtocol = PROTOCOL_INT_MAP.get(PROTOCOL_IP);
-            carrierEnabled = true;
-        } else {
-            if (a.length < 18) {
-                return null;
-            }
-            typeArray = a[13].split("\\s*\\|\\s*");
-            protocol = a[14];
-            roamingProtocol = a[15];
-            carrierEnabled = Boolean.parseBoolean(a[16]);
-
-            bearerBitmask = ServiceState.getBitmaskFromString(a[17]);
-
-            if (a.length > 22) {
-                modemCognitive = Boolean.parseBoolean(a[19]);
-                try {
-                    profileId = Integer.parseInt(a[18]);
-                    maxConns = Integer.parseInt(a[20]);
-                    waitTime = Integer.parseInt(a[21]);
-                    maxConnsTime = Integer.parseInt(a[22]);
-                } catch (NumberFormatException e) {
-                }
-            }
-            if (a.length > 23) {
-                try {
-                    mtu = Integer.parseInt(a[23]);
-                } catch (NumberFormatException e) {
-                }
-            }
-            if (a.length > 25) {
-                mvnoType = a[24];
-                mvnoMatchData = a[25];
-            }
-            if (a.length > 26) {
-                networkTypeBitmask = ServiceState.getBitmaskFromString(a[26]);
-            }
-            if (a.length > 27) {
-                apnSetId = Integer.parseInt(a[27]);
-            }
-            if (a.length > 28) {
-                carrierId = Integer.parseInt(a[28]);
-            }
-            if (a.length > 29) {
-                try {
-                    skip464xlat = Integer.parseInt(a[29]);
-                } catch (NumberFormatException e) {
-                }
-            }
-        }
-
-        // If both bearerBitmask and networkTypeBitmask were specified, bearerBitmask would be
-        // ignored.
-        if (networkTypeBitmask == 0) {
-            networkTypeBitmask =
-                ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
-        }
-        return makeApnSetting(-1, a[10] + a[11], a[0], a[1], a[2],
-            portFromString(a[3]), UriFromString(a[7]), a[8],
-            portFromString(a[9]), a[4], a[5], authType,
-            getApnTypesBitmaskFromString(TextUtils.join(",", typeArray)),
-            getProtocolIntFromString(protocol), getProtocolIntFromString(roamingProtocol),
-            carrierEnabled, networkTypeBitmask, profileId, modemCognitive, maxConns, waitTime,
-            maxConnsTime, mtu, getMvnoTypeIntFromString(mvnoType), mvnoMatchData, apnSetId,
-            carrierId, skip464xlat);
-    }
-
-    /**
-     * Creates an array of ApnSetting objects from a string.
-     *
-     * @param data the string to read.
-     *
-     * Builds on top of the same format used by fromString, but allows for multiple entries
-     * separated by ";".
-     *
-     * @hide
-     */
-    public static List<ApnSetting> arrayFromString(String data) {
-        List<ApnSetting> retVal = new ArrayList<ApnSetting>();
-        if (TextUtils.isEmpty(data)) {
-            return retVal;
-        }
-        String[] apnStrings = data.split("\\s*;\\s*");
-        for (String apnString : apnStrings) {
-            ApnSetting apn = fromString(apnString);
-            if (apn != null) {
-                retVal.add(apn);
-            }
-        }
-        return retVal;
+        return new Builder()
+                .setId(apn.mId)
+                .setOperatorNumeric(apn.mOperatorNumeric)
+                .setEntryName(apn.mEntryName)
+                .setApnName(apn.mApnName)
+                .setProxyAddress(apn.mProxyAddress)
+                .setProxyPort(apn.mProxyPort)
+                .setMmsc(apn.mMmsc)
+                .setMmsProxyAddress(apn.mMmsProxyAddress)
+                .setMmsProxyPort(apn.mMmsProxyPort)
+                .setUser(apn.mUser)
+                .setPassword(apn.mPassword)
+                .setAuthType(apn.mAuthType)
+                .setApnTypeBitmask(apn.mApnTypeBitmask)
+                .setProtocol(apn.mProtocol)
+                .setRoamingProtocol(apn.mRoamingProtocol)
+                .setCarrierEnabled(apn.mCarrierEnabled)
+                .setNetworkTypeBitmask(apn.mNetworkTypeBitmask)
+                .setProfileId(apn.mProfileId)
+                .setModemCognitive(apn.mPersistent)
+                .setMaxConns(apn.mMaxConns)
+                .setWaitTime(apn.mWaitTime)
+                .setMaxConnsTime(apn.mMaxConnsTime)
+                .setMtuV4(apn.mMtuV4)
+                .setMtuV6(apn.mMtuV6)
+                .setMvnoType(apn.mMvnoType)
+                .setMvnoMatchData(apn.mMvnoMatchData)
+                .setApnSetId(apn.mApnSetId)
+                .setCarrierId(apn.mCarrierId)
+                .setSkip464Xlat(apn.mSkip464Xlat)
+                .buildWithoutCheck();
     }
 
     /**
@@ -1251,7 +1042,7 @@
      */
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("[ApnSettingV7] ")
+        sb.append("[ApnSetting] ")
                 .append(mEntryName)
                 .append(", ").append(mId)
                 .append(", ").append(mOperatorNumeric)
@@ -1272,7 +1063,8 @@
         sb.append(", ").append(mMaxConns);
         sb.append(", ").append(mWaitTime);
         sb.append(", ").append(mMaxConnsTime);
-        sb.append(", ").append(mMtu);
+        sb.append(", ").append(mMtuV4);
+        sb.append(", ").append(mMtuV6);
         sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType));
         sb.append(", ").append(mMvnoMatchData);
         sb.append(", ").append(mPermanentFailed);
@@ -1343,9 +1135,9 @@
     public int hashCode() {
         return Objects.hash(mApnName, mProxyAddress, mProxyPort, mMmsc, mMmsProxyAddress,
                 mMmsProxyPort, mUser, mPassword, mAuthType, mApnTypeBitmask, mId, mOperatorNumeric,
-                mProtocol, mRoamingProtocol, mMtu, mCarrierEnabled, mNetworkTypeBitmask, mProfileId,
-                mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType, mMvnoMatchData,
-                mApnSetId, mCarrierId, mSkip464Xlat);
+                mProtocol, mRoamingProtocol, mMtuV4, mMtuV6, mCarrierEnabled, mNetworkTypeBitmask,
+                mProfileId, mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType,
+                mMvnoMatchData, mApnSetId, mCarrierId, mSkip464Xlat);
     }
 
     @Override
@@ -1357,33 +1149,34 @@
         ApnSetting other = (ApnSetting) o;
 
         return mEntryName.equals(other.mEntryName)
-            && Objects.equals(mId, other.mId)
-            && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
-            && Objects.equals(mApnName, other.mApnName)
-            && Objects.equals(mProxyAddress, other.mProxyAddress)
-            && Objects.equals(mMmsc, other.mMmsc)
-            && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
-            && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-            && Objects.equals(mProxyPort, other.mProxyPort)
-            && Objects.equals(mUser, other.mUser)
-            && Objects.equals(mPassword, other.mPassword)
-            && Objects.equals(mAuthType, other.mAuthType)
-            && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-            && Objects.equals(mProtocol, other.mProtocol)
-            && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
-            && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
-            && Objects.equals(mProfileId, other.mProfileId)
-            && Objects.equals(mPersistent, other.mPersistent)
-            && Objects.equals(mMaxConns, other.mMaxConns)
-            && Objects.equals(mWaitTime, other.mWaitTime)
-            && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
-            && Objects.equals(mMtu, other.mMtu)
-            && Objects.equals(mMvnoType, other.mMvnoType)
-            && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
-            && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
-            && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId)
-            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+                && Objects.equals(mId, other.mId)
+                && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+                && Objects.equals(mApnName, other.mApnName)
+                && Objects.equals(mProxyAddress, other.mProxyAddress)
+                && Objects.equals(mMmsc, other.mMmsc)
+                && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+                && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+                && Objects.equals(mProxyPort, other.mProxyPort)
+                && Objects.equals(mUser, other.mUser)
+                && Objects.equals(mPassword, other.mPassword)
+                && Objects.equals(mAuthType, other.mAuthType)
+                && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+                && Objects.equals(mProtocol, other.mProtocol)
+                && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+                && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+                && Objects.equals(mProfileId, other.mProfileId)
+                && Objects.equals(mPersistent, other.mPersistent)
+                && Objects.equals(mMaxConns, other.mMaxConns)
+                && Objects.equals(mWaitTime, other.mWaitTime)
+                && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+                && Objects.equals(mMtuV4, other.mMtuV4)
+                && Objects.equals(mMtuV6, other.mMtuV6)
+                && Objects.equals(mMvnoType, other.mMvnoType)
+                && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+                && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+                && Objects.equals(mApnSetId, other.mApnSetId)
+                && Objects.equals(mCarrierId, other.mCarrierId)
+                && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     /**
@@ -1406,31 +1199,32 @@
         ApnSetting other = (ApnSetting) o;
 
         return mEntryName.equals(other.mEntryName)
-            && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
-            && Objects.equals(mApnName, other.mApnName)
-            && Objects.equals(mProxyAddress, other.mProxyAddress)
-            && Objects.equals(mMmsc, other.mMmsc)
-            && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
-            && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-            && Objects.equals(mProxyPort, other.mProxyPort)
-            && Objects.equals(mUser, other.mUser)
-            && Objects.equals(mPassword, other.mPassword)
-            && Objects.equals(mAuthType, other.mAuthType)
-            && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-            && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
-            && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
-            && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
-            && Objects.equals(mProfileId, other.mProfileId)
-            && Objects.equals(mPersistent, other.mPersistent)
-            && Objects.equals(mMaxConns, other.mMaxConns)
-            && Objects.equals(mWaitTime, other.mWaitTime)
-            && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
-            && Objects.equals(mMtu, other.mMtu)
-            && Objects.equals(mMvnoType, other.mMvnoType)
-            && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
-            && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId)
-            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+                && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+                && Objects.equals(mApnName, other.mApnName)
+                && Objects.equals(mProxyAddress, other.mProxyAddress)
+                && Objects.equals(mMmsc, other.mMmsc)
+                && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+                && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+                && Objects.equals(mProxyPort, other.mProxyPort)
+                && Objects.equals(mUser, other.mUser)
+                && Objects.equals(mPassword, other.mPassword)
+                && Objects.equals(mAuthType, other.mAuthType)
+                && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+                && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
+                && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+                && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+                && Objects.equals(mProfileId, other.mProfileId)
+                && Objects.equals(mPersistent, other.mPersistent)
+                && Objects.equals(mMaxConns, other.mMaxConns)
+                && Objects.equals(mWaitTime, other.mWaitTime)
+                && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+                && Objects.equals(mMtuV4, other.mMtuV4)
+                && Objects.equals(mMtuV6, other.mMtuV6)
+                && Objects.equals(mMvnoType, other.mMvnoType)
+                && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+                && Objects.equals(mApnSetId, other.mApnSetId)
+                && Objects.equals(mCarrierId, other.mCarrierId)
+                && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     /**
@@ -1732,7 +1526,7 @@
         dest.writeString(mApnName);
         dest.writeString(mProxyAddress);
         dest.writeInt(mProxyPort);
-        dest.writeValue(mMmsc);
+        dest.writeParcelable(mMmsc, flags);
         dest.writeString(mMmsProxyAddress);
         dest.writeInt(mMmsProxyPort);
         dest.writeString(mUser);
@@ -1742,40 +1536,53 @@
         dest.writeInt(mProtocol);
         dest.writeInt(mRoamingProtocol);
         dest.writeBoolean(mCarrierEnabled);
-        dest.writeInt(mMvnoType);
         dest.writeInt(mNetworkTypeBitmask);
+        dest.writeInt(mProfileId);
+        dest.writeBoolean(mPersistent);
+        dest.writeInt(mMaxConns);
+        dest.writeInt(mWaitTime);
+        dest.writeInt(mMaxConnsTime);
+        dest.writeInt(mMtuV4);
+        dest.writeInt(mMtuV6);
+        dest.writeInt(mMvnoType);
+        dest.writeString(mMvnoMatchData);
         dest.writeInt(mApnSetId);
         dest.writeInt(mCarrierId);
         dest.writeInt(mSkip464Xlat);
     }
 
     private static ApnSetting readFromParcel(Parcel in) {
-        final int id = in.readInt();
-        final String operatorNumeric = in.readString();
-        final String entryName = in.readString();
-        final String apnName = in.readString();
-        final String proxy = in.readString();
-        final int port = in.readInt();
-        final Uri mmsc = (Uri) in.readValue(Uri.class.getClassLoader());
-        final String mmsProxy = in.readString();
-        final int mmsPort = in.readInt();
-        final String user = in.readString();
-        final String password = in.readString();
-        final int authType = in.readInt();
-        final int apnTypesBitmask = in.readInt();
-        final int protocol = in.readInt();
-        final int roamingProtocol = in.readInt();
-        final boolean carrierEnabled = in.readBoolean();
-        final int mvnoType = in.readInt();
-        final int networkTypeBitmask = in.readInt();
-        final int apnSetId = in.readInt();
-        final int carrierId = in.readInt();
-        final int skip464xlat = in.readInt();
-
-        return makeApnSetting(id, operatorNumeric, entryName, apnName,
-                proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
-                protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
-                0, 0, 0, 0, mvnoType, null, apnSetId, carrierId, skip464xlat);
+        return new Builder()
+                .setId(in.readInt())
+                .setOperatorNumeric(in.readString())
+                .setEntryName(in.readString())
+                .setApnName(in.readString())
+                .setProxyAddress(in.readString())
+                .setProxyPort(in.readInt())
+                .setMmsc(in.readParcelable(Uri.class.getClassLoader()))
+                .setMmsProxyAddress(in.readString())
+                .setMmsProxyPort(in.readInt())
+                .setUser(in.readString())
+                .setPassword(in.readString())
+                .setAuthType(in.readInt())
+                .setApnTypeBitmask(in.readInt())
+                .setProtocol(in.readInt())
+                .setRoamingProtocol(in.readInt())
+                .setCarrierEnabled(in.readBoolean())
+                .setNetworkTypeBitmask(in.readInt())
+                .setProfileId(in.readInt())
+                .setModemCognitive(in.readBoolean())
+                .setMaxConns(in.readInt())
+                .setWaitTime(in.readInt())
+                .setMaxConnsTime(in.readInt())
+                .setMtuV4(in.readInt())
+                .setMtuV6(in.readInt())
+                .setMvnoType(in.readInt())
+                .setMvnoMatchData(in.readString())
+                .setApnSetId(in.readInt())
+                .setCarrierId(in.readInt())
+                .setSkip464Xlat(in.readInt())
+                .buildWithoutCheck();
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<ApnSetting> CREATOR =
@@ -1834,13 +1641,14 @@
         private int mMmsProxyPort = UNSPECIFIED_INT;
         private String mUser;
         private String mPassword;
-        private int mAuthType;
+        private int mAuthType = AUTH_TYPE_UNKNOWN;
         private int mApnTypeBitmask;
         private int mId;
         private String mOperatorNumeric;
         private int mProtocol = UNSPECIFIED_INT;
         private int mRoamingProtocol = UNSPECIFIED_INT;
-        private int mMtu;
+        private int mMtuV4;
+        private int mMtuV6;
         private int mNetworkTypeBitmask;
         private boolean mCarrierEnabled;
         private int mProfileId;
@@ -1863,20 +1671,34 @@
          * Sets the unique database id for this entry.
          *
          * @param id the unique database id to set for this entry
+         * @hide
          */
-        private Builder setId(int id) {
+        public Builder setId(int id) {
             this.mId = id;
             return this;
         }
 
         /**
-         * Set the MTU size of the mobile interface to which the APN connected.
+         * Set the MTU size of the IPv4 mobile interface to which the APN connected. Note this value
+         * is used only if MTU size is not provided in {@link DataCallResponse}.
          *
-         * @param mtu the MTU size to set for the APN
+         * @param mtuV4 the MTU size to set for the APN
          * @hide
          */
-        public Builder setMtu(int mtu) {
-            this.mMtu = mtu;
+        public Builder setMtuV4(int mtuV4) {
+            this.mMtuV4 = mtuV4;
+            return this;
+        }
+
+        /**
+         * Set the MTU size of the IPv6 mobile interface to which the APN connected. Note this value
+         * is used only if MTU size is not provided in {@link DataCallResponse}.
+         *
+         * @param mtuV6 the MTU size to set for the APN
+         * @hide
+         */
+        public Builder setMtuV6(int mtuV6) {
+            this.mMtuV6 = mtuV6;
             return this;
         }
 
@@ -2237,7 +2059,8 @@
                     | TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
                     | TYPE_XCAP | TYPE_VSIM | TYPE_BIP | TYPE_ENTERPRISE)) == 0
                 || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
-                return null;
+                throw new IllegalArgumentException("mApName=" + mApnName + ", mEntryName="
+                        + mEntryName + ", mApnTypeBitmask=" + mApnTypeBitmask);
             }
             return new ApnSetting(this);
         }
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index f2a1249..93903d2 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -25,13 +25,11 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.ApnType;
+import android.telephony.TelephonyManager;
 import android.telephony.TelephonyManager.NetworkTypeBitMask;
 import android.telephony.data.ApnSetting.AuthType;
 import android.text.TextUtils;
 
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.util.TelephonyUtils;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
@@ -62,152 +60,141 @@
     /** 3GPP2 type data profile */
     public static final int TYPE_3GPP2 = 2;
 
-    private final int mProfileId;
+    private final @Type int mType;
 
-    private final String mApn;
+    private final @Nullable ApnSetting mApnSetting;
 
-    @ProtocolType
-    private final int mProtocolType;
-
-    @AuthType
-    private final int mAuthType;
-
-    private final String mUserName;
-
-    private final String mPassword;
-
-    @Type
-    private final int mType;
-
-    private final int mMaxConnectionsTime;
-
-    private final int mMaxConnections;
-
-    private final int mWaitTime;
-
-    private final boolean mEnabled;
-
-    @ApnType
-    private final int mSupportedApnTypesBitmask;
-
-    @ProtocolType
-    private final int mRoamingProtocolType;
-
-    @NetworkTypeBitMask
-    private final int mBearerBitmask;
-
-    private final int mMtuV4;
-
-    private final int mMtuV6;
-
-    private final boolean mPersistent;
+    private final @Nullable TrafficDescriptor mTrafficDescriptor;
 
     private final boolean mPreferred;
 
-    /** @hide */
-    private DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType,
-            String userName, String password, int type, int maxConnectionsTime,
-            int maxConnections, int waitTime, boolean enabled,
-            @ApnType int supportedApnTypesBitmask, @ProtocolType int roamingProtocolType,
-            @NetworkTypeBitMask int bearerBitmask, int mtuV4, int mtuV6, boolean persistent,
-            boolean preferred) {
-        this.mProfileId = profileId;
-        this.mApn = apn;
-        this.mProtocolType = protocolType;
-        if (authType == -1) {
-            authType = TextUtils.isEmpty(userName) ? RILConstants.SETUP_DATA_AUTH_NONE
-                    : RILConstants.SETUP_DATA_AUTH_PAP_CHAP;
+    private DataProfile(@NonNull Builder builder) {
+        mApnSetting = builder.mApnSetting;
+        mTrafficDescriptor = builder.mTrafficDescriptor;
+        mPreferred = builder.mPreferred;
+
+        if (builder.mType != -1) {
+            mType = builder.mType;
+        } else if (mApnSetting != null) {
+            int networkTypes = mApnSetting.getNetworkTypeBitmask();
+
+            if (networkTypes == 0) {
+                mType = DataProfile.TYPE_COMMON;
+            } else if ((networkTypes & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP2)
+                    == networkTypes) {
+                mType = DataProfile.TYPE_3GPP2;
+            } else if ((networkTypes & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP)
+                    == networkTypes) {
+                mType = DataProfile.TYPE_3GPP;
+            } else {
+                mType = DataProfile.TYPE_COMMON;
+            }
+        } else {
+            mType = DataProfile.TYPE_COMMON;
         }
-        this.mAuthType = authType;
-        this.mUserName = userName;
-        this.mPassword = password;
-        this.mType = type;
-        this.mMaxConnectionsTime = maxConnectionsTime;
-        this.mMaxConnections = maxConnections;
-        this.mWaitTime = waitTime;
-        this.mEnabled = enabled;
-        this.mSupportedApnTypesBitmask = supportedApnTypesBitmask;
-        this.mRoamingProtocolType = roamingProtocolType;
-        this.mBearerBitmask = bearerBitmask;
-        this.mMtuV4 = mtuV4;
-        this.mMtuV6 = mtuV6;
-        this.mPersistent = persistent;
-        this.mPreferred = preferred;
     }
 
     private DataProfile(Parcel source) {
-        mProfileId = source.readInt();
-        mApn = source.readString();
-        mProtocolType = source.readInt();
-        mAuthType = source.readInt();
-        mUserName = source.readString();
-        mPassword = source.readString();
         mType = source.readInt();
-        mMaxConnectionsTime = source.readInt();
-        mMaxConnections = source.readInt();
-        mWaitTime = source.readInt();
-        mEnabled = source.readBoolean();
-        mSupportedApnTypesBitmask = source.readInt();
-        mRoamingProtocolType = source.readInt();
-        mBearerBitmask = source.readInt();
-        mMtuV4 = source.readInt();
-        mMtuV6 = source.readInt();
-        mPersistent = source.readBoolean();
+        mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader());
+        mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader());
         mPreferred = source.readBoolean();
     }
 
     /**
      * @return Id of the data profile.
      */
-    public int getProfileId() { return mProfileId; }
+    public int getProfileId() {
+        if (mApnSetting != null) {
+            return mApnSetting.getProfileId();
+        }
+        return 0;
+    }
 
     /**
      * @return The APN (Access Point Name) to establish data connection. This is a string
      * specifically defined by the carrier.
      */
     @NonNull
-    public String getApn() { return mApn; }
+    public String getApn() {
+        if (mApnSetting != null) {
+            return TextUtils.emptyIfNull(mApnSetting.getApnName());
+        }
+        return "";
+    }
 
     /**
      * @return The connection protocol defined in 3GPP TS 27.007 section 10.1.1.
      */
-    public @ProtocolType int getProtocolType() { return mProtocolType; }
+    public @ProtocolType int getProtocolType() {
+        if (mApnSetting != null) {
+            return mApnSetting.getProtocol();
+        }
+        return ApnSetting.PROTOCOL_IP;
+    }
 
     /**
      * @return The authentication protocol used for this PDP context.
      */
-    public @AuthType int getAuthType() { return mAuthType; }
+    public @AuthType int getAuthType() {
+        if (mApnSetting != null) {
+            return mApnSetting.getAuthType();
+        }
+        return ApnSetting.AUTH_TYPE_NONE;
+    }
 
     /**
      * @return The username for APN. Can be null.
      */
     @Nullable
-    public String getUserName() { return mUserName; }
+    public String getUserName() {
+        if (mApnSetting != null) {
+            return mApnSetting.getUser();
+        }
+        return null;
+    }
 
     /**
      * @return The password for APN. Can be null.
      */
     @Nullable
-    public String getPassword() { return mPassword; }
+    public String getPassword() {
+        if (mApnSetting != null) {
+            return mApnSetting.getPassword();
+        }
+        return null;
+    }
 
     /**
      * @return The profile type.
      */
-    public @Type int getType() { return mType; }
+    public @Type int getType() {
+        return mType;
+    }
 
     /**
      * @return The period in seconds to limit the maximum connections.
      *
      * @hide
      */
-    public int getMaxConnectionsTime() { return mMaxConnectionsTime; }
+    public int getMaxConnectionsTime() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMaxConnsTime();
+        }
+        return 0;
+    }
 
     /**
      * @return The maximum connections allowed.
      *
      * @hide
      */
-    public int getMaxConnections() { return mMaxConnections; }
+    public int getMaxConnections() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMaxConns();
+        }
+        return 0;
+    }
 
     /**
      * @return The required wait time in seconds after a successful UE initiated disconnect of a
@@ -216,57 +203,117 @@
      *
      * @hide
      */
-    public int getWaitTime() { return mWaitTime; }
+    public int getWaitTime() {
+        if (mApnSetting != null) {
+            return mApnSetting.getWaitTime();
+        }
+        return 0;
+    }
 
     /**
      * @return True if the profile is enabled.
      */
-    public boolean isEnabled() { return mEnabled; }
+    public boolean isEnabled() {
+        if (mApnSetting != null) {
+            return mApnSetting.isEnabled();
+        }
+        return false;
+    }
 
     /**
      * @return The supported APN types bitmask.
      */
-    public @ApnType int getSupportedApnTypesBitmask() { return mSupportedApnTypesBitmask; }
+    public @ApnType int getSupportedApnTypesBitmask() {
+        if (mApnSetting != null) {
+            return mApnSetting.getApnTypeBitmask();
+        }
+        return ApnSetting.TYPE_NONE;
+    }
 
     /**
      * @return The connection protocol on roaming network defined in 3GPP TS 27.007 section 10.1.1.
      */
-    public @ProtocolType int getRoamingProtocolType() { return mRoamingProtocolType; }
+    public @ProtocolType int getRoamingProtocolType() {
+        if (mApnSetting != null) {
+            return mApnSetting.getRoamingProtocol();
+        }
+        return ApnSetting.PROTOCOL_IP;
+    }
 
     /**
      * @return The bearer bitmask indicating the applicable networks for this data profile.
      */
-    public @NetworkTypeBitMask int getBearerBitmask() { return mBearerBitmask; }
+    public @NetworkTypeBitMask int getBearerBitmask() {
+        if (mApnSetting != null) {
+            return mApnSetting.getNetworkTypeBitmask();
+        }
+        return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
+    }
 
     /**
      * @return The maximum transmission unit (MTU) size in bytes.
      * @deprecated use {@link #getMtuV4} or {@link #getMtuV6} instead.
      */
     @Deprecated
-    public int getMtu() { return mMtuV4; }
+    public int getMtu() {
+        return getMtuV4();
+    }
 
     /**
      * This replaces the deprecated method getMtu.
      * @return The maximum transmission unit (MTU) size in bytes, for IPv4.
      */
-    public int getMtuV4() { return mMtuV4; }
+    public int getMtuV4() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMtuV4();
+        }
+        return 0;
+    }
 
     /**
      * @return The maximum transmission unit (MTU) size in bytes, for IPv6.
      */
-    public int getMtuV6() { return mMtuV6; }
+    public int getMtuV6() {
+        if (mApnSetting != null) {
+            return mApnSetting.getMtuV6();
+        }
+        return 0;
+    }
 
     /**
      * @return {@code true} if modem must persist this data profile.
      */
-    public boolean isPersistent() { return mPersistent; }
+    public boolean isPersistent() {
+        if (mApnSetting != null) {
+            return mApnSetting.isPersistent();
+        }
+        return false;
+    }
 
     /**
      * @return {@code true} if this data profile was used to bring up the last default
      * (i.e internet) data connection successfully, or the one chosen by the user in Settings'
      * APN editor. For one carrier there can be only one profiled preferred.
      */
-    public boolean isPreferred() { return  mPreferred; }
+    public boolean isPreferred() {
+        return mPreferred;
+    }
+
+    /**
+     * @return The APN setting
+     * @hide TODO: Remove before T is released.
+     */
+    public @Nullable ApnSetting getApnSetting() {
+        return mApnSetting;
+    }
+
+    /**
+     * @return The traffic descriptor
+     * @hide TODO: Remove before T is released.
+     */
+    public @Nullable TrafficDescriptor getTrafficDescriptor() {
+        return mTrafficDescriptor;
+    }
 
     @Override
     public int describeContents() {
@@ -276,34 +323,15 @@
     @NonNull
     @Override
     public String toString() {
-        return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType
-                + "/" + (TelephonyUtils.IS_USER ? "***/***/***" :
-                         (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
-                + mMaxConnectionsTime + "/" + mMaxConnections + "/"
-                + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/"
-                + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtuV4 + "/" + mMtuV6 + "/"
-                + mPersistent + "/" + mPreferred;
+        return "DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
+                + mPreferred;
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mProfileId);
-        dest.writeString(mApn);
-        dest.writeInt(mProtocolType);
-        dest.writeInt(mAuthType);
-        dest.writeString(mUserName);
-        dest.writeString(mPassword);
         dest.writeInt(mType);
-        dest.writeInt(mMaxConnectionsTime);
-        dest.writeInt(mMaxConnections);
-        dest.writeInt(mWaitTime);
-        dest.writeBoolean(mEnabled);
-        dest.writeInt(mSupportedApnTypesBitmask);
-        dest.writeInt(mRoamingProtocolType);
-        dest.writeInt(mBearerBitmask);
-        dest.writeInt(mMtuV4);
-        dest.writeInt(mMtuV6);
-        dest.writeBoolean(mPersistent);
+        dest.writeParcelable(mApnSetting, flags);
+        dest.writeParcelable(mTrafficDescriptor, flags);
         dest.writeBoolean(mPreferred);
     }
 
@@ -321,36 +349,18 @@
     };
 
     @Override
-    public boolean equals(@Nullable Object o) {
+    public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         DataProfile that = (DataProfile) o;
-        return mProfileId == that.mProfileId
-                && mProtocolType == that.mProtocolType
-                && mAuthType == that.mAuthType
-                && mType == that.mType
-                && mMaxConnectionsTime == that.mMaxConnectionsTime
-                && mMaxConnections == that.mMaxConnections
-                && mWaitTime == that.mWaitTime
-                && mEnabled == that.mEnabled
-                && mSupportedApnTypesBitmask == that.mSupportedApnTypesBitmask
-                && mRoamingProtocolType == that.mRoamingProtocolType
-                && mBearerBitmask == that.mBearerBitmask
-                && mMtuV4 == that.mMtuV4
-                && mMtuV6 == that.mMtuV6
-                && mPersistent == that.mPersistent
-                && mPreferred == that.mPreferred
-                && Objects.equals(mApn, that.mApn)
-                && Objects.equals(mUserName, that.mUserName)
-                && Objects.equals(mPassword, that.mPassword);
+        return mType == that.mType
+                && Objects.equals(mApnSetting, that.mApnSetting)
+                && Objects.equals(mTrafficDescriptor, that.mTrafficDescriptor);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType,
-                mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
-                mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
-                mPersistent, mPreferred);
+        return Objects.hash(mType, mApnSetting, mTrafficDescriptor);
     }
 
     /**
@@ -383,13 +393,7 @@
         private String mPassword;
 
         @Type
-        private int mType;
-
-        private int mMaxConnectionsTime;
-
-        private int mMaxConnections;
-
-        private int mWaitTime;
+        private int mType = -1;
 
         private boolean mEnabled;
 
@@ -410,6 +414,10 @@
 
         private boolean mPreferred;
 
+        private ApnSetting mApnSetting;
+
+        private TrafficDescriptor mTrafficDescriptor;
+
         /**
          * Default constructor for Builder.
          */
@@ -496,48 +504,6 @@
         }
 
         /**
-         * Set the period in seconds to limit the maximum connections.
-         *
-         * @param maxConnectionsTime The profile type
-         * @return The same instance of the builder.
-         *
-         * @hide
-         */
-        public @NonNull Builder setMaxConnectionsTime(int maxConnectionsTime) {
-            mMaxConnectionsTime = maxConnectionsTime;
-            return this;
-        }
-
-        /**
-         * Set the maximum connections allowed.
-         *
-         * @param maxConnections The maximum connections allowed.
-         * @return The same instance of the builder.
-         *
-         * @hide
-         */
-        public @NonNull Builder setMaxConnections(int maxConnections) {
-            mMaxConnections = maxConnections;
-            return this;
-        }
-
-        /**
-         * Set the period in seconds to limit the maximum connections.
-         *
-         * @param waitTime The required wait time in seconds after a successful UE initiated
-         * disconnect of a given PDN connection before the device can send a new PDN connection
-         * request for that given PDN.
-         *
-         * @return The same instance of the builder.
-         *
-         * @hide
-         */
-        public @NonNull Builder setWaitTime(int waitTime) {
-            mWaitTime = waitTime;
-            return this;
-        }
-
-        /**
          * Enable the data profile
          *
          * @param isEnabled {@code true} to enable the data profile, otherwise disable.
@@ -587,8 +553,9 @@
          *
          * @param mtu The maximum transmission unit (MTU) size in bytes.
          * @return The same instance of the builder.
-         * @deprecated use {@link #setMtuV4} or {@link #setMtuV6} instead.
+         * @deprecated use {@link #setApnSetting(ApnSetting)} instead.
          */
+        @Deprecated
         public @NonNull Builder setMtu(int mtu) {
             mMtuV4 = mMtuV6 = mtu;
             return this;
@@ -631,7 +598,7 @@
         }
 
         /**
-         * Set data profile as persistent/non-persistent
+         * Set data profile as persistent/non-persistent.
          *
          * @param isPersistent {@code true} if this data profile was used to bring up the last
          * default (i.e internet) data connection successfully.
@@ -643,15 +610,63 @@
         }
 
         /**
+         * Set APN setting.
+         *
+         * @param apnSetting APN setting
+         * @return The same instance of the builder
+         *
+         * @hide // TODO: Remove before T is released.
+         */
+        public @NonNull Builder setApnSetting(@NonNull ApnSetting apnSetting) {
+            mApnSetting = apnSetting;
+            return this;
+        }
+
+        /**
+         * Set traffic descriptor.
+         *
+         * @param trafficDescriptor Traffic descriptor
+         * @return The same instance of the builder
+         *
+         * @hide // TODO: Remove before T is released.
+         */
+        public @NonNull Builder setTrafficDescriptor(@NonNull TrafficDescriptor trafficDescriptor) {
+            mTrafficDescriptor = trafficDescriptor;
+            return this;
+        }
+
+        /**
          * Build the DataProfile object
          *
          * @return The data profile object
          */
         public @NonNull DataProfile build() {
-            return new DataProfile(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword,
-                    mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
-                    mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
-                    mPersistent, mPreferred);
+            if (mApnSetting == null && mApn != null) {
+                // This is for backwards compatibility.
+                mApnSetting = new ApnSetting.Builder()
+                        .setEntryName(mApn)
+                        .setApnName(mApn)
+                        .setApnTypeBitmask(mSupportedApnTypesBitmask)
+                        .setAuthType(mAuthType)
+                        .setCarrierEnabled(mEnabled)
+                        .setModemCognitive(mPersistent)
+                        .setMtuV4(mMtuV4)
+                        .setMtuV6(mMtuV6)
+                        .setNetworkTypeBitmask(mBearerBitmask)
+                        .setProfileId(mProfileId)
+                        .setPassword(mPassword)
+                        .setProtocol(mProtocolType)
+                        .setRoamingProtocol(mRoamingProtocolType)
+                        .setUser(mUserName)
+                        .build();
+            }
+
+            if (mApnSetting == null && mTrafficDescriptor == null) {
+                throw new IllegalArgumentException("APN setting and traffic descriptor can't be "
+                        + "both null.");
+            }
+
+            return new DataProfile(this);
         }
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 63732b5..d586a4a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1002,11 +1002,6 @@
      boolean isManualNetworkSelectionAllowed(int subId);
 
     /**
-     * Enable or disable always reporting signal strength changes from radio.
-     */
-     void setAlwaysReportSignalStrength(int subId, boolean isEnable);
-
-    /**
      * Get P-CSCF address from PCO after data connection is established or modified.
      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
      * @param callingPackage The package making the call.
@@ -2229,6 +2224,20 @@
     List<String> getEquivalentHomePlmns(int subId, String callingPackage, String callingFeatureId);
 
     /**
+     * Enable or disable Voice over NR (VoNR)
+     * @param subId the subscription ID that this action applies to.
+     * @param enabled enable or disable VoNR.
+     * @return operation result.
+     */
+    int setVoNrEnabled(int subId, boolean enabled);
+
+    /**
+     * Is voice over NR enabled
+     * @return true if VoNR is enabled else false
+     */
+    boolean isVoNrEnabled(int subId);
+
+    /**
      * Enable/Disable E-UTRA-NR Dual Connectivity
      * @return operation result. See TelephonyManager.EnableNrDualConnectivityResult for
      * details
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index b73f827..866fd2c 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -528,6 +528,8 @@
     int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP = 222;
     int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP = 223;
     int RIL_REQUEST_GET_SLICING_CONFIG = 224;
+    int RIL_REQUEST_ENABLE_VONR = 225;
+    int RIL_REQUEST_IS_VONR_ENABLED = 226;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/DynamicCodeLoggerIntegrationTests/OWNERS b/tests/DynamicCodeLoggerIntegrationTests/OWNERS
new file mode 100644
index 0000000..d9eb141
--- /dev/null
+++ b/tests/DynamicCodeLoggerIntegrationTests/OWNERS
@@ -0,0 +1 @@
+file:/services/core/java/com/android/server/pm/dex/OWNERS
diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS
index b556101..c1221e3 100644
--- a/tests/FlickerTests/OWNERS
+++ b/tests/FlickerTests/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 909476
 include /services/core/java/com/android/server/wm/OWNERS
-natanieljr@google.com
\ No newline at end of file
+natanieljr@google.com
+pablogamito@google.com
diff --git a/tests/SharedLibraryLoadingTest/Android.bp b/tests/SharedLibraryLoadingTest/Android.bp
new file mode 100644
index 0000000..088278d
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/Android.bp
@@ -0,0 +1,37 @@
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_test_host {
+    name: "SharedLibraryLoadingTests",
+    libs: [
+        "tradefed",
+        "junit",
+    ],
+    test_suites: ["general-tests"],
+    data: [
+        ":SharedLibraryLoadingTests_StandardSharedLibrary",
+        ":SharedLibraryLoadingTests_SharedLibraryLoadedAfter",
+        ":SharedLibraryLoadingTests_SharedLibraryClientTests",
+        ":SharedLibraryLoadingTests_Overlay",
+    ],
+}
diff --git a/tests/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml
new file mode 100644
index 0000000..947453d
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<configuration description="Host-driven test module config for SharedLibraryHostTests">
+    <option name="test-tag" value="SharedLibraryLoadingTests" />
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="false" />
+        <option name="remount-system" value="true" />
+        <option name="push"
+                value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" />
+        <option name="push"
+                value="SharedLibraryLoadingTests_SharedLibraryLoadedAfter.apk->/product/app/SharedLibraryLoadingTests_SharedLibraryLoadedAfter.apk" />
+        <option name="push"
+                value="SharedLibraryLoadingTests_Overlay.apk->/product/overlay/SharedLibraryLoadingTests_Overlay.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="SharedLibraryLoadingTests_SharedLibraryClientTests.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.sharedlibloadingtest.client" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/OWNERS b/tests/SharedLibraryLoadingTest/OWNERS
new file mode 100644
index 0000000..d7b4569
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/OWNERS
@@ -0,0 +1,2 @@
+stenning@google.com
+
diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp
new file mode 100644
index 0000000..b2f4e89
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "SharedLibraryLoadingTests_Overlay",
+    platform_apis: true,
+    certificate: "platform",
+    aaptflags: ["--no-resource-removal"],
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml
new file mode 100644
index 0000000..ae2784c
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.sharedlibloadingtest.overlay">
+    <application android:hasCode="false" />
+    <overlay android:targetPackage="android"
+             android:isStatic="true"
+             android:priority="1"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml b/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml
new file mode 100644
index 0000000..15da3db
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/Overlay/res/values/config.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2020 Google Inc.
+ *
+ * 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.
+ */
+-->
+<resources>
+    <string-array name="config_sharedLibrariesLoadedAfterApp" translatable="false">
+        <item>com.android.sharedlibloadingtest.shared_library_after</item>
+    </string-array>
+</resources>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp
new file mode 100644
index 0000000..0d20497
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "SharedLibraryLoadingTests_SharedLibraryClientTests",
+    srcs: ["**/*.java"],
+    resource_dirs: ["res"],
+    libs: [
+        "SharedLibraryLoadingTests_StandardSharedLibrary",
+        "SharedLibraryLoadingTests_SharedLibraryLoadedAfter",
+        "android.test.base",
+    ],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "androidx.test.core",
+        "testng",
+    ],
+    platform_apis: true,
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml
new file mode 100644
index 0000000..e3a9b9b
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.sharedlibloadingtest.client">
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="com.android.sharedlibloadingtest.shared_library"/>
+        <uses-library android:name="com.android.sharedlibloadingtest.shared_library_after"/>
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.sharedlibloadingtest.client"  />
+</manifest>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml
new file mode 100644
index 0000000..5e0544e
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/res/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<resources>
+    <string name="identical_resource_key">client value</string>
+</resources>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java
new file mode 100644
index 0000000..e48fb83
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/ClientClass.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+public class ClientClass {
+    @Override
+    public String toString() {
+        return "Client Code";
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java
new file mode 100644
index 0000000..4c77155
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassA.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassA {
+    @Override
+    public String toString() {
+        return "Client's Version";
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java
new file mode 100644
index 0000000..86aa6a1
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/DuplicateClassB.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassB {
+    @Override
+    public String toString() {
+        return "Client's Version B";
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java
new file mode 100644
index 0000000..43bcb1a
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryClientTests/src/com/android/sharedlibloadingtest/client/SharedLibraryLoadingOrderTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest.client;
+
+import static org.testng.Assert.assertEquals;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.util.Preconditions;
+import com.android.sharedlibloadingtest.ClientClass;
+import com.android.sharedlibloadingtest.DuplicateClassA;
+import com.android.sharedlibloadingtest.DuplicateClassB;
+import com.android.sharedlibloadingtest.SharedClassAfter;
+import com.android.sharedlibloadingtest.StdSharedClass;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.HashSet;
+
+@RunWith(AndroidJUnit4.class)
+public class SharedLibraryLoadingOrderTest {
+
+    @Test
+    public void testLoadingOfStdShareLibsShouldBeFirst() {
+        Preconditions.checkArgument(!getLibsLoadedAfter()
+                .contains("com.android.sharedlibloadingtest.shared_library"));
+        DuplicateClassA clazz = new DuplicateClassA();
+        assertEquals(clazz.toString(), "Standard Shared Lib's Version");
+
+        StdSharedClass stdSharedClass = new StdSharedClass();
+        assertEquals(stdSharedClass.toString(), "Nothing Special Lib");
+
+        ClientClass clientCode = new ClientClass();
+        assertEquals(clientCode.toString(), "Client Code");
+    }
+
+    @Test
+    public void testLoadingOfShareLibsIsAfter() {
+        Preconditions.checkArgument(getLibsLoadedAfter()
+                .contains("com.android.sharedlibloadingtest.shared_library_after"));
+        DuplicateClassB clazz = new DuplicateClassB();
+        assertEquals(clazz.toString(), "Client's Version B");
+
+        SharedClassAfter stdSharedClass = new SharedClassAfter();
+        assertEquals(stdSharedClass.toString(), "Also Nothing Special");
+
+        ClientClass clientCode = new ClientClass();
+        assertEquals(clientCode.toString(), "Client Code");
+    }
+
+    @Test
+    public void testLoadingOfResource() {
+        // aapt compiler gives each lib their own namespace so this test just confirming
+        // the resources can be loaded from the same context object
+        Context context = ApplicationProvider.getApplicationContext();
+        String clientString = context.getResources().getString(R.string.identical_resource_key);
+        assertEquals(clientString, "client value");
+        assertEquals(StdSharedClass.getResString(context), "std lib value");
+        assertEquals(SharedClassAfter.getResString(context), "loaded after value");
+
+    }
+
+    private HashSet<String> getLibsLoadedAfter() {
+        Resources systemR = Resources.getSystem();
+        HashSet<String> libsToLoadAfter = new HashSet<>();
+        Collections.addAll(libsToLoadAfter, systemR.getStringArray(
+                com.android.internal.R.array.config_sharedLibrariesLoadedAfterApp));
+        return libsToLoadAfter;
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp
new file mode 100644
index 0000000..db9b3ed
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "SharedLibraryLoadingTests_SharedLibraryLoadedAfter",
+    srcs: ["**/*.java"],
+    resource_dirs: ["res"],
+    sdk_version: "current",
+    aaptflags: ["--shared-lib"],
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml
new file mode 100644
index 0000000..efedfcf
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.sharedlibloadingtest.shared_library_after">
+    <application>
+        <library android:name="com.android.sharedlibloadingtest.shared_library_after" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml
new file mode 100644
index 0000000..4525944
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/res/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<resources>
+    <string name="identical_resource_key">loaded after value</string>
+</resources>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java
new file mode 100644
index 0000000..1e1f5aa
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/DuplicateClassB.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassB {
+    @Override
+    public String toString() {
+        return "Loaded After Shared Lib's Version";
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java
new file mode 100644
index 0000000..9e5b40f
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/SharedLibraryLoadedAfter/src/com/android/sharedlibloadingtest/SharedClassAfter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+import android.content.Context;
+
+import com.android.sharedlibloadingtest.shared_library_after.R;
+
+public class SharedClassAfter {
+    @Override
+    public String toString() {
+        return "Also Nothing Special";
+    }
+
+    public static String getResString(Context context) {
+        return context.getResources().getString(R.string.identical_resource_key);
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp
new file mode 100644
index 0000000..50456b0
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "SharedLibraryLoadingTests_StandardSharedLibrary",
+    srcs: ["**/*.java"],
+    resource_dirs: ["res"],
+    sdk_version: "current",
+    aaptflags: ["--shared-lib"],
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml
new file mode 100644
index 0000000..f1a079f
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.sharedlibloadingtest.shared_library">
+    <application>
+        <library android:name="com.android.sharedlibloadingtest.shared_library" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml
new file mode 100644
index 0000000..941351a
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/res/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<resources>
+    <string name="identical_resource_key">std lib value</string>
+</resources>
\ No newline at end of file
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java
new file mode 100644
index 0000000..a3874aa
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/DuplicateClassA.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+public class DuplicateClassA {
+    @Override
+    public String toString() {
+        return "Standard Shared Lib's Version";
+    }
+}
diff --git a/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java
new file mode 100644
index 0000000..429d65c
--- /dev/null
+++ b/tests/SharedLibraryLoadingTest/test-apps/StandardSharedLibrary/src/com/android/sharedlibloadingtest/StdSharedClass.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedlibloadingtest;
+
+import android.content.Context;
+
+import com.android.sharedlibloadingtest.shared_library.R;
+
+public class StdSharedClass {
+    @Override
+    public String toString() {
+        return "Nothing Special Lib";
+    }
+
+    public static String getResString(Context context) {
+        return context.getResources().getString(R.string.identical_resource_key);
+    }
+}
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 7a564fc..a5852b5 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -31,6 +31,7 @@
     ],
     test_suites: ["general-tests"],
     java_resources: [
+        ":apex.apexd_test_classpath",
         ":com.android.apex.apkrollback.test_v2",
         ":StagedInstallTestApexV2",
         ":StagedInstallTestApexV2_WrongSha",
@@ -54,6 +55,7 @@
         "cts-install-lib-host",
     ],
     data: [
+        ":apex.apexd_test",
         ":com.android.apex.apkrollback.test_v1",
         ":StagedInstallTestApexV2",
         ":StagedInstallTestApexV2_WrongSha",
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index c610641..f0ab63e 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -74,6 +74,11 @@
             "ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
             "com.android.apex.cts.shim.v2.apex");
 
+    private static final String TEST_APEX_PACKAGE_NAME = "com.android.apex.test_package";
+    private static final TestApp TEST_APEX_CLASSPATH = new TestApp("TestApex",
+            TEST_APEX_PACKAGE_NAME, 1, /*isApex=*/true,
+            "apex.apexd_test_classpath.apex");
+
     private File mTestStateFile = new File(
             InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
             "stagedinstall_state");
@@ -439,11 +444,13 @@
         StagedApexInfo result = getPackageManagerNative().getStagedApexInfo("not found");
         assertThat(result).isNull();
         // Stage an apex
-        int sessionId = Install.single(APEX_V2).setStaged().commit();
+        int sessionId = Install.single(TEST_APEX_CLASSPATH).setStaged().commit();
         waitForSessionReady(sessionId);
         // Query proper module name
-        result = getPackageManagerNative().getStagedApexInfo(SHIM_APEX_PACKAGE_NAME);
-        assertThat(result.moduleName).isEqualTo(SHIM_APEX_PACKAGE_NAME);
+        result = getPackageManagerNative().getStagedApexInfo(TEST_APEX_PACKAGE_NAME);
+        assertThat(result.moduleName).isEqualTo(TEST_APEX_PACKAGE_NAME);
+        assertThat(result.hasBootClassPathJars).isTrue();
+        assertThat(result.hasSystemServerClassPathJars).isTrue();
         InstallUtils.openPackageInstallerSession(sessionId).abandon();
     }
 
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 3102103..cd00783 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -61,6 +61,7 @@
     private static final String APEX_WRONG_SHA = "com.android.apex.cts.shim.v2_wrong_sha.apex";
     private static final String APK_A = "TestAppAv1.apk";
     private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
+    private static final String APEXD_TEST_APEX = "apex.apexd_test.apex";
 
     private static final String TEST_VENDOR_APEX_ALLOW_LIST =
             "/vendor/etc/sysconfig/test-vendor-apex-allow-list.xml";
@@ -480,16 +481,29 @@
 
     @Test
     public void testGetStagedModuleNames() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
         runPhase("testGetStagedModuleNames");
     }
 
     @Test
+    @LargeTest
     public void testGetStagedApexInfo() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
+        pushTestApex(APEXD_TEST_APEX);
+        getDevice().reboot();
+
         runPhase("testGetStagedApexInfo");
     }
 
     @Test
     public void testStagedApexObserver() throws Exception {
+        assumeTrue("Device does not support updating APEX",
+                mHostUtils.isApexUpdateSupported());
+
         runPhase("testStagedApexObserver");
     }
 
diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
index f385113..3b201f9 100644
--- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
@@ -135,11 +135,12 @@
     }
 
     @Test
-    public void testEncodeRecodeParamsWithIkeOptions() throws Exception {
+    public void testEncodeDecodeParamsWithIkeOptions() throws Exception {
         final IkeSessionParams params =
                 createBuilderMinimum()
                         .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
                         .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
+                        .addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT)
                         .build();
         verifyPersistableBundleEncodeDecodeIsLossless(params);
     }
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index c9a8947a..937f9dc 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -297,8 +297,6 @@
                         any(),
                         any());
         verify(mNetworkAgent).register();
-        verify(mNetworkAgent)
-                .setUnderlyingNetworks(eq(singletonList(TEST_UNDERLYING_NETWORK_RECORD_1.network)));
         verify(mNetworkAgent).markConnected();
 
         verify(mIpSecSvc)
@@ -313,6 +311,7 @@
         final NetworkCapabilities nc = ncCaptor.getValue();
         assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+        assertEquals(List.of(TEST_UNDERLYING_NETWORK_RECORD_1.network), nc.getUnderlyingNetworks());
         for (int cap : mConfig.getAllExposedCapabilities()) {
             assertTrue(nc.hasCapability(cap));
         }
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index a700171..2b0037e 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.vcn;
 
+import static android.net.IpSecManager.IpSecTunnelInterface;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -24,6 +25,8 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
+import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
+import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
 import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
 import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
 
@@ -36,8 +39,11 @@
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.net.IpSecManager;
+import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
@@ -59,8 +65,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.InetAddress;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -70,6 +79,8 @@
 public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
     private static final int TEST_UID = Process.myUid() + 1;
 
+    private static final String LOOPBACK_IFACE = "lo";
+
     private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
     private static final int TEST_SIM_SLOT_INDEX = 1;
     private static final int TEST_SUBSCRIPTION_ID_1 = 2;
@@ -77,6 +88,12 @@
     private static final int TEST_SUBSCRIPTION_ID_2 = 3;
     private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
     private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+    private static final String TEST_TCP_BUFFER_SIZES = "1,2,3,4,5,6";
+    private static final int TEST_MTU = 1300;
+    private static final int TEST_MTU_DELTA = 64;
+    private static final List<LinkAddress> TEST_INTERNAL_ADDRESSES =
+            Arrays.asList(new LinkAddress(DUMMY_ADDR, 16));
+    private static final List<InetAddress> TEST_DNS_ADDRESSES = Arrays.asList(DUMMY_ADDR);
 
     private static final int TEST_UPSTREAM_BANDWIDTH = 1234;
     private static final int TEST_DOWNSTREAM_BANDWIDTH = 2345;
@@ -116,8 +133,9 @@
         capBuilder.setLinkUpstreamBandwidthKbps(TEST_UPSTREAM_BANDWIDTH);
         capBuilder.setLinkDownstreamBandwidthKbps(TEST_DOWNSTREAM_BANDWIDTH);
         capBuilder.setAdministratorUids(new int[] {TEST_UID});
+        final Network underlyingNetwork = mock(Network.class, CALLS_REAL_METHODS);
         UnderlyingNetworkRecord record = new UnderlyingNetworkRecord(
-                mock(Network.class, CALLS_REAL_METHODS),
+                underlyingNetwork,
                 capBuilder.build(), new LinkProperties(), false);
         final NetworkCapabilities vcnCaps =
                 VcnGatewayConnection.buildNetworkCapabilities(
@@ -128,6 +146,7 @@
         assertTrue(vcnCaps.hasTransport(TRANSPORT_CELLULAR));
         assertTrue(vcnCaps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(vcnCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(vcnCaps.getUnderlyingNetworks().equals(List.of(underlyingNetwork)));
 
         for (int cap : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
             if (cap == NET_CAPABILITY_INTERNET || cap == NET_CAPABILITY_DUN) {
@@ -166,6 +185,59 @@
     }
 
     @Test
+    public void testBuildLinkProperties() throws Exception {
+        final IpSecTunnelInterface tunnelIface =
+                mContext.getSystemService(IpSecManager.class)
+                        .createIpSecTunnelInterface(
+                                DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network);
+
+        final LinkProperties underlyingLp = new LinkProperties();
+        underlyingLp.setInterfaceName(LOOPBACK_IFACE);
+        underlyingLp.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES);
+        doReturn(TEST_MTU).when(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+        final VcnChildSessionConfiguration childSessionConfig =
+                mock(VcnChildSessionConfiguration.class);
+        doReturn(TEST_INTERNAL_ADDRESSES).when(childSessionConfig).getInternalAddresses();
+        doReturn(TEST_DNS_ADDRESSES).when(childSessionConfig).getInternalDnsServers();
+
+        UnderlyingNetworkRecord record =
+                new UnderlyingNetworkRecord(
+                        mock(Network.class, CALLS_REAL_METHODS),
+                        new NetworkCapabilities.Builder().build(),
+                        underlyingLp,
+                        false);
+
+        final LinkProperties vcnLp1 =
+                mGatewayConnection.buildConnectedLinkProperties(
+                        VcnGatewayConnectionConfigTest.buildTestConfig(),
+                        tunnelIface,
+                        childSessionConfig,
+                        record);
+
+        verify(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+        // Instead of having to recalculate the final MTU (after accounting for IPsec overhead),
+        // calculate another set of Link Properties with a lower MTU, and calculate the delta.
+        doReturn(TEST_MTU - TEST_MTU_DELTA).when(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+        final LinkProperties vcnLp2 =
+                mGatewayConnection.buildConnectedLinkProperties(
+                        VcnGatewayConnectionConfigTest.buildTestConfig(),
+                        tunnelIface,
+                        childSessionConfig,
+                        record);
+
+        verify(mDeps, times(2)).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+        assertEquals(tunnelIface.getInterfaceName(), vcnLp1.getInterfaceName());
+        assertEquals(TEST_INTERNAL_ADDRESSES, vcnLp1.getLinkAddresses());
+        assertEquals(TEST_DNS_ADDRESSES, vcnLp1.getDnsServers());
+        assertEquals(TEST_TCP_BUFFER_SIZES, vcnLp1.getTcpBufferSizes());
+        assertEquals(TEST_MTU_DELTA, vcnLp1.getMtu() - vcnLp2.getMtu());
+    }
+
+    @Test
     public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkTracker() {
         verifyWakeLockSetUp();
 
diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS
index 69dfcc9..4f655e5 100644
--- a/tools/aapt2/OWNERS
+++ b/tools/aapt2/OWNERS
@@ -1,4 +1,4 @@
 set noparent
 toddke@google.com
-rtmitchell@google.com
+zyy@google.com
 patb@google.com
\ No newline at end of file
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 5d57de6..be09545 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -154,7 +154,7 @@
   const char* end = path.end();
   const char* last_dir_sep = path.begin();
   for (const char* c = path.begin(); c != end; ++c) {
-    if (*c == sDirSep) {
+    if (*c == sDirSep || *c == sInvariantDirSep) {
       last_dir_sep = c + 1;
     }
   }
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index 481a4cd..e50cb50 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -41,6 +41,8 @@
 constexpr const char sPathSep = ':';
 #endif
 
+constexpr const char sInvariantDirSep = '/';
+
 enum class FileType {
   kUnknown = 0,
   kNonexistant,