Merge "Add a method to get rawContact"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 591e8ba..4becc6b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1008,13 +1008,21 @@
     }
 
     @Override
-    public void onUserUnlocked(@NonNull TargetUser user) {
+    public void onUserStarting(@NonNull TargetUser user) {
         synchronized (mLock) {
-            // Note that the user has started after its unlocked instead of when the user
-            // actually starts because the storage won't be decrypted until unlock.
             mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
         }
-        // Let's kick any outstanding jobs for this user.
+        // The user is starting but credential encrypted storage is still locked.
+        // Only direct-boot-aware jobs can safely run.
+        // Let's kick off any eligible jobs for this user.
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+    }
+
+    @Override
+    public void onUserUnlocked(@NonNull TargetUser user) {
+        // The user is fully unlocked and credential encrypted storage is now decrypted.
+        // Direct-boot-UNaware jobs can now safely run.
+        // Let's kick off any outstanding jobs for this user.
         mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
     }
 
diff --git a/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
new file mode 100644
index 0000000..f560434
--- /dev/null
+++ b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
@@ -0,0 +1,4 @@
+rubinxu@google.com
+acjohnston@google.com
+pgrafov@google.com
+alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/admin/EnterprisePlatform_OWNERS b/core/java/android/app/admin/EnterprisePlatform_OWNERS
new file mode 100644
index 0000000..fb00fe5
--- /dev/null
+++ b/core/java/android/app/admin/EnterprisePlatform_OWNERS
@@ -0,0 +1,2 @@
+file:WorkDeviceExperience_OWNERS
+file:EnterprisePlatformSecurity_OWNERS
\ No newline at end of file
diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS
index 6acbef2..10a5f14 100644
--- a/core/java/android/app/admin/OWNERS
+++ b/core/java/android/app/admin/OWNERS
@@ -1,11 +1,5 @@
 # Bug component: 142675
 
-# Android Enterprise team
-rubinxu@google.com
-sandness@google.com
-alexkershaw@google.com
-pgrafov@google.com
+file:EnterprisePlatform_OWNERS
 
-# Emeritus
-yamasani@google.com
-eranm@google.com
+yamasani@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/admin/WorkDeviceExperience_OWNERS b/core/java/android/app/admin/WorkDeviceExperience_OWNERS
new file mode 100644
index 0000000..dcacaa2
--- /dev/null
+++ b/core/java/android/app/admin/WorkDeviceExperience_OWNERS
@@ -0,0 +1,5 @@
+work-device-experience+reviews@google.com
+scottjonathan@google.com
+arangelov@google.com
+kholoudm@google.com
+alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c71fcc6..9caeb29 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1186,11 +1186,6 @@
         mAttributionSource = attributionSource;
     }
 
