Merge "create library for mainline module"
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 385c407..cd41e58 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10633,7 +10633,7 @@
     method public int getPduSessionId();
     method public int getProtocolType();
     method public long getRetryDurationMillis();
-    method @Nullable public android.telephony.data.SliceInfo getSliceInfo();
+    method @Nullable public android.telephony.data.NetworkSliceInfo getSliceInfo();
     method @Deprecated public int getSuggestedRetryTime();
     method @NonNull public java.util.List<android.telephony.data.TrafficDescriptor> getTrafficDescriptors();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10669,7 +10669,7 @@
     method @NonNull public android.telephony.data.DataCallResponse.Builder setPduSessionId(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
-    method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
+    method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.NetworkSliceInfo);
     method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setTrafficDescriptors(@NonNull java.util.List<android.telephony.data.TrafficDescriptor>);
   }
@@ -10742,7 +10742,7 @@
     method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
-    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @Nullable android.telephony.data.TrafficDescriptor, boolean, @NonNull android.telephony.data.DataServiceCallback);
+    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.NetworkSliceInfo, @Nullable android.telephony.data.TrafficDescriptor, boolean, @NonNull android.telephony.data.DataServiceCallback);
   }
 
   public class DataServiceCallback {
@@ -10772,6 +10772,32 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.EpsBearerQosSessionAttributes> CREATOR;
   }
 
+  public final class NetworkSliceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator();
+    method public int getMappedHplmnSliceServiceType();
+    method @IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getSliceDifferentiator();
+    method public int getSliceServiceType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.NetworkSliceInfo> CREATOR;
+    field public static final int MAX_SLICE_DIFFERENTIATOR = 16777214; // 0xfffffe
+    field public static final int MIN_SLICE_DIFFERENTIATOR = -1; // 0xffffffff
+    field public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; // 0xffffffff
+    field public static final int SLICE_SERVICE_TYPE_EMBB = 1; // 0x1
+    field public static final int SLICE_SERVICE_TYPE_MIOT = 3; // 0x3
+    field public static final int SLICE_SERVICE_TYPE_NONE = 0; // 0x0
+    field public static final int SLICE_SERVICE_TYPE_URLLC = 2; // 0x2
+  }
+
+  public static final class NetworkSliceInfo.Builder {
+    ctor public NetworkSliceInfo.Builder();
+    method @NonNull public android.telephony.data.NetworkSliceInfo build();
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceServiceType(int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceDifferentiator(@IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceServiceType(int);
+  }
+
   public final class NrQosSessionAttributes implements android.os.Parcelable android.net.QosSessionAttributes {
     method public int describeContents();
     method @NonNull public java.time.Duration getBitRateWindowDuration();
@@ -10800,32 +10826,6 @@
     method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
   }
 
-  public final class SliceInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator();
-    method public int getMappedHplmnSliceServiceType();
-    method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getSliceDifferentiator();
-    method public int getSliceServiceType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.SliceInfo> CREATOR;
-    field public static final int MAX_SLICE_DIFFERENTIATOR = 16777214; // 0xfffffe
-    field public static final int MIN_SLICE_DIFFERENTIATOR = -1; // 0xffffffff
-    field public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; // 0xffffffff
-    field public static final int SLICE_SERVICE_TYPE_EMBB = 1; // 0x1
-    field public static final int SLICE_SERVICE_TYPE_MIOT = 3; // 0x3
-    field public static final int SLICE_SERVICE_TYPE_NONE = 0; // 0x0
-    field public static final int SLICE_SERVICE_TYPE_URLLC = 2; // 0x2
-  }
-
-  public static final class SliceInfo.Builder {
-    ctor public SliceInfo.Builder();
-    method @NonNull public android.telephony.data.SliceInfo build();
-    method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
-    method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceServiceType(int);
-    method @NonNull public android.telephony.data.SliceInfo.Builder setSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
-    method @NonNull public android.telephony.data.SliceInfo.Builder setSliceServiceType(int);
-  }
-
   public final class ThrottleStatus implements android.os.Parcelable {
     method public int describeContents();
     method public int getApnType();
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
index 75fcab9..6bbe95e 100644
--- a/core/java/android/bluetooth/BluetoothLeAudio.java
+++ b/core/java/android/bluetooth/BluetoothLeAudio.java
@@ -65,9 +65,6 @@
      * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
      * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED =
@@ -82,9 +79,6 @@
      * be null if no device is active. </li>
      * </ul>
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
-     *
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -92,12 +86,148 @@
             "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
 
     /**
+     * Intent used to broadcast group node status information.
+     *
+     * <p>This intent will have 3 extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_NODE_STATUS} - Group node status. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED";
+
+
+    /**
+     * Intent used to broadcast group status information.
+     *
+     * <p>This intent will have 4 extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_STATUS} - Group status. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_GROUP_STATUS_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED";
+
+    /**
+     * Intent used to broadcast group audio configuration changed information.
+     *
+     * <p>This intent will have 5 extra:
+     * <ul>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_DIRECTION} - Direction as bit mask. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_SINK_LOCATION} - Sink location as per Bluetooth Assigned
+     * Numbers </li>
+     * <li> {@link #EXTRA_LE_AUDIO_SOURCE_LOCATION} - Source location as per Bluetooth Assigned
+     * Numbers </li>
+     * <li> {@link #EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS} - Available contexts for group as per
+     * Bluetooth Assigned Numbers </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_CONF_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_CONF_CHANGED";
+
+    /**
+     * Indicates conversation between humans as, for example, in telephony or video calls.
+     * @hide
+     */
+    public static final int CONTEXT_TYPE_COMMUNICATION = 0x0002;
+
+    /**
+     * Indicates media as, for example, in music, public radio, podcast or video soundtrack.
+     * @hide
+     */
+    public static final int CONTEXT_TYPE_MEDIA = 0x0004;
+
+    /**
      * This represents an invalid group ID.
      *
      * @hide
      */
     public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
 
+    /**
+     * Contains group id.
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_ID =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_ID";
+
+    /**
+     * Contains group node status, can be any of
+     * <p>
+     * <ul>
+     * <li> {@link #GROUP_NODE_ADDED} </li>
+     * <li> {@link #GROUP_NODE_REMOVED} </li>
+     * </ul>
+     * <p>
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_NODE_STATUS =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_NODE_STATUS";
+
+    /**
+     * Contains group status, can be any of
+     *
+     * <p>
+     * <ul>
+     * <li> {@link #GROUP_STATUS_IDLE} </li>
+     * <li> {@link #GROUP_STATUS_STREAMING} </li>
+     * <li> {@link #GROUP_STATUS_SUSPENDED} </li>
+     * <li> {@link #GROUP_STATUS_RECONFIGURED} </li>
+     * <li> {@link #GROUP_STATUS_DESTROYED} </li>
+     * </ul>
+     * <p>
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_STATUS =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_STATUS";
+
+    /**
+     * Contains bit mask for direction, bit 0 set when Sink, bit 1 set when Source.
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_DIRECTION =
+            "android.bluetooth.extra.LE_AUDIO_DIRECTION";
+
+    /**
+     * Contains source location as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_SOURCE_LOCATION =
+            "android.bluetooth.extra.LE_AUDIO_SOURCE_LOCATION";
+
+    /**
+     * Contains sink location as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_SINK_LOCATION =
+            "android.bluetooth.extra.LE_AUDIO_SINK_LOCATION";
+
+    /**
+     * Contains available context types for group as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS =
+            "android.bluetooth.extra.LE_AUDIO_AVAILABLE_CONTEXTS";
+
     private BluetoothAdapter mAdapter;
     private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
             new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio",
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 575eb37..00db972 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -665,7 +665,6 @@
      * @hide
      */
     public static boolean hasFileDescriptors(Object value) {
-        getValueType(value); // Will throw if value is not supported
         if (value instanceof LazyValue) {
             return ((LazyValue) value).hasFileDescriptors();
         } else if (value instanceof Parcelable) {
@@ -706,6 +705,8 @@
                     }
                 }
             }
+        } else {
+            getValueType(value); // Will throw if value is not supported
         }
         return false;
     }
