AudioService: change to BT service profile listener events
Put the BT service profile listener events on the AudioDeviceBroker event thread to ensure correct locking order. Bug: 112863932 Test: test enabling / disabling of BT with devices connected Change-Id: I10a79673c7e7ef1dc6250beb8e781f3de242d248
This commit is contained in:
@@ -21,6 +21,8 @@ import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTE
|
||||
import android.annotation.NonNull;
|
||||
import android.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
import android.bluetooth.BluetoothHearingAid;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -424,11 +426,28 @@ import java.util.ArrayList;
|
||||
}
|
||||
|
||||
/*package*/ void postDisconnectHearingAid() {
|
||||
sendMsgNoDelay(MSG_DISCONNECT_HEARING_AID, SENDMSG_QUEUE);
|
||||
sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
|
||||
}
|
||||
|
||||
/*package*/ void postDisconnectHeadset() {
|
||||
sendMsgNoDelay(MSG_DISCONNECT_HEADSET, SENDMSG_QUEUE);
|
||||
sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
|
||||
}
|
||||
|
||||
/*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) {
|
||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile);
|
||||
}
|
||||
|
||||
/*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) {
|
||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile);
|
||||
}
|
||||
|
||||
/*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) {
|
||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile);
|
||||
}
|
||||
|
||||
/*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) {
|
||||
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE,
|
||||
hearingAidProfile);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@@ -460,16 +479,14 @@ import java.util.ArrayList;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mDeviceStateLock")
|
||||
/*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state,
|
||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
|
||||
final int intState = (state == BluetoothA2dp.STATE_CONNECTED)
|
||||
? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED;
|
||||
final int delay;
|
||||
synchronized (mDeviceStateLock) {
|
||||
delay = mDeviceInventory.checkSendBecomingNoisyIntent(
|
||||
final int delay = mDeviceInventory.checkSendBecomingNoisyIntent(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
|
||||
AudioSystem.DEVICE_NONE);
|
||||
}
|
||||
final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress();
|
||||
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
@@ -719,16 +736,36 @@ import java.util.ArrayList;
|
||||
mDeviceInventory.disconnectA2dpSink();
|
||||
}
|
||||
break;
|
||||
case MSG_DISCONNECT_HEARING_AID:
|
||||
case MSG_DISCONNECT_BT_HEARING_AID:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mDeviceInventory.disconnectHearingAid();
|
||||
}
|
||||
break;
|
||||
case MSG_DISCONNECT_HEADSET:
|
||||
case MSG_DISCONNECT_BT_HEADSET:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mBtHelper.disconnectHeadset();
|
||||
}
|
||||
break;
|
||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
|
||||
}
|
||||
break;
|
||||
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.wtf(TAG, "Invalid message " + msg.what);
|
||||
}
|
||||
@@ -766,8 +803,12 @@ import java.util.ArrayList;
|
||||
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
|
||||
private static final int MSG_DISCONNECT_A2DP = 19;
|
||||
private static final int MSG_DISCONNECT_A2DP_SINK = 20;
|
||||
private static final int MSG_DISCONNECT_HEARING_AID = 21;
|
||||
private static final int MSG_DISCONNECT_HEADSET = 22;
|
||||
private static final int MSG_DISCONNECT_BT_HEARING_AID = 21;
|
||||
private static final int MSG_DISCONNECT_BT_HEADSET = 22;
|
||||
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23;
|
||||
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
|
||||
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
|
||||
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
|
||||
|
||||
|
||||
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
||||
|
||||
@@ -393,6 +393,84 @@ public class BtHelper {
|
||||
mBluetoothHeadset = null;
|
||||
}
|
||||
|
||||
/*package*/ synchronized void onA2dpProfileConnected(BluetoothA2dp a2dp) {
|
||||
mA2dp = a2dp;
|
||||
final List<BluetoothDevice> deviceList = mA2dp.getConnectedDevices();
|
||||
if (deviceList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final BluetoothDevice btDevice = deviceList.get(0);
|
||||
final @BluetoothProfile.BtProfileState int state = mA2dp.getConnectionState(btDevice);
|
||||
mDeviceBroker.handleSetA2dpSinkConnectionState(
|
||||
state, new BluetoothA2dpDeviceInfo(btDevice));
|
||||
}
|
||||
|
||||
/*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) {
|
||||
final List<BluetoothDevice> deviceList = profile.getConnectedDevices();
|
||||
if (deviceList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final BluetoothDevice btDevice = deviceList.get(0);
|
||||
final @BluetoothProfile.BtProfileState int state =
|
||||
profile.getConnectionState(btDevice);
|
||||
mDeviceBroker.postSetA2dpSourceConnectionState(
|
||||
state, new BluetoothA2dpDeviceInfo(btDevice));
|
||||
}
|
||||
|
||||
/*package*/ synchronized void onHearingAidProfileConnected(BluetoothHearingAid hearingAid) {
|
||||
mHearingAid = hearingAid;
|
||||
final List<BluetoothDevice> deviceList = mHearingAid.getConnectedDevices();
|
||||
if (deviceList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final BluetoothDevice btDevice = deviceList.get(0);
|
||||
final @BluetoothProfile.BtProfileState int state =
|
||||
mHearingAid.getConnectionState(btDevice);
|
||||
mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
|
||||
btDevice, state,
|
||||
/*suppressNoisyIntent*/ false,
|
||||
/*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
|
||||
/*eventSource*/ "mBluetoothProfileServiceListener");
|
||||
}
|
||||
|
||||
/*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
|
||||
// Discard timeout message
|
||||
mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
|
||||
mBluetoothHeadset = headset;
|
||||
setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
|
||||
// Refresh SCO audio state
|
||||
checkScoAudioState();
|
||||
if (mScoAudioState != SCO_STATE_ACTIVATE_REQ
|
||||
&& mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
|
||||
return;
|
||||
}
|
||||
boolean status = false;
|
||||
if (mBluetoothHeadsetDevice != null) {
|
||||
switch (mScoAudioState) {
|
||||
case SCO_STATE_ACTIVATE_REQ:
|
||||
status = connectBluetoothScoAudioHelper(
|
||||
mBluetoothHeadset,
|
||||
mBluetoothHeadsetDevice, mScoAudioMode);
|
||||
if (status) {
|
||||
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
|
||||
}
|
||||
break;
|
||||
case SCO_STATE_DEACTIVATE_REQ:
|
||||
status = disconnectBluetoothScoAudioHelper(
|
||||
mBluetoothHeadset,
|
||||
mBluetoothHeadsetDevice, mScoAudioMode);
|
||||
if (status) {
|
||||
mScoAudioState = SCO_STATE_DEACTIVATING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
mScoAudioState = SCO_STATE_INACTIVE;
|
||||
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
private void broadcastScoConnectionState(int state) {
|
||||
mDeviceBroker.postBroadcastScoConnectionState(state);
|
||||
@@ -462,99 +540,36 @@ public class BtHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE this listener is NOT called from AudioDeviceBroker event thread, only call async
|
||||
// methods inside listener.
|
||||
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
|
||||
new BluetoothProfile.ServiceListener() {
|
||||
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||
final BluetoothDevice btDevice;
|
||||
List<BluetoothDevice> deviceList;
|
||||
switch(profile) {
|
||||
case BluetoothProfile.A2DP:
|
||||
synchronized (BtHelper.this) {
|
||||
mA2dp = (BluetoothA2dp) proxy;
|
||||
deviceList = mA2dp.getConnectedDevices();
|
||||
if (deviceList.size() > 0) {
|
||||
btDevice = deviceList.get(0);
|
||||
if (btDevice == null) {
|
||||
Log.e(TAG, "Invalid null device in BT profile listener");
|
||||
return;
|
||||
}
|
||||
final @BluetoothProfile.BtProfileState int state =
|
||||
mA2dp.getConnectionState(btDevice);
|
||||
mDeviceBroker.handleSetA2dpSinkConnectionState(
|
||||
state, new BluetoothA2dpDeviceInfo(btDevice));
|
||||
}
|
||||
}
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"BT profile service: connecting A2DP profile"));
|
||||
mDeviceBroker.postBtA2dpProfileConnected((BluetoothA2dp) proxy);
|
||||
break;
|
||||
|
||||
case BluetoothProfile.A2DP_SINK:
|
||||
deviceList = proxy.getConnectedDevices();
|
||||
if (deviceList.size() > 0) {
|
||||
btDevice = deviceList.get(0);
|
||||
final @BluetoothProfile.BtProfileState int state =
|
||||
proxy.getConnectionState(btDevice);
|
||||
mDeviceBroker.postSetA2dpSourceConnectionState(
|
||||
state, new BluetoothA2dpDeviceInfo(btDevice));
|
||||
}
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"BT profile service: connecting A2DP_SINK profile"));
|
||||
mDeviceBroker.postBtA2dpSinkProfileConnected(proxy);
|
||||
break;
|
||||
|
||||
case BluetoothProfile.HEADSET:
|
||||
synchronized (BtHelper.this) {
|
||||
// Discard timeout message
|
||||
mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
|
||||
mBluetoothHeadset = (BluetoothHeadset) proxy;
|
||||
setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
|
||||
// Refresh SCO audio state
|
||||
checkScoAudioState();
|
||||
// Continue pending action if any
|
||||
if (mScoAudioState == SCO_STATE_ACTIVATE_REQ
|
||||
|| mScoAudioState == SCO_STATE_DEACTIVATE_REQ) {
|
||||
boolean status = false;
|
||||
if (mBluetoothHeadsetDevice != null) {
|
||||
switch (mScoAudioState) {
|
||||
case SCO_STATE_ACTIVATE_REQ:
|
||||
status = connectBluetoothScoAudioHelper(
|
||||
mBluetoothHeadset,
|
||||
mBluetoothHeadsetDevice, mScoAudioMode);
|
||||
if (status) {
|
||||
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
|
||||
}
|
||||
break;
|
||||
case SCO_STATE_DEACTIVATE_REQ:
|
||||
status = disconnectBluetoothScoAudioHelper(
|
||||
mBluetoothHeadset,
|
||||
mBluetoothHeadsetDevice, mScoAudioMode);
|
||||
if (status) {
|
||||
mScoAudioState = SCO_STATE_DEACTIVATING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
mScoAudioState = SCO_STATE_INACTIVE;
|
||||
broadcastScoConnectionState(
|
||||
AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"BT profile service: connecting HEADSET profile"));
|
||||
mDeviceBroker.postBtHeasetProfileConnected((BluetoothHeadset) proxy);
|
||||
break;
|
||||
|
||||
case BluetoothProfile.HEARING_AID:
|
||||
synchronized (BtHelper.this) {
|
||||
mHearingAid = (BluetoothHearingAid) proxy;
|
||||
deviceList = mHearingAid.getConnectedDevices();
|
||||
if (deviceList.size() > 0) {
|
||||
btDevice = deviceList.get(0);
|
||||
final @BluetoothProfile.BtProfileState int state =
|
||||
mHearingAid.getConnectionState(btDevice);
|
||||
mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
|
||||
btDevice, state,
|
||||
/*suppressNoisyIntent*/ false,
|
||||
/*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
|
||||
/*eventSource*/ "mBluetoothProfileServiceListener");
|
||||
}
|
||||
}
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"BT profile service: connecting HEARING_AID profile"));
|
||||
mDeviceBroker.postBtHearingAidProfileConnected(
|
||||
(BluetoothHearingAid) proxy);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user