-    /** {@hide} */
-    public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
-        setAttributionSource(attributionSource);
-    }
-
     @Override
     public boolean equals(@Nullable Object o) {
         if (o instanceof BluetoothDevice) {
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 20152f3..b5df4db 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 final AttributionSource mAttributionSource;
+    private static AttributionSource sAttributionSource = null;
     private final BluetoothAdapter mAdapter;
 
     /**
      * @hide
      */
     public BluetoothManager(Context context) {
-        mAttributionSource = resolveAttributionSource(context);
-        mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
+        sAttributionSource = resolveAttributionSource(context);
+        mAdapter = BluetoothAdapter.createAdapter(sAttributionSource);
     }
 
     /** {@hide} */
@@ -79,6 +79,9 @@
         if (context != null) {
             res = context.getAttributionSource();
         }
+        else if (sAttributionSource != null) {
+            return sAttributionSource;
+        }
         if (res == null) {
             res = ActivityThread.currentAttributionSource();
         }
@@ -198,8 +201,8 @@
             IBluetoothGatt iGatt = managerService.getBluetoothGatt();
             if (iGatt == null) return devices;
             devices = Attributable.setAttributionSource(
-                    iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
-                    mAttributionSource);
+                    iGatt.getDevicesMatchingConnectionStates(states, sAttributionSource),
+                    sAttributionSource);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d811040..2fd437d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -31,7 +31,6 @@
 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;
@@ -11462,16 +11461,6 @@
         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/res/Configuration.java b/core/java/android/content/res/Configuration.java
index b66f048..755114e 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1736,35 +1736,9 @@
      * object and the given one.  Does not change the values of either.  Any
      * undefined fields in <var>delta</var> are ignored.
      * @return Returns a bit mask indicating which configuration
-     * values has changed, containing any combination of
-     * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
-     * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
-     * {@link android.content.pm.ActivityInfo#CONFIG_MCC
-     * PackageManager.ActivityInfo.CONFIG_MCC},
-     * {@link android.content.pm.ActivityInfo#CONFIG_MNC
-     * PackageManager.ActivityInfo.CONFIG_MNC},
-     * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
-     * PackageManager.ActivityInfo.CONFIG_LOCALE},
-     * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
-     * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
-     * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
-     * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
-     * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
-     * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
-     * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
-     * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
-     * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
-     * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
-     * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
-     * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
-     * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
-     * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
-     * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
-     * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
-     * {@link android.content.pm.ActivityInfo#CONFIG_FONT_WEIGHT_ADJUSTMENT
-     *  PackageManager.ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT.
+     * values have changed.
      */
-    public int diff(Configuration delta) {
+    public @Config int diff(Configuration delta) {
         return diff(delta, false /* compareUndefined */, false /* publicOnly */);
     }
 
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 24a06df..f55bcd3 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -2,5 +2,5 @@
 
 include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
 
-per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, ngeoffray@google.com
-per-file SntpClient*, sntp/* = file:/services/core/java/com/android/server/timedetector/OWNERS
+per-file SSL*,Uri*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
+per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/java/android/net/sntp/OWNERS b/core/java/android/net/sntp/OWNERS
new file mode 100644
index 0000000..9a3e264
--- /dev/null
+++ b/core/java/android/net/sntp/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index fa578be..ab2c8c0 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -401,7 +401,7 @@
     private static final int WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS = 1000;
 
     @CriticalNative
-    private static native long nativeGetBlobAshmemSize(long nativePtr);
+    private static native long nativeGetOpenAshmemSize(long nativePtr);
 
     public final static Parcelable.Creator<String> STRING_CREATOR
              = new Parcelable.Creator<String>() {
@@ -2891,9 +2891,11 @@
 
     /**
      * Same as {@link #readList(List, ClassLoader)} but accepts {@code clazz} parameter as
-     * the type required for each item. If the item to be deserialized is not an instance
-     * of that class or any of its children class
-     * a {@link BadParcelableException} will be thrown.
+     * 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.
      */
     public <T> void readList(@NonNull List<? super T> outVal,
             @Nullable ClassLoader loader, @NonNull Class<T> clazz) {
@@ -3894,8 +3896,11 @@
 
     /**
      * Same as {@link #readParcelable(ClassLoader)} but accepts {@code clazz} parameter as the type
-     * required for each item. If the item to be deserialized is not an instance of that class or
-     * any of its children classes a {@link BadParcelableException} will be thrown.
+     * 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 extends Parcelable> T readParcelable(@Nullable ClassLoader loader,
@@ -3961,8 +3966,11 @@
 
     /**
      * Same as {@link #readParcelableCreator(ClassLoader)} but accepts {@code clazz} parameter
-     * as the required type. If the item to be deserialized is not an instance of that class
-     * or any of its children classes a {@link BadParcelableException} will be thrown.
+     * 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
+     * trying to read the {@link Parcelable.Creator}.
      */
     @Nullable
     public <T> Parcelable.Creator<T> readParcelableCreator(
@@ -4373,8 +4381,8 @@
     /**
      * @hide For testing
      */
-    public long getBlobAshmemSize() {
-        return nativeGetBlobAshmemSize(mNativePtr);
+    public long getOpenAshmemSize() {
+        return nativeGetOpenAshmemSize(mNativePtr);
     }
 
     private static String valueTypeToString(int type) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index dd4de0a..3028a6d 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -691,6 +691,11 @@
          * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
          * subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PHONE_STATE}.
+         *
          */
         @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
         void onMessageWaitingIndicatorChanged(boolean mwi);
@@ -710,6 +715,11 @@
          * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
          * subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PHONE_STATE}.
+         *
          */
         @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
         void onCallForwardingIndicatorChanged(boolean cfi);
@@ -868,6 +878,10 @@
          * subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+         *
          * @param callState {@link PreciseCallState}
          */
         @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -910,6 +924,10 @@
          * subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+         *
          * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
          */
         @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -932,9 +950,9 @@
          * subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
          *
-         * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
-         * or the calling app has carrier privileges
-         * (see {@link TelephonyManager#hasCarrierPrivileges}).
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
          *
          * @param dataConnectionState {@link PreciseDataConnectionState}
          */
@@ -1063,6 +1081,10 @@
          * given subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PHONE_STATE}.
+         *
          * @param emergencyNumberList Map associating all active subscriptions on the device with
          *                            the list of emergency numbers originating from that
          *                            subscription.
@@ -1157,6 +1179,11 @@
          *              For example, it could be the current active opportunistic subscription
          *              in use, or the subscription user selected as default data subscription in
          *              DSDS mode.
+         *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PHONE_STATE}.
+         *
          */
         @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
         void onActiveDataSubscriptionIdChanged(int subId);
@@ -1225,6 +1252,11 @@
          * <p>Because registration failures are ephemeral, this callback is not sticky.
          * Registrants will not receive the most recent past value when registering.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} and
+         * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+         *
          * @param cellIdentity        the CellIdentity, which must include the globally unique
          *                            identifier
          *                            for the cell (for example, all components of the CGI or ECGI).
@@ -1308,6 +1340,10 @@
          * subscription ID. Otherwise, this callback applies to
          * {@link SubscriptionManager#getDefaultSubscriptionId()}.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+         *
          * @param callAttributes the call attributes
          */
         @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -1324,6 +1360,11 @@
          * <p>Barring info is provided for all services applicable to the current camped/registered
          * cell, for the registered PLMN and current access class/access category.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} and
+         * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+         *
          * @param barringInfo for all services on the current cell.
          * @see android.telephony.BarringInfo
          */
@@ -1341,6 +1382,10 @@
         /**
          * Callback invoked when the current physical channel configuration has changed
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+         *
          * @param configs List of the current {@link PhysicalChannelConfig}s
          */
         @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -1357,6 +1402,10 @@
         /**
          * Callback invoked when the data enabled changes.
          *
+         * The calling app should have carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+         * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+         *
          * @param enabled {@code true} if data is enabled, otherwise disabled.
          * @param reason  Reason for data enabled/disabled.
          *                See {@link TelephonyManager.DataEnabledReason}.
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 8fee610..0d33807 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -740,11 +740,11 @@
     return Parcel::getGlobalAllocCount();
 }
 
-static jlong android_os_Parcel_getBlobAshmemSize(jlong nativePtr)
+static jlong android_os_Parcel_getOpenAshmemSize(jlong nativePtr)
 {
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
     if (parcel != NULL) {
-        return parcel->getBlobAshmemSize();
+        return parcel->getOpenAshmemSize();
     }
     return 0;
 }
@@ -852,7 +852,7 @@
     {"getGlobalAllocCount",       "()J", (void*)android_os_Parcel_getGlobalAllocCount},
 
     // @CriticalNative
-    {"nativeGetBlobAshmemSize",       "(J)J", (void*)android_os_Parcel_getBlobAshmemSize},
+    {"nativeGetOpenAshmemSize",       "(J)J", (void*)android_os_Parcel_getOpenAshmemSize},
 
     // @CriticalNative
     {"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid},
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
index aa87958..4e5136f 100644
--- a/core/tests/coretests/src/android/net/OWNERS
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -1 +1,3 @@
 include /services/core/java/com/android/server/net/OWNERS
+
+per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/net/sntp/OWNERS b/core/tests/coretests/src/android/net/sntp/OWNERS
new file mode 100644
index 0000000..232c2eb
--- /dev/null
+++ b/core/tests/coretests/src/android/net/sntp/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/net/sntp/OWNERS
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 7e9d2d8..9c9e83b 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -106,7 +106,7 @@
     @IntDef({
             TYPE_UNKNOWN, TYPE_BUILTIN_SPEAKER, TYPE_WIRED_HEADSET,
             TYPE_WIRED_HEADPHONES, TYPE_BLUETOOTH_A2DP, TYPE_HDMI, TYPE_USB_DEVICE,
-            TYPE_USB_ACCESSORY, TYPE_DOCK, TYPE_USB_HEADSET, TYPE_HEARING_AID,
+            TYPE_USB_ACCESSORY, TYPE_DOCK, TYPE_USB_HEADSET, TYPE_HEARING_AID, TYPE_BLE_HEADSET,
             TYPE_REMOTE_TV, TYPE_REMOTE_SPEAKER, TYPE_GROUP})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {}
@@ -202,6 +202,14 @@
     public static final int TYPE_HEARING_AID = AudioDeviceInfo.TYPE_HEARING_AID;
 
     /**
+     * A route type describing a BLE HEADSET.
+     *
+     * @see #getType
+     * @hide
+     */
+    public static final int TYPE_BLE_HEADSET = AudioDeviceInfo.TYPE_BLE_HEADSET;
+
+    /**
      * A route type indicating the presentation of the media is happening on a TV.
      *
      * @see #getType
diff --git a/packages/SettingsLib/res/drawable/ic_bt_le_audio.xml b/packages/SettingsLib/res/drawable/ic_bt_le_audio.xml
new file mode 100644
index 0000000..5b52a04
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_bt_le_audio.xml
@@ -0,0 +1,31 @@
+<!--
+     Copyright 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal" >
+    <path
+        android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
+        android:fillColor="#FFFFFFFF"/>
+    <path
+        android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
+        android:fillColor="#FFFFFFFF"/>
+    <path
+        android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 6b840bd..a56c490 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -257,8 +257,12 @@
 
     <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the Hearing Aid profile. -->
     <string name="bluetooth_profile_hearing_aid">Hearing Aids</string>
+    <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the LE_AUDIO profile. -->
+    <string name="bluetooth_profile_le_audio">LE_AUDIO</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. -->
     <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aids</string>
+    <!-- Bluetooth settings.  Connection options screen.  The summary for the LE_AUDIO checkbox preference when LE_AUDIO is connected. -->
+    <string name="bluetooth_le_audio_profile_summary_connected">Connected to LE_AUDIO</string>
 
     <!-- Bluetooth settings.  Connection options screen.  The summary for the A2DP checkbox preference when A2DP is connected. -->
     <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
@@ -299,6 +303,8 @@
     <string name="bluetooth_hid_profile_summary_use_for">Use for input</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. -->
     <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aids</string>
+    <!-- Bluetooth settings.  Connection options screen.  The summary for the LE_AUDIO checkbox preference that describes how checking it will set the LE_AUDIO profile as preferred. -->
+    <string name="bluetooth_le_audio_profile_summary_use_for">Use for LE_AUDIO</string>
 
     <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] -->
     <string name="bluetooth_pairing_accept">Pair</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 8750309..58d2185 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -22,6 +22,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -116,6 +117,8 @@
         addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
         addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
                 new ActiveDeviceChangedHandler());
+        addHandler(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED,
+                   new ActiveDeviceChangedHandler());
 
         // Headset state changed broadcasts
         addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
@@ -127,9 +130,6 @@
         addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
         addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
 
-        addHandler(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE,
-                new SetMemberAvailableHandler());
-
         registerAdapterIntentReceiver();
     }
 
@@ -455,6 +455,9 @@
                 bluetoothProfile = BluetoothProfile.HEADSET;
             } else if (Objects.equals(action, BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED)) {
                 bluetoothProfile = BluetoothProfile.HEARING_AID;
+            } else if (Objects.equals(action,
+                        BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED)) {
+                bluetoothProfile = BluetoothProfile.LE_AUDIO;
             } else {
                 Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
                 return;
@@ -515,29 +518,4 @@
             dispatchAudioModeChanged();
         }
     }
-
-    private class SetMemberAvailableHandler implements Handler {
-        @Override
-        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
-            final String action = intent.getAction();
-            if (device == null) {
-                Log.e(TAG, "SetMemberAvailableHandler: device is null");
-                return;
-            }
-
-            if (action == null) {
-                Log.e(TAG, "SetMemberAvailableHandler: action is null");
-                return;
-            }
-
-            final int groupId = intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID,
-                    BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
-            if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
-                Log.e(TAG, "SetMemberAvailableHandler: Invalid group id");
-                return;
-            }
-
-            mDeviceManager.onSetMemberAppear(device, groupId);
-        }
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 2431941..021ba224 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
@@ -109,10 +110,12 @@
     private boolean mIsActiveDeviceA2dp = false;
     private boolean mIsActiveDeviceHeadset = false;
     private boolean mIsActiveDeviceHearingAid = false;
+    private boolean mIsActiveDeviceLeAudio = false;
     // Media profile connect state
     private boolean mIsA2dpProfileConnectedFail = false;
     private boolean mIsHeadsetProfileConnectedFail = false;
     private boolean mIsHearingAidProfileConnectedFail = false;
+    private boolean mIsLeAudioProfileConnectedFail = false;
     // Group second device for Hearing Aid
     private CachedBluetoothDevice mSubDevice;
     // Group member devices for the coordinated set
@@ -133,6 +136,9 @@
                 case BluetoothProfile.HEARING_AID:
                     mIsHearingAidProfileConnectedFail = true;
                     break;
+                case BluetoothProfile.LE_AUDIO:
+                    mIsLeAudioProfileConnectedFail = true;
+                    break;
                 default:
                     Log.w(TAG, "handleMessage(): unknown message : " + msg.what);
                     break;
@@ -266,6 +272,9 @@
             case BluetoothProfile.HEARING_AID:
                 mIsHearingAidProfileConnectedFail = isFailed;
                 break;
+            case BluetoothProfile.LE_AUDIO:
+                mIsLeAudioProfileConnectedFail = isFailed;
+                break;
             default:
                 Log.w(TAG, "setProfileConnectedStatus(): unknown profile id : " + profileId);
                 break;
@@ -541,6 +550,13 @@
                 result = true;
             }
         }
+        LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile();
+        if ((leAudioProfile != null) && isConnectedProfile(leAudioProfile)) {
+            if (leAudioProfile.setActiveDevice(getDevice())) {
+                Log.i(TAG, "OnPreferenceClickListener: LeAudio active device=" + this);
+                result = true;
+            }
+        }
         return result;
     }
 
@@ -619,6 +635,10 @@
             changed = (mIsActiveDeviceHearingAid != isActive);
             mIsActiveDeviceHearingAid = isActive;
             break;
+        case BluetoothProfile.LE_AUDIO:
+            changed = (mIsActiveDeviceLeAudio != isActive);
+            mIsActiveDeviceLeAudio = isActive;
+            break;
         default:
             Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile +
                     " isActive " + isActive);
@@ -650,6 +670,8 @@
                 return mIsActiveDeviceHeadset;
             case BluetoothProfile.HEARING_AID:
                 return mIsActiveDeviceHearingAid;
+            case BluetoothProfile.LE_AUDIO:
+                return mIsActiveDeviceLeAudio;
             default:
                 Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile);
                 break;
@@ -744,6 +766,10 @@
         if (hearingAidProfile != null) {
             mIsActiveDeviceHearingAid = hearingAidProfile.getActiveDevices().contains(mDevice);
         }
+        LeAudioProfile leAudio = mProfileManager.getLeAudioProfile();
+        if (leAudio != null) {
+            mIsActiveDeviceLeAudio = leAudio.getActiveDevices().contains(mDevice);
+        }
     }
 
     /**
@@ -984,6 +1010,7 @@
         boolean a2dpConnected = true;        // A2DP is connected
         boolean hfpConnected = true;         // HFP is connected
         boolean hearingAidConnected = true;  // Hearing Aid is connected
+        boolean leAudioConnected = true;        // LeAudio is connected
         int leftBattery = -1;
         int rightBattery = -1;
 
@@ -1015,6 +1042,8 @@
                                 hfpConnected = false;
                             } else if (profile instanceof HearingAidProfile) {
                                 hearingAidConnected = false;
+                            } else if (profile instanceof LeAudioProfile) {
+                                leAudioConnected = false;
                             }
                         }
                         break;
@@ -1057,7 +1086,8 @@
             //    1. Hearing Aid device active.
             //    2. Headset device active with in-calling state.
             //    3. A2DP device active without in-calling state.
-            if (a2dpConnected || hfpConnected || hearingAidConnected) {
+            //    4. Le Audio device active
+            if (a2dpConnected || hfpConnected || hearingAidConnected || leAudioConnected) {
                 final boolean isOnCall = Utils.isAudioModeOngoingCall(mContext);
                 if ((mIsActiveDeviceHearingAid)
                         || (mIsActiveDeviceHeadset && isOnCall)
@@ -1092,7 +1122,8 @@
 
     private boolean isProfileConnectedFail() {
         return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail
-                || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail);
+                || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail)
+                || mIsLeAudioProfileConnectedFail;
     }
 
     /**
@@ -1103,6 +1134,7 @@
         boolean a2dpNotConnected = false;       // A2DP is preferred but not connected
         boolean hfpNotConnected = false;        // HFP is preferred but not connected
         boolean hearingAidNotConnected = false; // Hearing Aid is preferred but not connected
+        boolean leAudioNotConnected = false;       // LeAudio is preferred but not connected
 
         synchronized (mProfileLock) {
             for (LocalBluetoothProfile profile : getProfiles()) {
@@ -1128,6 +1160,8 @@
                                 hfpNotConnected = true;
                             } else if (profile instanceof HearingAidProfile) {
                                 hearingAidNotConnected = true;
+                            } else if (profile instanceof  LeAudioProfile) {
+                                leAudioNotConnected = true;
                             }
                         }
                         break;
@@ -1166,6 +1200,11 @@
             return mContext.getString(R.string.bluetooth_connected, activeDeviceString);
         }
 
+        if (!leAudioNotConnected && mIsActiveDeviceLeAudio) {
+            activeDeviceString = activeDeviceStringsArray[1];
+            return mContext.getString(R.string.bluetooth_connected, activeDeviceString);
+        }
+
         if (profileConnected) {
             if (a2dpNotConnected && hfpNotConnected) {
                 if (batteryLevelPercentageString != null) {
@@ -1235,6 +1274,15 @@
                 BluetoothProfile.STATE_CONNECTED;
     }
 
+    /**
+     * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio device
+     */
+    public boolean isConnectedLeAudioDevice() {
+        LeAudioProfile leAudio = mProfileManager.getLeAudioProfile();
+        return leAudio != null && leAudio.getConnectionStatus(mDevice) ==
+                BluetoothProfile.STATE_CONNECTED;
+    }
+
     private boolean isConnectedSapDevice() {
         SapProfile sapProfile = mProfileManager.getSapProfile();
         return sapProfile != null && sapProfile.getConnectionStatus(mDevice)
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 1f75ae3..b429fe6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -340,22 +340,24 @@
 
     /**
      * Called when we found a set member of a group. The function will check the {@code groupId} if
-     * it exists and if there is a ongoing pair, the device would be ignored.
+     * it exists and the bond state of the device is BOND_NOE, and if there isn't any ongoing pair
+     * , and then return {@code true} to pair the device automatically.
      *
      * @param device The found device
      * @param groupId The group id of the found device
+     *
+     * @return {@code true}, if the device should pair automatically; Otherwise, return
+     * {@code false}.
      */
-    public synchronized void onSetMemberAppear(BluetoothDevice device, int groupId) {
-        Log.d(TAG, "onSetMemberAppear, groupId: " + groupId + " device: " + device.toString());
-
-        if (mOngoingSetMemberPair != null) {
-            Log.d(TAG, "Ongoing set memberPairing in process, drop it!");
-            return;
+    public synchronized boolean shouldPairByCsip(BluetoothDevice device, int groupId) {
+        if (mOngoingSetMemberPair != null || device.getBondState() != BluetoothDevice.BOND_NONE
+                || !mCsipDeviceManager.isExistedGroupId(groupId)) {
+            return false;
         }
 
-        if (mCsipDeviceManager.onSetMemberAppear(device, groupId)) {
-            mOngoingSetMemberPair = device;
-        }
+        Log.d(TAG, "Bond " + device.getName() + " by CSIP");
+        mOngoingSetMemberPair = device;
+        return true;
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 347e14b..1d29966 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -240,22 +240,15 @@
     }
 
     /**
-     * Called when we found a set member of a group. The function will check bond state, and
-     * the {@code groupId} if it exists, and then create the bond.
+     * Check if the {@code groupId} is existed.
      *
-     * @param device The found device
-     * @param groupId The group id of the found device
+     * @param groupId The group id
      *
-     * @return {@code true}, if the we create bond with the device. Otherwise, return
-     * {@code false}.
+     * @return {@code true}, if we could find a device with this {@code groupId}; Otherwise,
+     * return {@code false}.
      */
-    public boolean onSetMemberAppear(BluetoothDevice device, int groupId) {
-        if (device.getBondState() != BluetoothDevice.BOND_NONE) {
-            return false;
-        }
-
+    public boolean isExistedGroupId(int groupId) {
         if (getCachedDevice(groupId) != null) {
-            device.createBond(BluetoothDevice.TRANSPORT_LE);
             return true;
         }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
new file mode 100644
index 0000000..209507a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -0,0 +1,264 @@
+/*   Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA
+- www.ehima.com
+*/
+
+/* 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.settingslib.bluetooth;
+
+import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_ALL;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.Build;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class LeAudioProfile implements LocalBluetoothProfile {
+    private static final String TAG = "LeAudioProfile";
+    private static boolean DEBUG = true;
+
+    private Context mContext;
+
+    private BluetoothLeAudio mService;
+    private boolean mIsProfileReady;
+
+    private final CachedBluetoothDeviceManager mDeviceManager;
+
+    static final String NAME = "LE_AUDIO";
+    private final LocalBluetoothProfileManager mProfileManager;
+    private final BluetoothAdapter mBluetoothAdapter;
+
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 1;
+
+    // These callbacks run on the main thread.
+    private final class LeAudioServiceListener
+            implements BluetoothProfile.ServiceListener {
+
+        @RequiresApi(Build.VERSION_CODES.S)
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            if (DEBUG) {
+                Log.d(TAG,"Bluetooth service connected");
+            }
+            mService = (BluetoothLeAudio) proxy;
+            // We just bound to the service, so refresh the UI for any connected LeAudio devices.
+            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+            while (!deviceList.isEmpty()) {
+                BluetoothDevice nextDevice = deviceList.remove(0);
+                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+                // we may add a new device here, but generally this should not happen
+                if (device == null) {
+                    if (DEBUG) {
+                        Log.d(TAG, "LeAudioProfile found new device: " + nextDevice);
+                    }
+                    device = mDeviceManager.addDevice(nextDevice);
+                }
+                device.onProfileStateChanged(LeAudioProfile.this,
+                        BluetoothProfile.STATE_CONNECTED);
+                device.refresh();
+            }
+
+            mProfileManager.callServiceConnectedListeners();
+            mIsProfileReady = true;
+        }
+
+        public void onServiceDisconnected(int profile) {
+            if (DEBUG) {
+                 Log.d(TAG,"Bluetooth service disconnected");
+            }
+            mProfileManager.callServiceDisconnectedListeners();
+            mIsProfileReady = false;
+        }
+    }
+
+    public boolean isProfileReady() {
+        return mIsProfileReady;
+    }
+
+    @Override
+    public int getProfileId() {
+        return BluetoothProfile.LE_AUDIO;
+    }
+
+    LeAudioProfile(Context context, CachedBluetoothDeviceManager deviceManager,
+            LocalBluetoothProfileManager profileManager) {
+        mContext = context;
+        mDeviceManager = deviceManager;
+        mProfileManager = profileManager;
+
+        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        mBluetoothAdapter.getProfileProxy(
+                context, new LeAudioServiceListener(),
+                BluetoothProfile.LE_AUDIO);
+    }
+
+    public boolean accessProfileEnabled() {
+        return true;
+    }
+
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
+        return mService.getDevicesMatchingConnectionStates(
+              new int[] {BluetoothProfile.STATE_CONNECTED,
+                         BluetoothProfile.STATE_CONNECTING,
+                         BluetoothProfile.STATE_DISCONNECTING});
+    }
+
+    /*
+    * @hide
+    */
+    public boolean connect(BluetoothDevice device) {
+       if (mService == null) {
+           return false;
+       }
+       return mService.connect(device);
+    }
+
+    /*
+    * @hide
+    */
+    public boolean disconnect(BluetoothDevice device) {
+       if (mService == null) {
+           return false;
+       }
+       return mService.disconnect(device);
+    }
+
+    public int getConnectionStatus(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+        return mService.getConnectionState(device);
+    }
+
+    public boolean setActiveDevice(BluetoothDevice device) {
+        if (mBluetoothAdapter == null) {
+            return false;
+        }
+        return device == null
+                ? mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_ALL)
+                : mBluetoothAdapter.setActiveDevice(device, ACTIVE_DEVICE_ALL);
+    }
+
+    public List<BluetoothDevice> getActiveDevices() {
+        if (mService == null) {
+            return new ArrayList<>();
+        }
+        return mService.getActiveDevices();
+    }
+
+    @Override
+    public boolean isEnabled(BluetoothDevice device) {
+        if (mService == null || device == null) {
+            return false;
+        }
+        return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN;
+    }
+
+    @Override
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (mService == null || device == null) {
+            return CONNECTION_POLICY_FORBIDDEN;
+        }
+        return mService.getConnectionPolicy(device);
+    }
+
+    @Override
+    public boolean setEnabled(BluetoothDevice device, boolean enabled) {
+        boolean isEnabled = false;
+        if (mService == null || device == null) {
+            return false;
+        }
+        if (enabled) {
+            if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) {
+                isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
+            }
+        } else {
+            isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN);
+        }
+
+        return isEnabled;
+    }
+
+    public String toString() {
+        return NAME;
+    }
+
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    public int getNameResource(BluetoothDevice device) {
+        return R.string.bluetooth_profile_le_audio;
+    }
+
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        int state = getConnectionStatus(device);
+        switch (state) {
+            case BluetoothProfile.STATE_DISCONNECTED:
+                return R.string.bluetooth_le_audio_profile_summary_use_for;
+
+            case BluetoothProfile.STATE_CONNECTED:
+                return R.string.bluetooth_le_audio_profile_summary_connected;
+
+            default:
+                return BluetoothUtils.getConnectionStateSummary(state);
+        }
+    }
+
+    public int getDrawableResource(BluetoothClass btClass) {
+        return R.drawable.ic_bt_le_audio;
+    }
+
+    @RequiresApi(Build.VERSION_CODES.S)
+    protected void finalize() {
+        if (DEBUG) {
+            Log.d(TAG, "finalize()");
+        }
+        if (mService != null) {
+            try {
+                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.LE_AUDIO,
+                        mService);
+                mService = null;
+            }catch (Throwable t) {
+                Log.w(TAG, "Error cleaning up LeAudio proxy", t);
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index bcb3455..3347920 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -24,6 +24,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHeadsetClient;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothHidDevice;
 import android.bluetooth.BluetoothHidHost;
 import android.bluetooth.BluetoothMap;
@@ -102,6 +103,7 @@
     private PbapServerProfile mPbapProfile;
     private HearingAidProfile mHearingAidProfile;
     private CsipSetCoordinatorProfile mCsipSetCoordinatorProfile;
+    private LeAudioProfile mLeAudioProfile;
     private SapProfile mSapProfile;
     private VolumeControlProfile mVolumeControlProfile;
 
@@ -232,6 +234,14 @@
             // Note: no event handler for VCP, only for being connectable.
             mProfileNameMap.put(VolumeControlProfile.NAME, mVolumeControlProfile);
         }
+        if (mLeAudioProfile == null && supportedList.contains(BluetoothProfile.LE_AUDIO)) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding local LE_AUDIO profile");
+            }
+            mLeAudioProfile = new LeAudioProfile(mContext, mDeviceManager, this);
+            addProfile(mLeAudioProfile, LeAudioProfile.NAME,
+                       BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+        }
         if (mCsipSetCoordinatorProfile == null
                 && supportedList.contains(BluetoothProfile.CSIP_SET_COORDINATOR)) {
             if (DEBUG) {
@@ -487,6 +497,10 @@
         return mHearingAidProfile;
     }
 
+    public LeAudioProfile getLeAudioProfile() {
+        return mLeAudioProfile;
+    }
+
     SapProfile getSapProfile() {
         return mSapProfile;
     }
@@ -614,6 +628,11 @@
             removedProfiles.remove(mHearingAidProfile);
         }
 
+        if (ArrayUtils.contains(uuids, BluetoothUuid.LE_AUDIO) && mLeAudioProfile != null) {
+            profiles.add(mLeAudioProfile);
+            removedProfiles.remove(mLeAudioProfile);
+        }
+
         if (mSapProfile != null && ArrayUtils.contains(uuids, BluetoothUuid.SAP)) {
             profiles.add(mSapProfile);
             removedProfiles.remove(mSapProfile);
diff --git a/services/companion/OWNERS b/services/companion/OWNERS
new file mode 100644
index 0000000..cb4cc56
--- /dev/null
+++ b/services/companion/OWNERS
@@ -0,0 +1,4 @@
+evanxinchen@google.com
+ewol@google.com
+guojing@google.com
+svetoslavganov@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index fdba098..469f465 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -476,7 +476,11 @@
      */
     public static void addTombstoneToDropBox(Context ctx, File tombstone, boolean proto) {
         final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
-        final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
+        if (db == null) {
+            Slog.e(TAG, "Can't log tombstone: DropBoxManager not available");
+            return;
+        }
+
         HashMap<String, Long> timestamps = readTimestamps();
         try {
             if (proto) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index edf832f..c11c4de 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -385,6 +385,10 @@
     private int[] mAllowedNetworkTypeReason;
     private long[] mAllowedNetworkTypeValue;
 
+    private static final List<LinkCapacityEstimate> INVALID_LCE_LIST =
+            new ArrayList<LinkCapacityEstimate>(Arrays.asList(new LinkCapacityEstimate(
+            LinkCapacityEstimate.LCE_TYPE_COMBINED,
+            LinkCapacityEstimate.INVALID, LinkCapacityEstimate.INVALID)));
     private List<List<LinkCapacityEstimate>> mLinkCapacityEstimateLists;
 
     /**
@@ -719,7 +723,7 @@
             mPhysicalChannelConfigs.add(i, new ArrayList<>());
             mAllowedNetworkTypeReason[i] = -1;
             mAllowedNetworkTypeValue[i] = -1;
-            mLinkCapacityEstimateLists.add(i, new ArrayList<>());
+            mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
         }
     }
 
@@ -819,7 +823,7 @@
             mPhysicalChannelConfigs.add(i, new ArrayList<>());
             mAllowedNetworkTypeReason[i] = -1;
             mAllowedNetworkTypeValue[i] = -1;
-            mLinkCapacityEstimateLists.add(i, new ArrayList<>());
+            mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
         }
 
         mAppOps = mContext.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 503b3a9..94bf62f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1568,17 +1568,23 @@
                     perm = PackageManager.PERMISSION_DENIED;
                 }
 
-                if (perm == PackageManager.PERMISSION_GRANTED) {
-                    skip = true;
-                    break;
-                }
-
                 int appOp = AppOpsManager.permissionToOpCode(excludedPermission);
                 if (appOp != AppOpsManager.OP_NONE) {
-                    if (mService.getAppOpsManager().checkOpNoThrow(appOp,
+                    // When there is an app op associated with the permission,
+                    // skip when both the permission and the app op are
+                    // granted.
+                    if ((perm == PackageManager.PERMISSION_GRANTED) && (
+                                mService.getAppOpsManager().checkOpNoThrow(appOp,
                                 info.activityInfo.applicationInfo.uid,
                                 info.activityInfo.packageName)
-                            == AppOpsManager.MODE_ALLOWED) {
+                            == AppOpsManager.MODE_ALLOWED)) {
+                        skip = true;
+                        break;
+                    }
+                } else {
+                    // When there is no app op associated with the permission,
+                    // skip when permission is granted.
+                    if (perm == PackageManager.PERMISSION_GRANTED) {
                         skip = true;
                         break;
                     }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 38f71ba..c383f51 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -22,6 +22,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothLeAudio;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -503,6 +504,18 @@
         }
     }
 
+    /*package*/ static final class BleVolumeInfo {
+        final int mIndex;
+        final int mMaxIndex;
+        final int mStreamType;
+
+        BleVolumeInfo(int index, int maxIndex, int streamType) {
+            mIndex = index;
+            mMaxIndex = maxIndex;
+            mStreamType = streamType;
+        }
+    };
+
     /*package*/ static final class BtDeviceConnectionInfo {
         final @NonNull BluetoothDevice mDevice;
         final @AudioService.BtProfileConnectionState int mState;
@@ -711,6 +724,11 @@
         sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
     }
 
+     /*package*/ void postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType) {
+        BleVolumeInfo info = new BleVolumeInfo(index, maxIndex, streamType);
+        sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info);
+    }
+
     /*package*/ void postSetModeOwnerPid(int pid, int mode) {
         sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode);
     }
@@ -851,6 +869,10 @@
         return mAudioService.getVssVolumeForDevice(streamType, device);
     }
 
+    /*package*/ int getMaxVssVolumeForStream(int streamType) {
+        return mAudioService.getMaxVssVolumeForStream(streamType);
+    }
+
     /*package*/ int getDeviceForStream(int streamType) {
         return mAudioService.getDeviceForStream(streamType);
     }
@@ -962,6 +984,10 @@
         sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
     }
 