diff --git a/core/java/android/util/apk/OWNERS b/core/java/android/util/apk/OWNERS
index 52c9550..0f4e869 100644
--- a/core/java/android/util/apk/OWNERS
+++ b/core/java/android/util/apk/OWNERS
@@ -1 +1,3 @@
 include /core/java/android/content/pm/OWNERS
+cbrubaker@google.com
+mpgroover@google.com
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 8b9a688..515c08d 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -62,7 +62,6 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/un.h>
-#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -837,26 +836,6 @@
   }
 }
 
-static bool NeedsNoRandomizeWorkaround() {
-#if !defined(__arm__)
-    return false;
-#else
-    int major;
-    int minor;
-    struct utsname uts;
-    if (uname(&uts) == -1) {
-        return false;
-    }
-
-    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
-        return false;
-    }
-
-    // Kernels before 3.4.* need the workaround.
-    return (major < 3) || ((major == 3) && (minor < 4));
-#endif
-}
-
 // Utility to close down the Zygote socket file descriptors while
 // the child is still running as root with Zygote's privileges.  Each
 // descriptor (if any) is closed via dup3(), replacing it with a valid
@@ -1687,15 +1666,6 @@
     // runtime.
     runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK;
 
-    if (NeedsNoRandomizeWorkaround()) {
-        // Work around ARM kernel ASLR lossage (http://b/5817320).
-        int old_personality = personality(0xffffffff);
-        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
-        if (new_personality == -1) {
-            ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
-        }
-    }
-
     SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
                     fail_fn);
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d22e97c..8390ae4 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5273,6 +5273,40 @@
         }
     }
 
