Merge "settingslib/bluetooth: Add LeAudio support"
This commit is contained in:
31
packages/SettingsLib/res/drawable/ic_bt_le_audio.xml
Normal file
31
packages/SettingsLib/res/drawable/ic_bt_le_audio.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user