+    /*package*/ void postDisconnectLeAudio() {
+        sendMsgNoDelay(MSG_DISCONNECT_BT_LE_AUDIO, SENDMSG_QUEUE);
+    }
+
     /*package*/ void postDisconnectHeadset() {
         sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
     }
@@ -983,6 +1009,11 @@
                 hearingAidProfile);
     }
 
+    /*package*/ void postBtLeAudioProfileConnected(BluetoothLeAudio leAudioProfile) {
+        sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO, SENDMSG_QUEUE,
+                leAudioProfile);
+    }
+
     /*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
         sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client);
     }
@@ -1321,6 +1352,12 @@
                         mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2);
                     }
                     break;
+                case MSG_II_SET_LE_AUDIO_OUT_VOLUME: {
+                    final BleVolumeInfo info = (BleVolumeInfo) msg.obj;
+                    synchronized (mDeviceStateLock) {
+                        mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType);
+                    }
+                } break;
                 case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME:
                     synchronized (mDeviceStateLock) {
                         mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
@@ -1384,6 +1421,11 @@
                         }
                     }
                     break;
+                case MSG_DISCONNECT_BT_LE_AUDIO:
+                    synchronized(mDeviceStateLock) {
+                        mDeviceInventory.disconnectLeAudio();
+                    }
+                    break;
                 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
                     synchronized (mDeviceStateLock) {
                         mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
@@ -1399,6 +1441,12 @@
                         mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
                     }
                     break;
+
+                case MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO:
+                    synchronized(mDeviceStateLock) {
+                        mBtHelper.onLeAudioProfileConnected((BluetoothLeAudio) msg.obj);
+                    }
+                    break;
                 case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
                     synchronized (mSetModeLock) {
                         synchronized (mDeviceStateLock) {
@@ -1586,6 +1634,11 @@
     private static final int MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE = 43;
     private static final int MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT = 44;
     private static final int MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT = 45;
+    // process set volume for Le Audio, obj is BleVolumeInfo
+    private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
+
+    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO = 47;
+    private static final int MSG_DISCONNECT_BT_LE_AUDIO = 48;
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
@@ -1714,10 +1767,12 @@
         MESSAGES_MUTE_MUSIC = new HashSet<>();
         MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED);
         MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED);
+        MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE);
         MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
         MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE);
         MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION);
         MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
+        MESSAGES_MUTE_MUSIC.add(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT);
         MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
         MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP);
     }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 64e620e..6c3c736 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -887,6 +887,28 @@
         }
     }
 
+     /*package*/ void disconnectLeAudio() {
+        synchronized (mDevicesLock) {
+            final ArraySet<String> toRemove = new ArraySet<>();
+            // Disconnect ALL DEVICE_OUT_BLE_HEADSET devices
+            mConnectedDevices.values().forEach(deviceInfo -> {
+                if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+                    toRemove.add(deviceInfo.mDeviceAddress);
+                }
+            });
+            new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
+                    .record();
+            if (toRemove.size() > 0) {
+                final int delay = checkSendBecomingNoisyIntentInt(
+                        AudioSystem.DEVICE_OUT_BLE_HEADSET, 0, AudioSystem.DEVICE_NONE);
+                toRemove.stream().forEach(deviceAddress ->
+                        makeLeAudioDeviceUnavailable(deviceAddress,
+                            AudioSystem.DEVICE_OUT_BLE_HEADSET)
+                );
+            }
+        }
+    }
+
     // must be called before removing the device from mConnectedDevices
     // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
     // from AudioSystem