+    /**
+    * Indicate Le Audio output device connection state change and eventually suppress
+    * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
+    * @param device Bluetooth device connected/disconnected
+    * @param state new connection state (BluetoothProfile.STATE_xxx)
+    * @param suppressNoisyIntent if true the
+    * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
+    * {@hide}
+    */
+    public void setBluetoothLeAudioOutDeviceConnectionState(BluetoothDevice device, int state,
+            boolean suppressNoisyIntent) {
+        final IAudioService service = getService();
+        try {
+            service.setBluetoothLeAudioOutDeviceConnectionState(device, state, suppressNoisyIntent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+    * Indicate Le Audio input connection state change.
+    * @param device Bluetooth device connected/disconnected
+    * @param state new connection state (BluetoothProfile.STATE_xxx)
+    * {@hide}
+    */
+    public void setBluetoothLeAudioInDeviceConnectionState(BluetoothDevice device, int state) {
+        final IAudioService service = getService();
+        try {
+            service.setBluetoothLeAudioInDeviceConnectionState(device, state);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
      /**
      * Indicate A2DP source or sink connection state change and eventually suppress
      * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index ed48b56..73bc428 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -256,6 +256,11 @@
     void setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
             int state, boolean suppressNoisyIntent, int musicDevice);
 
+    void setBluetoothLeAudioOutDeviceConnectionState(in BluetoothDevice device, int state,
+            boolean suppressNoisyIntent);
+
+    void setBluetoothLeAudioInDeviceConnectionState(in BluetoothDevice device, int state);
+
     void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 34fdc1e..c4cb6a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -101,6 +101,7 @@
     private PbapServerProfile mPbapProfile;
     private HearingAidProfile mHearingAidProfile;
     private SapProfile mSapProfile;
+    private VolumeControlProfile mVolumeControlProfile;
 
     /**
      * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -220,6 +221,16 @@
             mSapProfile = new SapProfile(mContext, mDeviceManager, this);
             addProfile(mSapProfile, SapProfile.NAME, BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
         }
+        if (mVolumeControlProfile == null
+                && supportedList.contains(BluetoothProfile.VOLUME_CONTROL)) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding local Volume Control profile");
+            }
+            mVolumeControlProfile = new VolumeControlProfile();
+            // Note: no event handler for VCP, only for being connectable.
+            mProfileNameMap.put(VolumeControlProfile.NAME, mVolumeControlProfile);
+        }
+
         mEventManager.registerProfileIntentReceiver();
     }
 
@@ -565,6 +576,12 @@
             removedProfiles.remove(mSapProfile);
         }
 
+        if (mVolumeControlProfile != null
+                && ArrayUtils.contains(uuids, BluetoothUuid.VOLUME_CONTROL)) {
+            profiles.add(mVolumeControlProfile);
+            removedProfiles.remove(mVolumeControlProfile);
+        }
+
         if (DEBUG) {
             Log.d(TAG,"New Profiles" + profiles.toString());
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
new file mode 100644
index 0000000..511df28
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+
+/**
+ * VolumeControlProfile handles Bluetooth Volume Control Controller role
+ */
+public class VolumeControlProfile implements LocalBluetoothProfile {
+    private static final String TAG = "VolumeControlProfile";
+    static final String NAME = "VCP";
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 23;
+
+    @Override
+    public boolean accessProfileEnabled() {
+        return false;
+    }
+
+    @Override
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    @Override
+    public int getConnectionStatus(BluetoothDevice device) {
+        return BluetoothProfile.STATE_DISCONNECTED; // Settings app doesn't handle VCP
+    }
+
+    @Override
+    public boolean isEnabled(BluetoothDevice device) {
+        return false;
+    }
+
+    @Override
+    public int getConnectionPolicy(BluetoothDevice device) {
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; // Settings app doesn't handle VCP
+    }
+
+    @Override
+    public boolean setEnabled(BluetoothDevice device, boolean enabled) {
+        return false;
+    }
+
+    @Override
+    public boolean isProfileReady() {
+        return true;
+    }
+
+    @Override
+    public int getProfileId() {
+        return BluetoothProfile.VOLUME_CONTROL;
+    }
+
+    public String toString() {
+        return NAME;
+    }
+
+    @Override
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    @Override
+    public int getNameResource(BluetoothDevice device) {
+        return 0; // VCP profile not displayed in UI
+    }
+
+    @Override
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        return 0;   // VCP profile not displayed in UI
+    }
+
+    @Override
+    public int getDrawableResource(BluetoothClass btClass) {
+        // no icon for VCP
+        return 0;
+    }
+}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index cd3d27d..b5e6c11 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -563,6 +563,37 @@
         sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
+    private static final class LeAudioDeviceConnectionInfo {
+        final @NonNull BluetoothDevice mDevice;
+        final @AudioService.BtProfileConnectionState int mState;
+        final boolean mSupprNoisy;
+        final @NonNull String mEventSource;
+
+        LeAudioDeviceConnectionInfo(@NonNull BluetoothDevice device,
+                @AudioService.BtProfileConnectionState int state,
+                boolean suppressNoisyIntent, @NonNull String eventSource) {
+            mDevice = device;
+            mState = state;
+            mSupprNoisy = suppressNoisyIntent;
+            mEventSource = eventSource;
+        }
+    }
+
+    /*package*/ void postBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            boolean suppressNoisyIntent, @NonNull String eventSource) {
+        final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
+                device, state, suppressNoisyIntent, eventSource);
+        sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+    }
+
+    /*package*/ void postBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            @NonNull String eventSource) {
+        final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
+                device, state, false, eventSource);
+        sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+    }
 
     /**
      * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
@@ -849,6 +880,23 @@
                 delay);
     }
 
+    /*package*/ void postSetLeAudioOutConnectionState(
+            @AudioService.BtProfileConnectionState int state,
+            @NonNull BluetoothDevice device, int delay) {
+        sendILMsg(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE, SENDMSG_QUEUE,
+                state,
+                device,
+                delay);
+    }
+
+    /*package*/ void postSetLeAudioInConnectionState(
+            @AudioService.BtProfileConnectionState int state,
+            @NonNull BluetoothDevice device) {
+        sendILMsgNoDelay(MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE, SENDMSG_QUEUE,
+                state,
+                device);
+    }
+
     /*package*/ void postDisconnectA2dp() {
         sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
     }
