Merge "AudioService: simplify/document locking"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f453e78185
@@ -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);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user