@@ -1195,6 +1217,10 @@
             return;
         }
 
+        final int leAudioVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType,
+                                    AudioSystem.DEVICE_OUT_BLE_HEADSET);
+        final int maxIndex = mDeviceBroker.getMaxVssVolumeForStream(streamType);
+        mDeviceBroker.postSetLeAudioVolumeIndex(leAudioVolIndex, maxIndex, streamType);
         mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
     }
 
@@ -1243,6 +1269,7 @@
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_LINE);
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_BLE_HEADSET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bf5f4c2..8e1b06b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -334,6 +334,10 @@
         return mStreamStates[stream].getIndex(device);
     }
 
+    /*package*/ int getMaxVssVolumeForStream(int stream) {
+        return mStreamStates[stream].getMaxIndex();
+    }
+
     private SettingsObserver mSettingsObserver;
 
     private AtomicInteger mMode = new AtomicInteger(AudioSystem.MODE_NORMAL);
@@ -2952,6 +2956,16 @@
                 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
             }
 
+            if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+                    && streamType == getBluetoothContextualVolumeStream()) {
+                if (DEBUG_VOL) {
+                    Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
+                            + newIndex + " stream=" + streamType);
+                }
+                mDeviceBroker.postSetLeAudioVolumeIndex(newIndex,
+                    mStreamStates[streamType].getMaxIndex(), streamType);
+            }
+
             // Check if volume update should be send to Hearing Aid
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 // only modify the hearing aid attenuation when the stream to modify matches
@@ -3580,6 +3594,16 @@
                 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
             }
 