@@ -1154,7 +1202,20 @@
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.onSetHearingAidConnectionState(
                                 (BluetoothDevice) msg.obj, msg.arg1,
-                                mAudioService.getHearingAidStreamType());
+                                mAudioService.getBluetoothContextualVolumeStream());
+                    }
+                    break;
+                case MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE:
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.onSetLeAudioOutConnectionState(
+                                (BluetoothDevice) msg.obj, msg.arg1,
+                                mAudioService.getBluetoothContextualVolumeStream());
+                    }
+                    break;
+                case MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE:
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.onSetLeAudioInConnectionState(
+                                (BluetoothDevice) msg.obj, msg.arg1);
                     }
                     break;
                 case MSG_BT_HEADSET_CNCT_FAILED:
@@ -1343,6 +1404,31 @@
                     final int capturePreset = msg.arg1;
                     mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
                 } break;
+                case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT: {
+                    final LeAudioDeviceConnectionInfo info =
+                            (LeAudioDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setLeAudioDeviceOutConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " supprNoisy=" + info.mSupprNoisy
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothLeAudioOutDeviceConnectionState(
+                                info.mDevice, info.mState, info.mSupprNoisy);
+                    }
+                } break;
+                case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT: {
+                    final LeAudioDeviceConnectionInfo info =
+                            (LeAudioDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setLeAudioDeviceInConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothLeAudioInDeviceConnectionState(info.mDevice,
+                                info.mState);
+                    }
+                } break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
@@ -1424,6 +1510,11 @@
     private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40;
     private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41;
 
+    private static final int MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE = 42;
+    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;
+
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
             case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
@@ -1439,6 +1530,8 @@
             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
             case MSG_CHECK_MUTE_MUSIC:
+            case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT:
+            case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT:
                 return true;
             default:
                 return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 82586b8..78daabc 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.Intent;
 import android.media.AudioDeviceAttributes;
@@ -423,6 +424,45 @@
         }
     }
 
+    /*package*/ void onSetLeAudioConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state, int streamType, int device) {
+        String address = btDevice.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            address = "";
+        }
+        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "onSetLeAudioConnectionState addr=" + address));
+
+        synchronized (mDevicesLock) {
+            DeviceInfo di = null;
+            boolean isConnected = false;
+
+            String key = DeviceInfo.makeDeviceListKey(device, btDevice.getAddress());
+            di = mConnectedDevices.get(key);
+            isConnected = di != null;
+
+            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+                makeLeAudioDeviceUnavailable(address, device);
+            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+                makeLeAudioDeviceAvailable(address, BtHelper.getName(btDevice), streamType,
+                        device, "onSetLeAudioConnectionState");
+            }
+        }
+    }
+
+    /*package*/ void onSetLeAudioOutConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state, int streamType) {
+        // TODO: b/198610537 clarify DEVICE_OUT_BLE_HEADSET vs DEVICE_OUT_BLE_SPEAKER criteria
+        onSetLeAudioConnectionState(btDevice, state, streamType,
+                AudioSystem.DEVICE_OUT_BLE_HEADSET);
+    }
+
+    /*package*/ void onSetLeAudioInConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state) {
+        onSetLeAudioConnectionState(btDevice, state, AudioSystem.STREAM_DEFAULT,
+                AudioSystem.DEVICE_IN_BLE_HEADSET);
+    }
+
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
         /*package*/ void onBluetoothA2dpActiveDeviceChange(
             @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
@@ -943,6 +983,28 @@
         }
     }
 
+    /*package*/ int setBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            boolean suppressNoisyIntent) {
+        synchronized (mDevicesLock) {
+            /* Active device become null and it's previous device is not connected anymore */
+            int delay = 0;
+            if (!suppressNoisyIntent) {
+                int intState = (state == BluetoothLeAudio.STATE_CONNECTED) ? 1 : 0;
+                delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLE_HEADSET,
+                        intState, AudioSystem.DEVICE_NONE);
+            }
+            mDeviceBroker.postSetLeAudioOutConnectionState(state, device, delay);
+            return delay;
+        }
+    }
+
+    /*package*/ void setBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state) {
+        synchronized (mDevicesLock) {
+            mDeviceBroker.postSetLeAudioInConnectionState(state, device);
+        }
+    }
 
     //-------------------------------------------------------------------
     // Internal utilities
@@ -1115,6 +1177,36 @@
     }
 
     @GuardedBy("mDevicesLock")
