summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jakub Pawlowski <jpawlowski@google.com> 2021-10-15 09:55:05 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2021-10-15 09:55:05 +0000
commitba8a56e93d618856d61181695a7248cc9dbb4cb9 (patch)
treee45f5af7b4f51a5ba7a53cf3c3f63ca09f9a39f6
parent31a3297733d55e561e4dd863a6c4d787f8caf736 (diff)
parentc0aa3b32763e393afd42cd36dbade934d7e9fd36 (diff)
Merge "settingslib/bluetooth: Add LeAudio support"
-rw-r--r--packages/SettingsLib/res/drawable/ic_bt_le_audio.xml31
-rw-r--r--packages/SettingsLib/res/values/strings.xml6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java52
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java264
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java19
6 files changed, 376 insertions, 2 deletions
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 000000000000..5b52a04e1cf6
--- /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 6b840bd7901d..a56c49088b67 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 cf57ebf6fadb..58d2185ea9e9 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.BluetoothCsipSetCoordinator;
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 @@ public class BluetoothEventManager {
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,
@@ -452,6 +455,9 @@ public class BluetoothEventManager {
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;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 243194188727..021ba2247e67 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.BluetoothClass;
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
if (hearingAidProfile != null) {
mIsActiveDeviceHearingAid = hearingAidProfile.getActiveDevices().contains(mDevice);
}
+ LeAudioProfile leAudio = mProfileManager.getLeAudioProfile();
+ if (leAudio != null) {
+ mIsActiveDeviceLeAudio = leAudio.getActiveDevices().contains(mDevice);
+ }
}
/**
@@ -984,6 +1010,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
hfpConnected = false;
} else if (profile instanceof HearingAidProfile) {
hearingAidConnected = false;
+ } else if (profile instanceof LeAudioProfile) {
+ leAudioConnected = false;
}
}
break;
@@ -1057,7 +1086,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
// 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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
private boolean isProfileConnectedFail() {
return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail
- || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail);
+ || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail)
+ || mIsLeAudioProfileConnectedFail;
}
/**
@@ -1103,6 +1134,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
hfpNotConnected = true;
} else if (profile instanceof HearingAidProfile) {
hearingAidNotConnected = true;
+ } else if (profile instanceof LeAudioProfile) {
+ leAudioNotConnected = true;
}
}
break;
@@ -1166,6 +1200,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
new file mode 100644
index 000000000000..209507ac7088
--- /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 bcb345584ff3..334792048105 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.BluetoothDevice;
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 @@ public class LocalBluetoothProfileManager {
private PbapServerProfile mPbapProfile;
private HearingAidProfile mHearingAidProfile;
private CsipSetCoordinatorProfile mCsipSetCoordinatorProfile;
+ private LeAudioProfile mLeAudioProfile;
private SapProfile mSapProfile;
private VolumeControlProfile mVolumeControlProfile;
@@ -232,6 +234,14 @@ public class LocalBluetoothProfileManager {
// 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 @@ public class LocalBluetoothProfileManager {
return mHearingAidProfile;
}
+ public LeAudioProfile getLeAudioProfile() {
+ return mLeAudioProfile;
+ }
+
SapProfile getSapProfile() {
return mSapProfile;
}
@@ -614,6 +628,11 @@ public class LocalBluetoothProfileManager {
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);