summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Laurent <elaurent@google.com> 2023-10-03 14:04:03 +0000
committer Eric Laurent <elaurent@google.com> 2023-11-02 16:41:44 +0100
commitcf27729f2de9d12260175a44491facfad903594c (patch)
tree4e0c7fb2280356a049047ffeded2cfe41987fbe0
parent8f752e79094d9a5bb819e0824630b73ebc3eae4a (diff)
AudioService: Allow late Bluetooth profile service connection
If a Bluetooth device is connected by the Bluetooth stack before the corresponding profile service proxy has been initialized via the onServiceConnected callback, ignore the connecion request. When the service connection is received later, query the Bluetooth adapter for active devices on this profile and connected it. Also move resetting forced usage for media upon LE devices connection from AudioDeviceInventory.setBluetoothActiveDevice() to makeLeAudioDeviceAvailable() for consistency with A2DP. Bug: 295985930 Test: quickly disable/enable Bluetooth and verify music playback Change-Id: If598db52061417c8973bed506a689c92825b798a
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java10
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java8
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java87
3 files changed, 76 insertions, 29 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 2336753c88f9..28970750a5ac 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1765,6 +1765,14 @@ public class AudioDeviceBroker {
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
+ if (btInfo.mState == BluetoothProfile.STATE_CONNECTED
+ && !mBtHelper.isProfilePoxyConnected(btInfo.mProfile)) {
+ AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
+ "msg: MSG_L_SET_BT_ACTIVE_DEVICE "
+ + "received with null profile proxy: "
+ + btInfo)).printLog(TAG));
+ return;
+ }
@AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
mBtHelper.getA2dpCodecWithFallbackToSBC(
btInfo.mDevice, "MSG_L_SET_BT_ACTIVE_DEVICE");
@@ -1909,7 +1917,7 @@ public class AudioDeviceBroker {
final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
if (btInfo.mDevice == null) break;
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "msg: onBluetoothActiveDeviceChange " + btInfo)).printLog(TAG));
+ "msg: MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT " + btInfo)).printLog(TAG));
synchronized (mDeviceStateLock) {
mDeviceInventory.setBluetoothActiveDevice(btInfo);
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index d7076899fcb6..e59fd77919c5 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1628,11 +1628,6 @@ public class AudioDeviceInventory {
Log.i(TAG, "setBluetoothActiveDevice " + info.toString() + " delay(ms): " + delay);
}
mDeviceBroker.postBluetoothActiveDevice(info, delay);
- if (info.mProfile == BluetoothProfile.HEARING_AID
- && info.mState == BluetoothProfile.STATE_CONNECTED) {
- mDeviceBroker.setForceUse_Async(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE,
- "HEARING_AID set to CONNECTED");
- }
}
return delay;
}
@@ -2013,6 +2008,9 @@ public class AudioDeviceInventory {
final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType,
AudioSystem.DEVICE_OUT_HEARING_AID);
mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, streamType);
+
+ mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
+
AudioDeviceAttributes ada = new AudioDeviceAttributes(
AudioSystem.DEVICE_OUT_HEARING_AID, address, name);
mAudioSystem.setDeviceConnectionState(ada,
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 7d7e6d000f62..cce6bd2938d1 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -43,7 +43,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.utils.EventLogger;
import java.io.PrintWriter;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -288,6 +287,13 @@ public class BtHelper {
if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE,
android.bluetooth.BluetoothDevice.class);
+ if (btDevice != null && !isProfilePoxyConnected(BluetoothProfile.HEADSET)) {
+ AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
+ "onReceiveBtEvent ACTION_ACTIVE_DEVICE_CHANGED "
+ + "received with null profile proxy for device: "
+ + btDevice)).printLog(TAG));
+ return;
+ }
onSetBtScoActiveDevice(btDevice);
} else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
@@ -465,7 +471,8 @@ public class BtHelper {
@GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
/*package*/ synchronized void onBtProfileDisconnected(int profile) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
- "BT profile " + BluetoothProfile.getProfileName(profile) + " disconnected"));
+ "BT profile " + BluetoothProfile.getProfileName(profile)
+ + " disconnected").printLog(TAG));
switch (profile) {
case BluetoothProfile.HEADSET:
mBluetoothHeadset = null;
@@ -496,7 +503,11 @@ public class BtHelper {
/*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"BT profile " + BluetoothProfile.getProfileName(profile) + " connected to proxy "
- + proxy));
+ + proxy).printLog(TAG));
+ if (proxy == null) {
+ Log.e(TAG, "onBtProfileConnected: null proxy for profile: " + profile);
+ return;
+ }
switch (profile) {
case BluetoothProfile.HEADSET:
onHeadsetProfileConnected((BluetoothHeadset) proxy);
@@ -522,36 +533,64 @@ public class BtHelper {
}
// this part is only for A2DP, LE Audio unicast and Hearing aid
- final List<BluetoothDevice> deviceList = proxy.getConnectedDevices();
- if (deviceList.isEmpty()) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter == null) {
+ Log.e(TAG, "onBtProfileConnected: Null BluetoothAdapter when connecting profile: "
+ + BluetoothProfile.getProfileName(profile));
return;
}
- final BluetoothDevice btDevice = deviceList.get(0);
- if (proxy.getConnectionState(btDevice) == BluetoothProfile.STATE_CONNECTED) {
- mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
- new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
- new BluetoothProfileConnectionInfo(profile),
- "mBluetoothProfileServiceListener"));
- } else {
- mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
- new AudioDeviceBroker.BtDeviceChangedData(null, btDevice,
- new BluetoothProfileConnectionInfo(profile),
- "mBluetoothProfileServiceListener"));
+ List<BluetoothDevice> activeDevices = adapter.getActiveDevices(profile);
+ if (activeDevices.isEmpty() || activeDevices.get(0) == null) {
+ return;
+ }
+ AudioDeviceBroker.BtDeviceChangedData data = new AudioDeviceBroker.BtDeviceChangedData(
+ activeDevices.get(0), null, new BluetoothProfileConnectionInfo(profile),
+ "mBluetoothProfileServiceListener");
+ AudioDeviceBroker.BtDeviceInfo info =
+ mDeviceBroker.createBtDeviceInfo(data, activeDevices.get(0),
+ BluetoothProfile.STATE_CONNECTED);
+ mDeviceBroker.postBluetoothActiveDevice(info, 0 /* delay */);
+ }
+
+ // @GuardedBy("mDeviceBroker.mSetModeLock")
+ @GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
+ /*package*/ synchronized boolean isProfilePoxyConnected(int profile) {
+ switch (profile) {
+ case BluetoothProfile.HEADSET:
+ return mBluetoothHeadset != null;
+ case BluetoothProfile.A2DP:
+ return mA2dp != null;
+ case BluetoothProfile.HEARING_AID:
+ return mHearingAid != null;
+ case BluetoothProfile.LE_AUDIO:
+ return mLeAudio != null;
+ case BluetoothProfile.A2DP_SINK:
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ default:
+ // return true for profiles that are not managed by the BtHelper because
+ // the fact that the profile proxy is not connected does not affect
+ // the device connection handling.
+ return true;
}
}
// @GuardedBy("mDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
- private void onHeadsetProfileConnected(BluetoothHeadset headset) {
+ private void onHeadsetProfileConnected(@NonNull BluetoothHeadset headset) {
// Discard timeout message
mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
mBluetoothHeadset = headset;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- List<BluetoothDevice> activeDevices = Collections.emptyList();
if (adapter != null) {
- activeDevices = adapter.getActiveDevices(BluetoothProfile.HEADSET);
+ List<BluetoothDevice> activeDevices =
+ adapter.getActiveDevices(BluetoothProfile.HEADSET);
+ if (activeDevices.size() > 0 && activeDevices.get(0) != null) {
+ onSetBtScoActiveDevice(activeDevices.get(0));
+ }
+ } else {
+ Log.e(TAG, "onHeadsetProfileConnected: Null BluetoothAdapter");
}
- onSetBtScoActiveDevice((activeDevices.size() > 0) ? activeDevices.get(0) : null);
+
// Refresh SCO audio state
checkScoAudioState();
if (mScoAudioState != SCO_STATE_ACTIVATE_REQ
@@ -559,7 +598,7 @@ public class BtHelper {
return;
}
boolean status = false;
- if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
+ if (mBluetoothHeadsetDevice != null) {
switch (mScoAudioState) {
case SCO_STATE_ACTIVATE_REQ:
status = connectBluetoothScoAudioHelper(
@@ -715,7 +754,8 @@ public class BtHelper {
case BluetoothProfile.LE_AUDIO_BROADCAST:
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"BT profile service: connecting "
- + BluetoothProfile.getProfileName(profile) + " profile"));
+ + BluetoothProfile.getProfileName(profile)
+ + " profile").printLog(TAG));
mDeviceBroker.postBtProfileConnected(profile, proxy);
break;
@@ -734,7 +774,8 @@ public class BtHelper {
case BluetoothProfile.LE_AUDIO_BROADCAST:
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"BT profile service: disconnecting "
- + BluetoothProfile.getProfileName(profile) + " profile"));
+ + BluetoothProfile.getProfileName(profile)
+ + " profile").printLog(TAG));
mDeviceBroker.postBtProfileDisconnected(profile);
break;