+    private void makeLeAudioDeviceAvailable(String address, String name, int streamType, int device,
+            String eventSource) {
+        if (device != AudioSystem.DEVICE_NONE) {
+            AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE,
+                    address, name, AudioSystem.AUDIO_FORMAT_DEFAULT);
+            mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
+                    new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+            mDeviceBroker.postAccessoryPlugMediaUnmute(device);
+        }
+
+        if (streamType == AudioSystem.STREAM_DEFAULT) {
+            // No need to update volume for input devices
+            return;
+        }
+
+        mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
+    }
+
+    @GuardedBy("mDevicesLock")
+    private void makeLeAudioDeviceUnavailable(String address, int device) {
+        if (device != AudioSystem.DEVICE_NONE) {
+            AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                    address, "", AudioSystem.AUDIO_FORMAT_DEFAULT);
+            mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
+        }
+
+        setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
+    }
+
+    @GuardedBy("mDevicesLock")
     private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
         synchronized (mCurAudioRoutes) {
             if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
@@ -1150,6 +1242,7 @@
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
         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);
     }
 
     // must be called before removing the device from mConnectedDevices
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d0a3079..97a20c4 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -163,6 +163,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -307,6 +308,12 @@
     // retry delay in case of failure to indicate system ready to AudioFlinger
     private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
 
+    // Bits representing connected devices to monitor playback monitor voice activity
+    private static final int CONNECTED_STATE_HEARING_AID_BIT = 0;
+    private static final int CONNECTED_STATE_LE_AUDIO_BIT = 1;
+
+    private BitSet mConnectedStateBitset = new BitSet(2);
+
     /** @see AudioSystemThread */
     private AudioSystemThread mAudioSystemThread;
     /** @see AudioHandler */
@@ -2529,7 +2536,7 @@
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 // only modify the hearing aid attenuation when the stream to modify matches
                 // the one expected by the hearing aid
-                if (streamType == getHearingAidStreamType()) {
+                if (streamType == getBluetoothContextualVolumeStream()) {
                     if (DEBUG_VOL) {
                         Log.d(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index="
                                 + newIndex + " stream=" + streamType);
@@ -2872,11 +2879,11 @@
         }
     }
 
-    /*package*/ int getHearingAidStreamType() {
-        return getHearingAidStreamType(mMode);
+    /*package*/ int getBluetoothContextualVolumeStream() {
+        return getBluetoothContextualVolumeStream(mMode);
     }
 
-    private int getHearingAidStreamType(int mode) {
+    private int getBluetoothContextualVolumeStream(int mode) {
         switch (mode) {
             case AudioSystem.MODE_IN_COMMUNICATION:
             case AudioSystem.MODE_IN_CALL:
@@ -2922,7 +2929,7 @@
     }
 
     private void updateHearingAidVolumeOnVoiceActivityUpdate() {
-        final int streamType = getHearingAidStreamType();
+        final int streamType = getBluetoothContextualVolumeStream();
         final int index = getStreamVolume(streamType);
         sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_HEARING_AID,
                 mVoiceActive.get(), streamType, index));
@@ -2954,7 +2961,7 @@
                 return;
         }
 
-        int streamType = getHearingAidStreamType(newMode);
+        int streamType = getBluetoothContextualVolumeStream(newMode);
 
         final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
                 AudioSystem.getDevicesForStream(streamType));
@@ -3036,7 +3043,7 @@
             }
 
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID
-                    && streamType == getHearingAidStreamType()) {
+                    && streamType == getBluetoothContextualVolumeStream()) {
                 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
                         + " stream=" + streamType);
                 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
@@ -5496,15 +5503,68 @@
             throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
                     + " (dis)connection, got " + state);
         }
-        if (state == BluetoothProfile.STATE_CONNECTED) {
-            mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
-        } else {
-            mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
+        synchronized (mConnectedStateBitset) {
+            if (state == BluetoothProfile.STATE_CONNECTED) {
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
+                }
+                mConnectedStateBitset.set(CONNECTED_STATE_HEARING_AID_BIT);
+            } else {
+                mConnectedStateBitset.clear(CONNECTED_STATE_HEARING_AID_BIT);
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
+                }
+            }
         }
         mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
                 device, state, suppressNoisyIntent, musicDevice, "AudioService");
     }
 
+    private void setBluetoothLeAudioDeviceConnectionState(@NonNull BluetoothDevice device,
+            @BtProfileConnectionState int state) {
+        if (device == null) {
+            throw new IllegalArgumentException("Illegal null device");
+        }
+        if (state != BluetoothProfile.STATE_CONNECTED
+                && state != BluetoothProfile.STATE_DISCONNECTED) {
+            throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
+                    + " (dis)connection, got " + state);
+        }
+        synchronized (mConnectedStateBitset) {
+            if (state == BluetoothProfile.STATE_CONNECTED) {
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
+                }
+                mConnectedStateBitset.set(CONNECTED_STATE_LE_AUDIO_BIT);
+            } else {
+                mConnectedStateBitset.clear(CONNECTED_STATE_LE_AUDIO_BIT);
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
+                }
+            }
+        }
+    }
+
+    /**
+     * See AudioManager.setBluetoothLeAudioOutDeviceConnectionState()
+     */
+    public void setBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
+            boolean suppressNoisyIntent) {
+        setBluetoothLeAudioDeviceConnectionState(device, state);
+        mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(device, state,
+                suppressNoisyIntent, "AudioService");
+    }
+
+    /**
+     * See AudioManager.setBluetoothLeAudioInDeviceConnectionState()
+     */
+    public void setBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @BtProfileConnectionState int state) {
+        setBluetoothLeAudioDeviceConnectionState(device, state);
+        mDeviceBroker.postBluetoothLeAudioInDeviceConnectionState(device, state, "AudioService");
+    }
+
     /**
      * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
      */
