Merge "AudioService: simplify/document locking"

This commit is contained in:
TreeHugger Robot
2019-09-21 01:11:33 +00:00
committed by Android (Google) Code Review
4 changed files with 302 additions and 325 deletions

View File

@@ -57,13 +57,6 @@ import java.io.PrintWriter;
private final @NonNull AudioService mAudioService;
private final @NonNull Context mContext;
/** Forced device usage for communications sent to AudioSystem */
private int mForcedUseForComm;
/**
* Externally reported force device usage state returned by getters: always consistent
* with requests by setters */
private int mForcedUseForCommExt;
// Manages all connected devices, only ever accessed on the message loop
private final AudioDeviceInventory mDeviceInventory;
// Manages notifications to BT service
@@ -71,24 +64,34 @@ import java.io.PrintWriter;
//-------------------------------------------------------------------
// we use a different lock than mDeviceStateLock so as not to create
// lock contention between enqueueing a message and handling them
private static final Object sLastDeviceConnectionMsgTimeLock = new Object();
@GuardedBy("sLastDeviceConnectionMsgTimeLock")
/**
* Lock to guard:
* - any changes to the message queue: enqueueing or removing any message
* - state of A2DP enabled
* - force use for communication + SCO changes
*/
private final Object mDeviceBrokerLock = new Object();
@GuardedBy("mDeviceBrokerLock")
private static long sLastDeviceConnectMsgTime = 0;
// General lock to be taken whenever the state of the audio devices is to be checked or changed
private final Object mDeviceStateLock = new Object();
// Request to override default use of A2DP for media.
@GuardedBy("mDeviceStateLock")
/** Request to override default use of A2DP for media */
@GuardedBy("mDeviceBrokerLock")
private boolean mBluetoothA2dpEnabled;
// lock always taken when accessing AudioService.mSetModeDeathHandlers
// TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
/*package*/ final Object mSetModeLock = new Object();
/** Forced device usage for communications sent to AudioSystem */
@GuardedBy("mDeviceBrokerLock")
private int mForcedUseForComm;
/**
* Externally reported force device usage state returned by getters: always consistent
* with requests by setters */
@GuardedBy("mDeviceBrokerLock")
private int mForcedUseForCommExt;
//-------------------------------------------------------------------
/** Normal constructor used by AudioService */
/*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
mContext = context;
mAudioService = service;
@@ -127,36 +130,37 @@ import java.io.PrintWriter;
// All post* methods are asynchronous
/*package*/ void onSystemReady() {
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.onSystemReady();
}
}
mBtHelper.onSystemReady();
}
/*package*/ void onAudioServerDied() {
// Restore forced usage for communications and record
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
AudioSystem.setParameters(
"BT_SCO=" + (mForcedUseForComm == AudioSystem.FORCE_BT_SCO ? "on" : "off"));
onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied");
onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied");
// restore devices
sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE);
}
// restore devices
sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE);
}
/*package*/ void setForceUse_Async(int useCase, int config, String eventSource) {
sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
useCase, config, eventSource);
synchronized (mDeviceBrokerLock) {
sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE,
useCase, config, eventSource);
}
}
/*package*/ void toggleHdmiIfConnected_Async() {
sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE);
}
}
/*package*/ void disconnectAllBluetoothProfiles() {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
mBtHelper.disconnectAllBluetoothProfiles();
}
}
@@ -168,15 +172,11 @@ import java.io.PrintWriter;
* @param intent
*/
/*package*/ void receiveBtEvent(@NonNull Intent intent) {
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.receiveBtEvent(intent);
}
}
mBtHelper.receiveBtEvent(intent);
}
/*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
if (mBluetoothA2dpEnabled == on) {
return;
}
@@ -196,7 +196,7 @@ import java.io.PrintWriter;
* @return true if speakerphone state changed
*/
/*package*/ boolean setSpeakerphoneOn(boolean on, String eventSource) {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
final boolean wasOn = isSpeakerphoneOn();
if (on) {
if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
@@ -214,7 +214,7 @@ import java.io.PrintWriter;
}
/*package*/ boolean isSpeakerphoneOn() {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
}
}
@@ -223,9 +223,7 @@ import java.io.PrintWriter;
@AudioService.ConnectionState int state, String address, String name,
String caller) {
//TODO move logging here just like in setBluetooth* methods
synchronized (mDeviceStateLock) {
mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller);
}
mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller);
}
private static final class BtDeviceConnectionInfo {
@@ -259,27 +257,24 @@ import java.io.PrintWriter;
final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
suppressNoisyIntent, a2dpVolume);
// when receiving a request to change the connection state of a device, this last request
// is the source of truth, so cancel all previous requests
removeAllA2dpConnectionEvents(device);
synchronized (mDeviceBrokerLock) {
// when receiving a request to change the connection state of a device, this last
// request is the source of truth, so cancel all previous requests
mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
device);
mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
device);
mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
device);
mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
device);
sendLMsgNoDelay(
state == BluetoothProfile.STATE_CONNECTED
? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION
: MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
SENDMSG_QUEUE, info);
}
/** remove all previously scheduled connection and disconnection events for the given device */
private void removeAllA2dpConnectionEvents(@NonNull BluetoothDevice device) {
mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
device);
mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
device);
mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
device);
mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
device);
sendLMsgNoDelay(
state == BluetoothProfile.STATE_CONNECTED
? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION
: MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
SENDMSG_QUEUE, info);
}
}
private static final class HearingAidDeviceConnectionInfo {
@@ -305,25 +300,27 @@ import java.io.PrintWriter;
boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo(
device, state, suppressNoisyIntent, musicDevice, eventSource);
sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
synchronized (mDeviceBrokerLock) {
sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
}
}
// never called by system components
/*package*/ void setBluetoothScoOnByApp(boolean on) {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
}
}
/*package*/ boolean isBluetoothScoOnForApp() {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO;
}
}
/*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
//Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
if (on) {
// do not accept SCO ON if SCO audio is not connected
if (!mBtHelper.isBluetoothScoOn()) {
@@ -346,58 +343,55 @@ import java.io.PrintWriter;
}
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
synchronized (mDeviceStateLock) {
return mDeviceInventory.startWatchingRoutes(observer);
}
return mDeviceInventory.startWatchingRoutes(observer);
}
/*package*/ AudioRoutesInfo getCurAudioRoutes() {
synchronized (mDeviceStateLock) {
return mDeviceInventory.getCurAudioRoutes();
}
return mDeviceInventory.getCurAudioRoutes();
}
/*package*/ boolean isAvrcpAbsoluteVolumeSupported() {
synchronized (mDeviceStateLock) {
return mBtHelper.isAvrcpAbsoluteVolumeSupported();
}
return mBtHelper.isAvrcpAbsoluteVolumeSupported();
}
/*package*/ boolean isBluetoothA2dpOn() {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
return mBluetoothA2dpEnabled;
}
}
/*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) {
sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index);
synchronized (mDeviceBrokerLock) {
sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index);
}
}
/*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) {
sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
synchronized (mDeviceBrokerLock) {
sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
}
}
/*package*/ void postDisconnectBluetoothSco(int exceptPid) {
sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid);
synchronized (mDeviceBrokerLock) {
sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid);
}
}
/*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device);
synchronized (mDeviceBrokerLock) {
sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device);
}
}
@GuardedBy("mSetModeLock")
/*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode,
@NonNull String eventSource) {
synchronized (mDeviceStateLock) {
mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource);
}
mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource);
}
@GuardedBy("mSetModeLock")
/*package*/ void stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource) {
synchronized (mDeviceStateLock) {
mBtHelper.stopBluetoothScoForClient(cb, eventSource);
}
mBtHelper.stopBluetoothScoForClient(cb, eventSource);
}
//---------------------------------------------------------------------
@@ -460,77 +454,109 @@ import java.io.PrintWriter;
//---------------------------------------------------------------------
// Message handling on behalf of helper classes
/*package*/ void postBroadcastScoConnectionState(int state) {
sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state);
synchronized (mDeviceBrokerLock) {
sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state);
}
}
/*package*/ void postBroadcastBecomingNoisy() {
sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
}
}
/*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state,
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
sendILMsg(state == BluetoothA2dp.STATE_CONNECTED
? MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED
: MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
SENDMSG_QUEUE,
state, btDeviceInfo, delay);
synchronized (mDeviceBrokerLock) {
sendILMsg(state == BluetoothA2dp.STATE_CONNECTED
? MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED
: MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
SENDMSG_QUEUE,
state, btDeviceInfo, delay);
}
}
/*package*/ void postA2dpSourceConnection(@AudioService.BtProfileConnectionState int state,
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE,
state, btDeviceInfo, delay);
synchronized (mDeviceBrokerLock) {
sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE,
state, btDeviceInfo, delay);
}
}
/*package*/ void postSetWiredDeviceConnectionState(
AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) {
sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay);
synchronized (mDeviceBrokerLock) {
sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE,
connectionState, delay);
}
}
/*package*/ void postSetHearingAidConnectionState(
@AudioService.BtProfileConnectionState int state,
@NonNull BluetoothDevice device, int delay) {
sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE,
state,
device,
delay);
synchronized (mDeviceBrokerLock) {
sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE,
state,
device,
delay);
}
}
/*package*/ void postDisconnectA2dp() {
sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
}
}
/*package*/ void postDisconnectA2dpSink() {
sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE);
}
}
/*package*/ void postDisconnectHearingAid() {
sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
}
}
/*package*/ void postDisconnectHeadset() {
sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
}
}
/*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) {
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile);
synchronized (mDeviceBrokerLock) {
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);
synchronized (mDeviceBrokerLock) {
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);
synchronized (mDeviceBrokerLock) {
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);
synchronized (mDeviceBrokerLock) {
sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE,
hearingAidProfile);
}
}
/*package*/ void postScoClientDied(Object obj) {
sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
synchronized (mDeviceBrokerLock) {
sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
}
}
//---------------------------------------------------------------------
@@ -545,7 +571,7 @@ import java.io.PrintWriter;
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
.append(Binder.getCallingPid()).append(" src:").append(source).toString();
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
mBluetoothA2dpEnabled = on;
mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE);
onSetForceUse(
@@ -557,71 +583,85 @@ import java.io.PrintWriter;
/*package*/ boolean handleDeviceConnection(boolean connect, int device, String address,
String deviceName) {
synchronized (mDeviceStateLock) {
return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName);
}
return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName);
}
/*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state,
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state,
btDeviceInfo);
synchronized (mDeviceBrokerLock) {
sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state,
btDeviceInfo);
}
}
/*package*/ void handleFailureToConnectToBtHeadsetService(int delay) {
sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
synchronized (mDeviceBrokerLock) {
sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay);
}
}
/*package*/ void handleCancelFailureToConnectToBtHeadsetService() {
mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
synchronized (mDeviceBrokerLock) {
mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
}
}
/*package*/ void postReportNewRoutes() {
sendMsgNoDelay(MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
synchronized (mDeviceBrokerLock) {
sendMsgNoDelay(MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
}
}
/*package*/ void cancelA2dpDockTimeout() {
mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
synchronized (mDeviceBrokerLock) {
mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
}
}
// FIXME: used by?
/*package*/ void postA2dpActiveDeviceChange(
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
synchronized (mDeviceBrokerLock) {
sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
}
}
/*package*/ boolean hasScheduledA2dpDockTimeout() {
return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
synchronized (mDeviceBrokerLock) {
return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
}
}
// must be called synchronized on mConnectedDevices
/*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
return (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
new BtHelper.BluetoothA2dpDeviceInfo(btDevice))
|| mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
new BtHelper.BluetoothA2dpDeviceInfo(btDevice)));
}
/*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) {
sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
}
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
synchronized (mDeviceStateLock) {
mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
synchronized (mDeviceBrokerLock) {
return (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
new BtHelper.BluetoothA2dpDeviceInfo(btDevice))
|| mBrokerHandler.hasMessages(
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
new BtHelper.BluetoothA2dpDeviceInfo(btDevice)));
}
}
/*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) {
synchronized (mDeviceBrokerLock) {
sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
}
}
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
}
/*package*/ boolean getBluetoothA2dpEnabled() {
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
return mBluetoothA2dpEnabled;
}
}
/*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) {
synchronized (mDeviceStateLock) {
return mBtHelper.getA2dpCodec(device);
}
return mBtHelper.getA2dpCodec(device);
}
/*package*/ void dump(PrintWriter pw, String prefix) {
@@ -709,68 +749,50 @@ import java.io.PrintWriter;
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESTORE_DEVICES:
synchronized (mDeviceStateLock) {
mDeviceInventory.onRestoreDevices();
mBtHelper.onAudioServerDiedRestoreA2dp();
}
mDeviceInventory.onRestoreDevices();
mBtHelper.onAudioServerDiedRestoreA2dp();
break;
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
synchronized (mDeviceStateLock) {
mDeviceInventory.onSetWiredDeviceConnectionState(
(AudioDeviceInventory.WiredDeviceConnectionState) msg.obj);
}
mDeviceInventory.onSetWiredDeviceConnectionState(
(AudioDeviceInventory.WiredDeviceConnectionState) msg.obj);
break;
case MSG_I_BROADCAST_BT_CONNECTION_STATE:
synchronized (mDeviceStateLock) {
mBtHelper.onBroadcastScoConnectionState(msg.arg1);
}
mBtHelper.onBroadcastScoConnectionState(msg.arg1);
break;
case MSG_IIL_SET_FORCE_USE: // intended fall-through
case MSG_IIL_SET_FORCE_BT_A2DP_USE:
onSetForceUse(msg.arg1, msg.arg2, (String) msg.obj);
break;
case MSG_REPORT_NEW_ROUTES:
synchronized (mDeviceStateLock) {
mDeviceInventory.onReportNewRoutes();
}
mDeviceInventory.onReportNewRoutes();
break;
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
synchronized (mDeviceStateLock) {
mDeviceInventory.onSetA2dpSinkConnectionState(
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
}
mDeviceInventory.onSetA2dpSinkConnectionState(
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
break;
case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
synchronized (mDeviceStateLock) {
mDeviceInventory.onSetA2dpSourceConnectionState(
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
}
mDeviceInventory.onSetA2dpSourceConnectionState(
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
break;
case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
synchronized (mDeviceStateLock) {
mDeviceInventory.onSetHearingAidConnectionState(
(BluetoothDevice) msg.obj, msg.arg1,
mAudioService.getHearingAidStreamType());
}
mDeviceInventory.onSetHearingAidConnectionState(
(BluetoothDevice) msg.obj, msg.arg1,
mAudioService.getHearingAidStreamType());
break;
case MSG_BT_HEADSET_CNCT_FAILED:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.resetBluetoothSco();
}
}
mBtHelper.resetBluetoothSco();
break;
case MSG_IL_BTA2DP_DOCK_TIMEOUT:
// msg.obj == address of BTA2DP device
synchronized (mDeviceStateLock) {
mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
}
mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
break;
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
final int a2dpCodec;
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
synchronized (mDeviceStateLock) {
synchronized (mDeviceBrokerLock) {
// FIXME why isn't the codec coming with the request? lock shouldn't be
// needed here
a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
@@ -781,84 +803,48 @@ import java.io.PrintWriter;
onSendBecomingNoisyIntent();
break;
case MSG_II_SET_HEARING_AID_VOLUME:
synchronized (mDeviceStateLock) {
mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2);
}
mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2);
break;
case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME:
synchronized (mDeviceStateLock) {
mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
}
mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
break;
case MSG_I_DISCONNECT_BT_SCO:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.disconnectBluetoothSco(msg.arg1);
}
}
mBtHelper.disconnectBluetoothSco(msg.arg1);
break;
case MSG_L_SCOCLIENT_DIED:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.scoClientDied(msg.obj);
}
}
mBtHelper.scoClientDied(msg.obj);
break;
case MSG_TOGGLE_HDMI:
synchronized (mDeviceStateLock) {
mDeviceInventory.onToggleHdmi();
}
mDeviceInventory.onToggleHdmi();
break;
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
synchronized (mDeviceStateLock) {
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj,
BtHelper.EVENT_ACTIVE_DEVICE_CHANGE);
}
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj,
BtHelper.EVENT_ACTIVE_DEVICE_CHANGE);
break;
case MSG_DISCONNECT_A2DP:
synchronized (mDeviceStateLock) {
mDeviceInventory.disconnectA2dp();
}
mDeviceInventory.disconnectA2dp();
break;
case MSG_DISCONNECT_A2DP_SINK:
synchronized (mDeviceStateLock) {
mDeviceInventory.disconnectA2dpSink();
}
mDeviceInventory.disconnectA2dpSink();
break;
case MSG_DISCONNECT_BT_HEARING_AID:
synchronized (mDeviceStateLock) {
mDeviceInventory.disconnectHearingAid();
}
mDeviceInventory.disconnectHearingAid();
break;
case MSG_DISCONNECT_BT_HEADSET:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.disconnectHeadset();
}
}
mBtHelper.disconnectHeadset();
break;
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
synchronized (mDeviceStateLock) {
mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
}
mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
break;
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK:
synchronized (mDeviceStateLock) {
mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
}
mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
break;
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID:
synchronized (mDeviceStateLock) {
mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
}
mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
break;
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
}
}
mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
break;
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: {
@@ -871,11 +857,9 @@ import java.io.PrintWriter;
+ " addr=" + info.mDevice.getAddress()
+ " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
+ " vol=" + info.mVolume)).printLog(TAG));
synchronized (mDeviceStateLock) {
mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
info.mDevice, info.mState, info.mProfile, info.mSupprNoisy,
AudioSystem.DEVICE_NONE, info.mVolume);
}
mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
info.mDevice, info.mState, info.mProfile, info.mSupprNoisy,
AudioSystem.DEVICE_NONE, info.mVolume);
} break;
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: {
final HearingAidDeviceConnectionInfo info =
@@ -885,10 +869,8 @@ import java.io.PrintWriter;
+ " addr=" + info.mDevice.getAddress()
+ " supprNoisy=" + info.mSupprNoisy
+ " src=" + info.mEventSource)).printLog(TAG));
synchronized (mDeviceStateLock) {
mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
}
mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
} break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
@@ -973,46 +955,57 @@ import java.io.PrintWriter;
/** If the msg is already queued, queue this one and leave the old. */
private static final int SENDMSG_QUEUE = 2;
@GuardedBy("mDeviceBrokerLock")
private void sendMsg(int msg, int existingMsgPolicy, int delay) {
sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay);
}
@GuardedBy("mDeviceBrokerLock")
private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) {
sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay);
}
@GuardedBy("mDeviceBrokerLock")
private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) {
sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay);
}
@GuardedBy("mDeviceBrokerLock")
private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) {
sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay);
}
@GuardedBy("mDeviceBrokerLock")
private void sendMsgNoDelay(int msg, int existingMsgPolicy) {
sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0);
}
@GuardedBy("mDeviceBrokerLock")
private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) {
sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0);
}
@GuardedBy("mDeviceBrokerLock")
private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) {
sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0);
}
@GuardedBy("mDeviceBrokerLock")
private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) {
sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0);
}
@GuardedBy("mDeviceBrokerLock")
private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) {
sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0);
}
@GuardedBy("mDeviceBrokerLock")
private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) {
sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0);
}
@GuardedBy("mDeviceBrokerLock")
private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj,
int delay) {
if (existingMsgPolicy == SENDMSG_REPLACE) {
@@ -1031,31 +1024,29 @@ import java.io.PrintWriter;
Binder.restoreCallingIdentity(identity);
}
synchronized (sLastDeviceConnectionMsgTimeLock) {
long time = SystemClock.uptimeMillis() + delay;
long time = SystemClock.uptimeMillis() + delay;
switch (msg) {
case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_DOCK_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
time = sLastDeviceConnectMsgTime + 30;
}
sLastDeviceConnectMsgTime = time;
break;
default:
break;
}
mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
time);
switch (msg) {
case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_DOCK_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
time = sLastDeviceConnectMsgTime + 30;
}
sLastDeviceConnectMsgTime = time;
break;
default:
break;
}
mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
time);
}
//-------------------------------------------------------------