+            if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+                    && streamType == getBluetoothContextualVolumeStream()) {
+                if (DEBUG_VOL) {
+                    Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
+                            + index + " stream=" + streamType);
+                }
+                mDeviceBroker.postSetLeAudioVolumeIndex(index,
+                    mStreamStates[streamType].getMaxIndex(), streamType);
+            }
+
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID
                     && streamType == getBluetoothContextualVolumeStream()) {
                 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index 0eb5a5d..3137fa5 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -155,6 +155,7 @@
         static final int VOL_MODE_CHANGE_HEARING_AID = 7;
         static final int VOL_SET_GROUP_VOL = 8;
         static final int VOL_MUTE_STREAM_INT = 9;
+        static final int VOL_SET_LE_AUDIO_VOL = 10;
 
         final int mOp;
         final int mStream;
@@ -310,6 +311,13 @@
                             .set(MediaMetrics.Property.INDEX, mVal1)
                             .record();
                     return;
+                case VOL_SET_LE_AUDIO_VOL:
+                    new MediaMetrics.Item(mMetricsId)
+                            .set(MediaMetrics.Property.EVENT, "setLeAudioVolume")
+                            .set(MediaMetrics.Property.INDEX, mVal1)
+                            .set(MediaMetrics.Property.MAX_INDEX, mVal2)
+                            .record();
+                    return;
                 case VOL_SET_AVRCP_VOL:
                     new MediaMetrics.Item(mMetricsId)
                             .set(MediaMetrics.Property.EVENT, "setAvrcpVolume")
@@ -382,6 +390,11 @@
                             .append(" index:").append(mVal1)
                             .append(" gain dB:").append(mVal2)
                             .toString();
+                case VOL_SET_LE_AUDIO_VOL:
+                    return new StringBuilder("setLeAudioVolume:")
+                            .append(" index:").append(mVal1)
+                            .append(" gain dB:").append(mVal2)
+                            .toString();
                 case VOL_SET_AVRCP_VOL:
                     return new StringBuilder("setAvrcpVolume:")
                             .append(" index:").append(mVal1)
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 52e8edf..c924fde 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -25,6 +25,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.Intent;
 import android.media.AudioDeviceAttributes;
@@ -63,6 +64,8 @@
 
     private @Nullable BluetoothHearingAid mHearingAid;
 
+    private @Nullable BluetoothLeAudio mLeAudio;
+
     // Reference to BluetoothA2dp to query for AbsoluteVolume.
     private @Nullable BluetoothA2dp mA2dp;
 
@@ -106,6 +109,8 @@
     private static final int SCO_MODE_MAX = 2;
 
     private static final int BT_HEARING_AID_GAIN_MIN = -128;
+    private static final int BT_LE_AUDIO_MIN_VOL = 0;
+    private static final int BT_LE_AUDIO_MAX_VOL = 255;
 
     /**
      * Returns a string representation of the scoAudioMode.
@@ -235,6 +240,8 @@
                     mBluetoothProfileServiceListener, BluetoothProfile.A2DP);
             adapter.getProfileProxy(mDeviceBroker.getContext(),
                     mBluetoothProfileServiceListener, BluetoothProfile.HEARING_AID);
+            adapter.getProfileProxy(mDeviceBroker.getContext(),
+                    mBluetoothProfileServiceListener, BluetoothProfile.LE_AUDIO);
         }
     }
 
@@ -389,6 +396,26 @@
         return requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, SCO_MODE_VIRTUAL_CALL);
     }
 
+    /*package*/ synchronized void setLeAudioVolume(int index, int maxIndex, int streamType) {
+        if (mLeAudio == null) {
+            if (AudioService.DEBUG_VOL) {
+                Log.i(TAG, "setLeAudioVolume: null mLeAudio");
+            }
+            return;
+        }
+        /* leaudio expect volume value in range 0 to 255
+         */
+        int volume = (index * (BT_LE_AUDIO_MAX_VOL - BT_LE_AUDIO_MIN_VOL)) / maxIndex ;
+
+        if (AudioService.DEBUG_VOL) {
+            Log.i(TAG, "setLeAudioVolume: calling mLeAudio.setVolume idx="
+                    + index + " volume=" + volume);
+        }
+        AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent(
+                AudioServiceEvents.VolumeEvent.VOL_SET_LE_AUDIO_VOL, index, maxIndex));
+        mLeAudio.setVolume(volume);
+    }
+
     /*package*/ synchronized void setHearingAidVolume(int index, int streamType) {
         if (mHearingAid == null) {
             if (AudioService.DEBUG_VOL) {
@@ -428,6 +455,7 @@
         mDeviceBroker.postDisconnectA2dpSink();
         mDeviceBroker.postDisconnectHeadset();
         mDeviceBroker.postDisconnectHearingAid();
+        mDeviceBroker.postDisconnectLeAudio();
     }
 
     // @GuardedBy("AudioDeviceBroker.mSetModeLock")
@@ -488,6 +516,23 @@
                 /*eventSource*/ "mBluetoothProfileServiceListener");
     }
 