diff --git a/services/core/java/com/android/server/connectivity/PacProxyService.java b/services/core/java/com/android/server/connectivity/PacProxyService.java
index b2df535..3a97765 100644
--- a/services/core/java/com/android/server/connectivity/PacProxyService.java
+++ b/services/core/java/com/android/server/connectivity/PacProxyService.java
@@ -34,7 +34,6 @@
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteCallbackList;
@@ -42,6 +41,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -357,8 +357,9 @@
                 }
             }
         };
-        mContext.bindService(intent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
+        mContext.bindServiceAsUser(intent, mConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
+                UserHandle.SYSTEM);
 
         intent = new Intent();
         intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE);
@@ -398,9 +399,9 @@
                 }
             }
         };
-        mContext.bindService(intent,
+        mContext.bindServiceAsUser(intent, mProxyConnection,
                 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
-                new HandlerExecutor(mNetThreadHandler), mProxyConnection);
+                mNetThreadHandler, UserHandle.SYSTEM);
     }
 
     private void unbind() {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d78e02b..f2f6b1d 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -176,7 +176,7 @@
         "android.frameworks.stats@1.0",
         "android.system.suspend.control-V1-cpp",
         "android.system.suspend.control.internal-cpp",
-        "android.system.suspend@1.0",
+        "android.system.suspend-V1-ndk",
         "service.incremental",
     ],
 
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 7a6d310..4922b2c 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -18,11 +18,12 @@
 
 //#define LOG_NDEBUG 0
 
+#include <aidl/android/system/suspend/ISystemSuspend.h>
+#include <aidl/android/system/suspend/IWakeLock.h>
 #include <android/hardware/power/1.1/IPower.h>
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
 #include <android/hardware/power/Mode.h>
-#include <android/system/suspend/1.0/ISystemSuspend.h>
 #include <android/system/suspend/ISuspendControlService.h>
 #include <android/system/suspend/internal/ISuspendControlServiceInternal.h>
 #include <nativehelper/JNIHelp.h>
@@ -33,6 +34,7 @@
 #include <limits.h>
 
 #include <android-base/chrono_utils.h>
+#include <android/binder_manager.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
 #include <binder/IServiceManager.h>
@@ -40,23 +42,23 @@
 #include <hardware/power.h>
 #include <hardware_legacy/power.h>
 #include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/misc.h>
-#include <utils/String8.h>
-#include <utils/Log.h>
 
 #include "com_android_server_power_PowerManagerService.h"
 
+using aidl::android::system::suspend::ISystemSuspend;
+using aidl::android::system::suspend::IWakeLock;
+using aidl::android::system::suspend::WakeLockType;
+using android::String8;
 using android::hardware::Return;
 using android::hardware::Void;
 using android::hardware::power::Boost;
 using android::hardware::power::Mode;
-using android::hardware::power::V1_0::PowerHint;
 using android::hardware::power::V1_0::Feature;
-using android::String8;
-using android::system::suspend::V1_0::ISystemSuspend;
-using android::system::suspend::V1_0::IWakeLock;
-using android::system::suspend::V1_0::WakeLockType;
+using android::hardware::power::V1_0::PowerHint;
 using android::system::suspend::ISuspendControlService;
 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
@@ -352,20 +354,21 @@
     }
 }
 
-static sp<ISystemSuspend> gSuspendHal = nullptr;
+static std::shared_ptr<ISystemSuspend> gSuspendHal = nullptr;
 static sp<ISuspendControlService> gSuspendControl = nullptr;
 static sp<system::suspend::internal::ISuspendControlServiceInternal> gSuspendControlInternal =
         nullptr;
-static sp<IWakeLock> gSuspendBlocker = nullptr;
+static std::shared_ptr<IWakeLock> gSuspendBlocker = nullptr;
 static std::mutex gSuspendMutex;
 
 // Assume SystemSuspend HAL is always alive.
 // TODO: Force device to restart if SystemSuspend HAL dies.
-sp<ISystemSuspend> getSuspendHal() {
+std::shared_ptr<ISystemSuspend> getSuspendHal() {
     static std::once_flag suspendHalFlag;
-    std::call_once(suspendHalFlag, [](){
-        ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
-        gSuspendHal = ISystemSuspend::getService();
+    std::call_once(suspendHalFlag, []() {
+        const std::string suspendInstance = std::string() + ISystemSuspend::descriptor + "/default";
+        gSuspendHal = ISystemSuspend::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(suspendInstance.c_str())));
         assert(gSuspendHal != nullptr);
     });
     return gSuspendHal;
@@ -403,7 +406,7 @@
         std::lock_guard<std::mutex> lock(gSuspendMutex);
         if (gSuspendBlocker) {
             gSuspendBlocker->release();
-            gSuspendBlocker.clear();
+            gSuspendBlocker = nullptr;
         }
     }
 }