View File

@@ -469,12 +469,11 @@ public class AudioService extends IAudioService.Stub
// List of binder death handlers for setMode() client processes.
// The last process to have called setMode() is at the top of the list.
// package-private so it can be accessed in AudioDeviceBroker.getSetModeDeathHandlers
//TODO candidate to be moved to separate class that handles synchronization
@GuardedBy("mDeviceBroker.mSetModeLock")
/*package*/ final ArrayList<SetModeDeathHandler> mSetModeDeathHandlers =
private final ArrayList<SetModeDeathHandler> mSetModeDeathHandlers =
new ArrayList<SetModeDeathHandler>();
private volatile int mCurrentModeOwnerPid = 0;
// true if boot sequence has been completed
private boolean mSystemReady;
// true if Intent.ACTION_USER_SWITCHED has ever been received
@@ -3150,15 +3149,10 @@ public class AudioService extends IAudioService.Stub
* @return 0 if nobody owns the mode
*/
/*package*/ int getModeOwnerPid() {
int modeOwnerPid = 0;
try {
modeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
} catch (Exception e) {
// nothing to do, modeOwnerPid is not modified
}
return modeOwnerPid;
return mCurrentModeOwnerPid;
}
private class SetModeDeathHandler implements IBinder.DeathRecipient {
private IBinder mCb; // To be notified of client's death
private int mPid;
@@ -3172,7 +3166,7 @@ public class AudioService extends IAudioService.Stub
public void binderDied() {
int oldModeOwnerPid = 0;
int newModeOwnerPid = 0;
synchronized (mDeviceBroker.mSetModeLock) {
synchronized (mSetModeDeathHandlers) {
Log.w(TAG, "setMode() client died");
if (!mSetModeDeathHandlers.isEmpty()) {
oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
@@ -3183,11 +3177,15 @@ public class AudioService extends IAudioService.Stub
} else {
newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
}
}
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
// SCO connections not started by the application changing the mode when pid changes
if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
if (newModeOwnerPid != oldModeOwnerPid) {
mCurrentModeOwnerPid = newModeOwnerPid;
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO
// connections not started by the application changing the mode when pid changes
if (newModeOwnerPid != 0) {
mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
}
}
}
}
@@ -3210,15 +3208,17 @@ public class AudioService extends IAudioService.Stub
/** @see AudioManager#setMode(int) */
public void setMode(int mode, IBinder cb, String callingPackage) {
if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
if (DEBUG_MODE) {
Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")");
}
if (!checkAudioSettingsPermission("setMode()")) {
return;
}
if ( (mode == AudioSystem.MODE_IN_CALL) &&
(mContext.checkCallingOrSelfPermission(
if ((mode == AudioSystem.MODE_IN_CALL)
&& (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED)) {
!= PackageManager.PERMISSION_GRANTED)) {
Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
return;
@@ -3230,7 +3230,7 @@ public class AudioService extends IAudioService.Stub
int oldModeOwnerPid = 0;
int newModeOwnerPid = 0;
synchronized (mDeviceBroker.mSetModeLock) {
synchronized (mSetModeDeathHandlers) {
if (!mSetModeDeathHandlers.isEmpty()) {
oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
}
@@ -3238,17 +3238,21 @@ public class AudioService extends IAudioService.Stub
mode = mMode;
}
newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
}
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
// SCO connections not started by the application changing the mode when pid changes
if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
if (newModeOwnerPid != oldModeOwnerPid) {
mCurrentModeOwnerPid = newModeOwnerPid;
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
// SCO connections not started by the application changing the mode when pid changes
if (newModeOwnerPid != 0) {
mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
}
}
}
}
// setModeInt() returns a valid PID if the audio mode was successfully set to
// any mode other than NORMAL.
@GuardedBy("mDeviceBroker.mSetModeLock")
@GuardedBy("mSetModeDeathHandlers")
private int setModeInt(int mode, IBinder cb, int pid, String caller) {
if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
+ caller + ")"); }
@@ -3587,9 +3591,7 @@ public class AudioService extends IAudioService.Stub
!mSystemReady) {
return;
}
synchronized (mDeviceBroker.mSetModeLock) {
mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
}
mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
}
/** @see AudioManager#stopBluetoothSco() */
@@ -3601,9 +3603,7 @@ public class AudioService extends IAudioService.Stub
final String eventSource = new StringBuilder("stopBluetoothSco()")
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
.append(Binder.getCallingPid()).toString();
synchronized (mDeviceBroker.mSetModeLock) {
mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
}
mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
}
@@ -4352,7 +4352,7 @@ public class AudioService extends IAudioService.Stub
// NOTE: Locking order for synchronized objects related to volume or ringer mode management:
// 1 mScoclient OR mSafeMediaVolumeState
// 2 mSetModeLock
// 2 mSetModeDeathHandlers
// 3 mSettingsLock
// 4 VolumeStreamState.class
private class VolumeStreamState {

View File

@@ -171,8 +171,6 @@ public class BtHelper {
//----------------------------------------------------------------------
// Interface for AudioDeviceBroker
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void onSystemReady() {
mScoConnectionState = android.media.AudioManager.SCO_AUDIO_STATE_ERROR;
resetBluetoothSco();
@@ -245,8 +243,6 @@ public class BtHelper {
return mapBluetoothCodecToAudioFormat(btCodecConfig.getCodecType());
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void receiveBtEvent(Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
@@ -333,8 +329,6 @@ public class BtHelper {
*
* @param exceptPid pid whose SCO connections through {@link AudioManager} should be kept
*/
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void disconnectBluetoothSco(int exceptPid) {
checkScoAudioState();
if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) {
@@ -343,8 +337,6 @@ public class BtHelper {
clearAllScoClients(exceptPid, true);
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void startBluetoothScoForClient(IBinder cb, int scoAudioMode,
@NonNull String eventSource) {
ScoClient client = getScoClient(cb, true);
@@ -364,8 +356,6 @@ public class BtHelper {
Binder.restoreCallingIdentity(ident);
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void stopBluetoothScoForClient(IBinder cb,
@NonNull String eventSource) {
ScoClient client = getScoClient(cb, false);
@@ -423,8 +413,6 @@ public class BtHelper {
mDeviceBroker.postDisconnectHearingAid();
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void resetBluetoothSco() {
clearAllScoClients(0, false);
mScoAudioState = SCO_STATE_INACTIVE;
@@ -433,8 +421,6 @@ public class BtHelper {
mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco");
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void disconnectHeadset() {
setBtScoActiveDevice(null);
mBluetoothHeadset = null;
@@ -480,8 +466,6 @@ public class BtHelper {
/*eventSource*/ "mBluetoothProfileServiceListener");
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
// Discard timeout message
mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
@@ -568,8 +552,6 @@ public class BtHelper {
return result;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
private void setBtScoActiveDevice(BluetoothDevice btDevice) {
Log.i(TAG, "setBtScoActiveDevice: " + mBluetoothHeadsetDevice + " -> " + btDevice);
@@ -652,8 +634,6 @@ public class BtHelper {
};
//----------------------------------------------------------------------
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void scoClientDied(Object obj) {
final ScoClient client = (ScoClient) obj;
Log.w(TAG, "SCO client died");
@@ -684,8 +664,6 @@ public class BtHelper {
mDeviceBroker.postScoClientDied(this);
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
// @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
void incCount(int scoAudioMode) {
if (!requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode)) {
@@ -705,8 +683,6 @@ public class BtHelper {
mStartcount++;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
// @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
void decCount() {
if (mStartcount == 0) {
@@ -726,8 +702,6 @@ public class BtHelper {
}
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
// @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
void clearCount(boolean stopSco) {
if (mStartcount != 0) {
@@ -764,8 +738,6 @@ public class BtHelper {
return count;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
private boolean requestScoState(int state, int scoAudioMode) {
checkScoAudioState();
@@ -959,8 +931,6 @@ public class BtHelper {
return null;
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
private void clearAllScoClients(int exceptPid, boolean stopSco) {
ScoClient savedClient = null;

View File

@@ -126,6 +126,22 @@ public class AudioDeviceBrokerTest {
doTestConnectionDisconnectionReconnection(AudioService.BECOMING_NOISY_DELAY_MS / 2);
}
/**
* Verify connecting an A2DP sink will call into AudioService to unmute media
*/
@Test
public void testA2dpConnectionUnmutesMedia() throws Exception {
Log.i(TAG, "testA2dpConnectionUnmutesMedia");
Assert.assertNotNull("invalid null BT device", mFakeBtDevice);
mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1);
Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
verify(mMockAudioService, times(1)).postAccessoryPlugMediaUnmute(
ArgumentMatchers.eq(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
}
private void doTestConnectionDisconnectionReconnection(int delayAfterDisconnection)
throws Exception {
when(mMockAudioService.getDeviceForStream(AudioManager.STREAM_MUSIC))