diff options
| author | 2019-10-25 15:43:38 +0000 | |
|---|---|---|
| committer | 2019-10-25 15:43:38 +0000 | |
| commit | 4f27cd6f468dabaff1ab2da555b47624fd54ea9e (patch) | |
| tree | 132566de7bc60a2df77ae246f8eb78a936e4ce64 | |
| parent | 68617d8d746b575d6b72166930f92c9924cfdfc6 (diff) | |
| parent | 261a9f94828187e7cf08034a45259eb18a51f80c (diff) | |
Merge "AudioService: simplify/document locking"
5 files changed, 303 insertions, 331 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 6010b1dc88c4..f7ac04041ed6 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -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,38 +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) { mBtHelper.disconnectAllBluetoothProfiles(); - } } /** @@ -168,15 +170,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 +194,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 +212,7 @@ import java.io.PrintWriter; } /*package*/ boolean isSpeakerphoneOn() { - synchronized (mDeviceStateLock) { + synchronized (mDeviceBrokerLock) { return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); } } @@ -223,9 +221,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 +255,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); - - 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); + 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); + } } private static final class HearingAidDeviceConnectionInfo { @@ -305,28 +298,31 @@ 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) { + final boolean isBtScoOn = mBtHelper.isBluetoothScoOn(); + synchronized (mDeviceBrokerLock) { if (on) { // do not accept SCO ON if SCO audio is not connected - if (!mBtHelper.isBluetoothScoOn()) { + if (!isBtScoOn) { mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; return; } @@ -346,58 +342,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 +453,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 +570,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 +582,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))); + 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) { - sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); + synchronized (mDeviceBrokerLock) { + sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); + } } /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { - synchronized (mDeviceStateLock) { - mBtHelper.setAvrcpAbsoluteVolumeSupported(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,156 +748,101 @@ 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) { - a2dpCodec = mBtHelper.getA2dpCodec(btDevice); - mDeviceInventory.onBluetoothA2dpActiveDeviceChange( - new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), - BtHelper.EVENT_DEVICE_CONFIG_CHANGE); - } + // FIXME why isn't the codec coming with the request? codec should be + // provided by BT when it calls + // AudioManager.handleBluetoothA2dpDeviceConfigChange(BluetoothDevice) + a2dpCodec = mBtHelper.getA2dpCodec(btDevice); + mDeviceInventory.onBluetoothA2dpActiveDeviceChange( + new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), + BtHelper.EVENT_DEVICE_CONFIG_CHANGE); break; case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 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 +855,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 +867,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 +953,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 +1022,29 @@ import java.io.PrintWriter; Binder.restoreCallingIdentity(identity); } - synchronized (sLastDeviceConnectionMsgTimeLock) { - 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; - } + long time = SystemClock.uptimeMillis() + delay; - 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); } //------------------------------------------------------------- diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 90973a888a9d..3933fb2d5f46 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -159,7 +159,6 @@ public class AudioDeviceInventory { } // only public for mocking/spying - @GuardedBy("AudioDeviceBroker.mDeviceStateLock") @VisibleForTesting public void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, @AudioService.BtProfileConnectionState int state) { @@ -284,7 +283,6 @@ public class AudioDeviceInventory { } } - @GuardedBy("AudioDeviceBroker.mDeviceStateLock") /*package*/ void onBluetoothA2dpActiveDeviceChange( @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) { final BluetoothDevice btDevice = btInfo.getBtDevice(); @@ -557,7 +555,6 @@ public class AudioDeviceInventory { } // only public for mocking/spying - @GuardedBy("AudioDeviceBroker.mDeviceStateLock") @VisibleForTesting public void setBluetoothA2dpDeviceConnectionState( @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 0d493b825133..cc50e37d2b61 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -470,12 +470,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 @@ -3192,15 +3191,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; @@ -3214,7 +3208,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(); @@ -3225,11 +3219,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); + } + } } } @@ -3252,15 +3250,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; @@ -3272,7 +3272,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(); } @@ -3280,17 +3280,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 + ")"); } @@ -3629,9 +3633,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() */ @@ -3643,9 +3645,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); } @@ -4406,7 +4406,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 { diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 9f1a6bd15ac3..625b6b690443 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -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; diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java index 5c2ad94720f0..29a8dada7d89 100644 --- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java @@ -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)) |