@@ -411,9 +414,10 @@
 void disableAutoSuspend() {
     std::lock_guard<std::mutex> lock(gSuspendMutex);
     if (!gSuspendBlocker) {
-        sp<ISystemSuspend> suspendHal = getSuspendHal();
-        gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
-                "PowerManager.SuspendLockout");
+        std::shared_ptr<ISystemSuspend> suspendHal = getSuspendHal();
+        suspendHal->acquireWakeLock(WakeLockType::PARTIAL, "PowerManager.SuspendLockout",
+                                    &gSuspendBlocker);
+        assert(gSuspendBlocker != nullptr);
     }
 }
 
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 5ecf6bb..6e01f69 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -79,7 +79,6 @@
 
     // These are not normally accessible from apps so they must be explicitly included.
     jni_libs: [
-        "libbacktrace",
         "libbase",
         "libbinder",
         "libc++",
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 541fc63..2448026 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -55,7 +55,6 @@
     jni_libs: [
         "libdexmakerjvmtiagent",
         "libmultiplejvmtiagentsinterferenceagent",
-        "libbacktrace",
         "libbase",
         "libbinder",
         "libc++",
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index ad57b91..5008307 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -138,7 +138,7 @@
     private final int mPduSessionId;
     private final Qos mDefaultQos;
     private final List<QosBearerSession> mQosBearerSessions;
-    private final SliceInfo mSliceInfo;
+    private final NetworkSliceInfo mSliceInfo;
     private final List<TrafficDescriptor> mTrafficDescriptors;
 
     /**
@@ -201,7 +201,8 @@
             @Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
             @HandoverFailureMode int handoverFailureMode, int pduSessionId,
             @Nullable Qos defaultQos, @Nullable List<QosBearerSession> qosBearerSessions,
-            @Nullable SliceInfo sliceInfo, @Nullable List<TrafficDescriptor> trafficDescriptors) {
+            @Nullable NetworkSliceInfo sliceInfo,
+            @Nullable List<TrafficDescriptor> trafficDescriptors) {
         mCause = cause;
         mSuggestedRetryTime = suggestedRetryTime;
         mId = id;
@@ -254,7 +255,7 @@
         mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
         mQosBearerSessions = new ArrayList<>();
         source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader());
-        mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
+        mSliceInfo = source.readParcelable(NetworkSliceInfo.class.getClassLoader());
         mTrafficDescriptors = new ArrayList<>();
         source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader());
     }
@@ -408,7 +409,7 @@
      * @return The slice info related to this data connection.
      */
     @Nullable
-    public SliceInfo getSliceInfo() {
+    public NetworkSliceInfo getSliceInfo() {
         return mSliceInfo;
     }
 
@@ -620,7 +621,7 @@
 
         private List<QosBearerSession> mQosBearerSessions = new ArrayList<>();
 
-        private SliceInfo mSliceInfo;
+        private NetworkSliceInfo mSliceInfo;
 
         private List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>();
 
@@ -851,13 +852,13 @@
          * The Slice used for this data connection.
          * <p/>
          * If a handover occurs from EPDG to 5G,
-         * this is the {@link SliceInfo} used in {@link DataService#setupDataCall}.
+         * this is the {@link NetworkSliceInfo} used in {@link DataService#setupDataCall}.
          *
          * @param sliceInfo the slice info for the data call
          *
          * @return The same instance of the builder.
          */
-        public @NonNull Builder setSliceInfo(@Nullable SliceInfo sliceInfo) {
+        public @NonNull Builder setSliceInfo(@Nullable NetworkSliceInfo sliceInfo) {
             mSliceInfo = sliceInfo;
             return this;
         }
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index f5f29c6..17e6f32 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -217,7 +217,7 @@
                 boolean isRoaming, boolean allowRoaming,
                 @SetupDataReason int reason,
                 @Nullable LinkProperties linkProperties,
-                @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
+                @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo,
                 @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                 @NonNull DataServiceCallback callback) {
             /* Call the old version since the new version isn't supported */
@@ -414,13 +414,13 @@
         public final int reason;
         public final LinkProperties linkProperties;
         public final int pduSessionId;
-        public final SliceInfo sliceInfo;
+        public final NetworkSliceInfo sliceInfo;
         public final TrafficDescriptor trafficDescriptor;
         public final boolean matchAllRuleAllowed;
         public final IDataServiceCallback callback;
         SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                 boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId,
-                SliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
+                NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
                 boolean matchAllRuleAllowed, IDataServiceCallback callback) {
             this.accessNetworkType = accessNetworkType;
             this.dataProfile = dataProfile;
@@ -707,7 +707,7 @@
         @Override
         public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
                 boolean isRoaming, boolean allowRoaming, int reason,
-                LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+                LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo,
                 TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                 IDataServiceCallback callback) {
             mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 81f5fd3..1346946 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -19,7 +19,7 @@
 import android.net.LinkProperties;
 import android.telephony.data.DataProfile;
 import android.telephony.data.IDataServiceCallback;
-import android.telephony.data.SliceInfo;
+import android.telephony.data.NetworkSliceInfo;
 import android.telephony.data.TrafficDescriptor;
 
 /**
@@ -31,7 +31,7 @@
     void removeDataServiceProvider(int slotId);
     void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
                        boolean allowRoaming, int reason, in LinkProperties linkProperties,
-                       int pduSessionId, in SliceInfo sliceInfo,
+                       int pduSessionId, in NetworkSliceInfo sliceInfo,
                        in TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                        IDataServiceCallback callback);
     void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/NetworkSliceInfo.aidl
similarity index 95%
rename from telephony/java/android/telephony/data/SliceInfo.aidl
rename to telephony/java/android/telephony/data/NetworkSliceInfo.aidl
index 286ea5e..e1a11f2 100644
--- a/telephony/java/android/telephony/data/SliceInfo.aidl
+++ b/telephony/java/android/telephony/data/NetworkSliceInfo.aidl
@@ -17,4 +17,4 @@
 /** @hide */
 package android.telephony.data;
 
-parcelable SliceInfo;
+parcelable NetworkSliceInfo;
diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/NetworkSliceInfo.java
similarity index 91%
rename from telephony/java/android/telephony/data/SliceInfo.java
rename to telephony/java/android/telephony/data/NetworkSliceInfo.java
index 609d111..1d90095 100644
--- a/telephony/java/android/telephony/data/SliceInfo.java
+++ b/telephony/java/android/telephony/data/NetworkSliceInfo.java
@@ -39,7 +39,7 @@
  * @hide
  */
 @SystemApi
-public final class SliceInfo implements Parcelable {
+public final class NetworkSliceInfo implements Parcelable {
     /**
      * When set on a Slice Differentiator, this value indicates that there is no corresponding
      * Slice.
@@ -98,7 +98,7 @@
     @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
     private final int mMappedHplmnSliceDifferentiator;
 
-    private SliceInfo(@SliceServiceType int sliceServiceType,
+    private NetworkSliceInfo(@SliceServiceType int sliceServiceType,
             int sliceDifferentiator, int mappedHplmnSliceServiceType,
             int mappedHplmnSliceDifferentiator) {
         mSliceServiceType = sliceServiceType;
@@ -141,7 +141,7 @@
     }
 
     /**
-     * This Slice Differentiator corresponds to a {@link SliceInfo} (S-NSSAI) of the HPLMN;
+     * This Slice Differentiator corresponds to a {@link NetworkSliceInfo} (S-NSSAI) of the HPLMN;
      * {@link #getSliceDifferentiator()} is mapped to this value.
      * <p/>
      * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true:
@@ -157,7 +157,7 @@
         return mMappedHplmnSliceDifferentiator;
     }
 
-    private SliceInfo(@NonNull Parcel in) {
+    private NetworkSliceInfo(@NonNull Parcel in) {
         mSliceServiceType = in.readInt();
         mSliceDifferentiator = in.readInt();
         mMappedHplmnSliceServiceType = in.readInt();
@@ -177,18 +177,18 @@
         dest.writeInt(mMappedHplmnSliceDifferentiator);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<SliceInfo> CREATOR =
-            new Parcelable.Creator<SliceInfo>() {
+    public static final @android.annotation.NonNull Parcelable.Creator<NetworkSliceInfo> CREATOR =
+            new Parcelable.Creator<NetworkSliceInfo>() {
                 @Override
                 @NonNull
-                public SliceInfo createFromParcel(@NonNull Parcel source) {
-                    return new SliceInfo(source);
+                public NetworkSliceInfo createFromParcel(@NonNull Parcel source) {
+                    return new NetworkSliceInfo(source);
                 }
 
                 @Override
                 @NonNull
-                public SliceInfo[] newArray(int size) {
-                    return new SliceInfo[size];
+                public NetworkSliceInfo[] newArray(int size) {
+                    return new NetworkSliceInfo[size];
                 }
             };
 
@@ -222,7 +222,7 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-        SliceInfo sliceInfo = (SliceInfo) o;
+        NetworkSliceInfo sliceInfo = (NetworkSliceInfo) o;
         return mSliceServiceType == sliceInfo.mSliceServiceType
                 && mSliceDifferentiator == sliceInfo.mSliceDifferentiator
                 && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType
@@ -236,7 +236,7 @@
     }
 
     /**
-     * Provides a convenient way to set the fields of a {@link SliceInfo} when creating a
+     * Provides a convenient way to set the fields of a {@link NetworkSliceInfo} when creating a
      * new instance.
      *
      * <p>The example below shows how you might create a new {@code SliceInfo}:
@@ -334,13 +334,13 @@
         }
 
         /**
-         * Build the {@link SliceInfo}.
+         * Build the {@link NetworkSliceInfo}.
          *
-         * @return the {@link SliceInfo} object.
+         * @return the {@link NetworkSliceInfo} object.
          */
         @NonNull
-        public SliceInfo build() {
-            return new SliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
+        public NetworkSliceInfo build() {
+            return new NetworkSliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
                     this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator);
         }
     }