+    /*package*/ synchronized void onLeAudioProfileConnected(BluetoothLeAudio leAudio) {
+        mLeAudio = leAudio;
+        final List<BluetoothDevice> deviceList = mLeAudio.getConnectedDevices();
+        if (deviceList.isEmpty()) {
+            return;
+        }
+
+        final BluetoothDevice btDevice = deviceList.get(0);
+        final @BluetoothProfile.BtProfileState int state =
+        mLeAudio.getConnectionState(btDevice);
+        mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(
+                btDevice, state,
+                /*suppressNoisyIntent*/ false,
+                /*musicDevice android.media.AudioSystem.DEVICE_NONE,*/
+                /*eventSource*/ "mBluetoothProfileServiceListener");
+    }
+
     // @GuardedBy("AudioDeviceBroker.mSetModeLock")
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
     /*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
@@ -655,6 +700,13 @@
                             mDeviceBroker.postBtHearingAidProfileConnected(
                                     (BluetoothHearingAid) proxy);
                             break;
+
+                        case BluetoothProfile.LE_AUDIO:
+                            AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                                    "BT profile service: connecting LE_AUDIO profile"));
+                            mDeviceBroker.postBtLeAudioProfileConnected(
+                                    (BluetoothLeAudio) proxy);
+                            break;
                         default:
                             break;
                     }
@@ -677,6 +729,9 @@
                         case BluetoothProfile.HEARING_AID:
                             mDeviceBroker.postDisconnectHearingAid();
                             break;
+                        case BluetoothProfile.LE_AUDIO:
+                            mDeviceBroker.postDisconnectLeAudio();
+                            break;
 
                         default:
                             break;
@@ -899,6 +954,7 @@
         pw.println(prefix + "mScoAudioState: " + scoAudioStateToString(mScoAudioState));
         pw.println(prefix + "mScoAudioMode: " + scoAudioModeToString(mScoAudioMode));
         pw.println("\n" + prefix + "mHearingAid: " + mHearingAid);
+        pw.println("\n" + prefix + "mLeAudio: " + mLeAudio);
         pw.println(prefix + "mA2dp: " + mA2dp);
         pw.println(prefix + "mAvrcpAbsVolSupported: " + mAvrcpAbsVolSupported);
     }
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 7afa81a..73de0f8 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -26,6 +26,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -56,6 +57,7 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
+    private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     // Maps hardware address to BluetoothRouteInfo
@@ -66,6 +68,8 @@
     BluetoothA2dp mA2dpProfile;
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     BluetoothHearingAid mHearingAidProfile;
+    @SuppressWarnings("WeakerAccess") /* synthetic access */
+    BluetoothLeAudio mLeAudioProfile;
 
     // Route type -> volume map
     private final SparseIntArray mVolumeMap = new SparseIntArray();
@@ -108,6 +112,7 @@
     public void start(UserHandle user) {
         mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
         mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
 
         // Bluetooth on/off broadcasts
         addEventReceiver(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedReceiver());
@@ -119,6 +124,10 @@
                 deviceStateChangedReceiver);
         addEventReceiver(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED,
                 deviceStateChangedReceiver);
+        addEventReceiver(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED,
+                deviceStateChangedReceiver);
+        addEventReceiver(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED,
+                deviceStateChangedReceiver);
 
         mContext.registerReceiverAsUser(mBroadcastReceiver, user,
                 mIntentFilter, null, null);
@@ -240,6 +249,8 @@
                 | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
                 | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
             routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        } else if ((devices & (AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0) {
+            routeType = MediaRoute2Info.TYPE_BLE_HEADSET;
         } else {
             return false;
         }
@@ -288,6 +299,12 @@
             routeId = HEARING_AID_ROUTE_ID_PREFIX + mHearingAidProfile.getHiSyncId(device);
             type = MediaRoute2Info.TYPE_HEARING_AID;
         }
+        if (mLeAudioProfile != null
+                && mLeAudioProfile.getConnectedDevices().contains(device)) {
+            newBtRoute.connectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
+            routeId = LE_AUDIO_ROUTE_ID_PREFIX + mLeAudioProfile.getGroupId(device);
+            type = MediaRoute2Info.TYPE_BLE_HEADSET;
+        }
 
         // Current volume will be set when connected.
         newBtRoute.route = new MediaRoute2Info.Builder(routeId, deviceName)
@@ -358,11 +375,7 @@
         }
     }
 
-    private void addActiveHearingAidDevices(BluetoothDevice device) {
-        if (DEBUG) {
-            Log.d(TAG, "Setting active hearing aid devices. device=" + device);
-        }
-
+    private void addActiveDevices(BluetoothDevice device) {
         // Let the given device be the first active device
         BluetoothRouteInfo activeBtRoute = mBluetoothRoutes.get(device.getAddress());
         addActiveRoute(activeBtRoute);
@@ -376,6 +389,21 @@
             }
         }
     }
+    private void addActiveHearingAidDevices(BluetoothDevice device) {
+        if (DEBUG) {
+            Log.d(TAG, "Setting active hearing aid devices. device=" + device);
+        }
+
+        addActiveDevices(device);
+    }
+
+    private void addActiveLeAudioDevices(BluetoothDevice device) {
+        if (DEBUG) {
+            Log.d(TAG, "Setting active le audio devices. device=" + device);
+        }
+
+        addActiveDevices(device);
+    }
 
     interface BluetoothRoutesUpdatedListener {
         void onBluetoothRoutesUpdated(@NonNull List<MediaRoute2Info> routes);
@@ -392,6 +420,11 @@
             if (connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
                 return MediaRoute2Info.TYPE_HEARING_AID;
             }
+
+            if (connectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
+                return MediaRoute2Info.TYPE_BLE_HEADSET;
+            }
+
             return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
         }
     }
@@ -410,6 +443,10 @@
                     mHearingAidProfile = (BluetoothHearingAid) proxy;
                     activeDevices = mHearingAidProfile.getActiveDevices();
                     break;
+                case BluetoothProfile.LE_AUDIO:
+                    mLeAudioProfile = (BluetoothLeAudio) proxy;
+                    activeDevices = mLeAudioProfile.getActiveDevices();
+                    break;
                 default:
                     return;
             }
@@ -434,6 +471,9 @@
                 case BluetoothProfile.HEARING_AID:
                     mHearingAidProfile = null;
                     break;
+                case BluetoothProfile.LE_AUDIO:
+                    mLeAudioProfile = null;
+                    break;
                 default:
                     return;
             }
@@ -490,12 +530,22 @@
                     }
                     notifyBluetoothRoutesUpdated();
                     break;
+                case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
+                    clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLE_HEADSET);
+                    if (device != null) {
+                        addActiveLeAudioDevices(device);
+                    }
+                    notifyBluetoothRoutesUpdated();
+                    break;
                 case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                     handleConnectionStateChanged(BluetoothProfile.A2DP, intent, device);
                     break;
                 case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
                     handleConnectionStateChanged(BluetoothProfile.HEARING_AID, intent, device);
                     break;
+                case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
+                    handleConnectionStateChanged(BluetoothProfile.LE_AUDIO, intent, device);
+                    break;
             }
         }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 84be7f5..20687c6 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -4073,7 +4073,7 @@
         if (hasRestrictedModeAccess(uid)) {
             uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
         } else {
-            uidBlockedState.allowedReasons &= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
+            uidBlockedState.allowedReasons &= ~ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
         }
         uidBlockedState.updateEffectiveBlockedReasons();
         if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
diff --git a/services/core/java/com/android/server/pm/dex/OWNERS b/services/core/java/com/android/server/pm/dex/OWNERS
index 5a4431e..052a4ca 100644
--- a/services/core/java/com/android/server/pm/dex/OWNERS
+++ b/services/core/java/com/android/server/pm/dex/OWNERS
@@ -1,2 +1,3 @@
-calin@google.com
+alanstokes@google.com
+jiakaiz@google.com
 ngeoffray@google.com
diff --git a/startop/OWNERS b/startop/OWNERS
index 2d1eb38..11d5ad0 100644
--- a/startop/OWNERS
+++ b/startop/OWNERS
@@ -1,7 +1,2 @@
-# mailing list: startop-eng@google.com
-calin@google.com
-chriswailes@google.com
-eholk@google.com
-iam@google.com
-mathieuc@google.com
-yawanng@google.com
+include platform/art:/OWNERS
+keunyoung@google.com
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.bp b/tests/DynamicCodeLoggerIntegrationTests/Android.bp
new file mode 100644
index 0000000..448d46f
--- /dev/null
+++ b/tests/DynamicCodeLoggerIntegrationTests/Android.bp
@@ -0,0 +1,60 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_test_helper_library {
+    name: "DynamicCodeLoggerTestLibrary",
+    srcs: ["src/com/android/dcl/**/*.java"],
+
+}
+
+cc_library_shared {
+    name: "DynamicCodeLoggerNativeTestLibrary",
+    srcs: ["src/cpp/com_android_dcl_Jni.cpp"],
+    header_libs: ["jni_headers"],
+    sdk_version: "28",
+    stl: "c++_static",
+}
+
+cc_binary {
+    name: "DynamicCodeLoggerNativeExecutable",
+    srcs: ["src/cpp/test_executable.cpp"],
+}
+
+android_test {
+    name: "DynamicCodeLoggerIntegrationTests",
+
+    sdk_version: "current",
+    test_suites: ["device-tests"],
+    certificate: "shared",
+    srcs: ["src/com/android/server/pm/**/*.java"],
+
+    static_libs: [
+        "androidx.test.rules",
+        "truth-prebuilt",
+    ],
+
+    compile_multilib: "both",
+    jni_libs: ["DynamicCodeLoggerNativeTestLibrary"],
+
+    java_resources: [
+        ":DynamicCodeLoggerTestLibrary",
+        ":DynamicCodeLoggerNativeExecutable",
+    ],
+}
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
deleted file mode 100644
index dab8304..0000000
--- a/tests/DynamicCodeLoggerIntegrationTests/Android.mk
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-# Build a tiny library that the test app can dynamically load
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DynamicCodeLoggerTestLibrary
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/dcl)
-
-include $(BUILD_JAVA_LIBRARY)
-
-dynamiccodeloggertest_jar := $(LOCAL_BUILT_MODULE)
-
-
-# Also build a native library that the test app can dynamically load
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DynamicCodeLoggerNativeTestLibrary
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SRC_FILES := src/cpp/com_android_dcl_Jni.cpp
-LOCAL_HEADER_LIBRARIES := jni_headers
-LOCAL_SDK_VERSION := 28
-LOCAL_NDK_STL_VARIANT := c++_static
-
-include $(BUILD_SHARED_LIBRARY)
-
-# And a standalone native executable that we can exec.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DynamicCodeLoggerNativeExecutable
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SRC_FILES := src/cpp/test_executable.cpp
-
-include $(BUILD_EXECUTABLE)
-
-dynamiccodeloggertest_executable := $(LOCAL_BUILT_MODULE)
-
-# Build the test app itself
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := DynamicCodeLoggerIntegrationTests
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_CERTIFICATE := shared
-LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/server/pm)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    truth-prebuilt \
-
-# Include both versions of the .so if we have 2 arch
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := \
-    DynamicCodeLoggerNativeTestLibrary \
-
-# This gets us the javalib.jar built by DynamicCodeLoggerTestLibrary above as well as the various
-# native binaries.
-LOCAL_JAVA_RESOURCE_FILES := \
-    $(dynamiccodeloggertest_jar) \
-    $(dynamiccodeloggertest_executable) \
-
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-include $(BUILD_PACKAGE)
diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 883c172..5430dee 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -114,7 +114,8 @@
         // Obtained via "echo -n copied.jar | sha256sum"
         String expectedNameHash =
                 "1B6C71DB26F36582867432CCA12FB6A517470C9F9AABE9198DD4C5C030D6DC0C";
-        String expectedContentHash = copyAndHashResource("/javalib.jar", privateCopyFile);
+        String expectedContentHash = copyAndHashResource(
+                "/DynamicCodeLoggerTestLibrary.jar", privateCopyFile);
 
         // Feed the jar to a class loader and make sure it contains what we expect.
         ClassLoader parentClassLoader = sContext.getClass().getClassLoader();
@@ -135,7 +136,8 @@
         File privateCopyFile = privateFile("copied2.jar");
         String expectedNameHash =
                 "202158B6A3169D78F1722487205A6B036B3F2F5653FDCFB4E74710611AC7EB93";
-        String expectedContentHash = copyAndHashResource("/javalib.jar", privateCopyFile);
+        String expectedContentHash = copyAndHashResource(
+                "/DynamicCodeLoggerTestLibrary.jar", privateCopyFile);
 
         // This time make sure an unknown class loader is an ancestor of the class loader we use.
         ClassLoader knownClassLoader = sContext.getClass().getClassLoader();
diff --git a/tests/LockTaskTests/Android.bp b/tests/LockTaskTests/Android.bp
new file mode 100644
index 0000000..dce681e
--- /dev/null
+++ b/tests/LockTaskTests/Android.bp
@@ -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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_app {
+    name: "LockTaskTests",
+
+    privileged: true,
+
+    sdk_version: "current",
+    certificate: "platform",
+
+    srcs: [
+        "src/**/I*.aidl",
+        "src/**/*.java",
+    ],
+
+}
diff --git a/tests/LockTaskTests/Android.mk b/tests/LockTaskTests/Android.mk
deleted file mode 100644
index 5406ee1..0000000
--- a/tests/LockTaskTests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app
-
-LOCAL_PACKAGE_NAME := LockTaskTests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-Iaidl-files-under, src) $(call all-java-files-under, src)
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
index 7cda977..5d639f6 100644
--- a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
+++ b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
@@ -409,10 +409,10 @@
         sleepIfYouCan(500);
 
         L("Parceling notifications...");
-        // we want to be able to use this test on older OSes that do not have getBlobAshmemSize
-        Method getBlobAshmemSize = null;
+        // we want to be able to use this test on older OSes that do not have getOpenAshmemSize
+        Method getOpenAshmemSize = null;
         try {
-            getBlobAshmemSize = Parcel.class.getMethod("getBlobAshmemSize");
+            getOpenAshmemSize = Parcel.class.getMethod("getOpenAshmemSize");
         } catch (NoSuchMethodException ex) {
         }
         for (int i=0; i<mNotifications.size(); i++) {
@@ -424,8 +424,8 @@
                 time = SystemClock.currentThreadTimeMillis() - time;
                 L("  %s: write parcel=%dms size=%d ashmem=%s",
                         summarize(n), time, p.dataPosition(),
-                        (getBlobAshmemSize != null)
-                            ? getBlobAshmemSize.invoke(p)
+                        (getOpenAshmemSize != null)
+                            ? getOpenAshmemSize.invoke(p)
                             : "???");
                 p.setDataPosition(0);
             }