diff options
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioDeviceBroker.java | 37 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/BtHelper.java | 45 |
2 files changed, 73 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 22b0aebca6c4..074d3fe10816 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -224,12 +224,35 @@ import java.util.concurrent.atomic.AtomicBoolean; if (!addSpeakerphoneClient(cb, pid, on)) { return false; } + if (on) { + // Cancel BT SCO ON request by this same client: speakerphone and BT SCO routes + // are mutually exclusive. + // See symmetrical operation for startBluetoothScoForClient_Sync(). + mBtHelper.stopBluetoothScoForPid(pid); + } final boolean wasOn = isSpeakerphoneOn(); updateSpeakerphoneOn(eventSource); return (wasOn != isSpeakerphoneOn()); } } + /** + * Turns speakerphone off for a given pid and update speakerphone state. + * @param pid + */ + @GuardedBy("mDeviceStateLock") + private void setSpeakerphoneOffForPid(int pid) { + SpeakerphoneClient client = getSpeakerphoneClientForPid(pid); + if (client == null) { + return; + } + client.unregisterDeathRecipient(); + mSpeakerphoneClients.remove(client); + final String eventSource = new StringBuilder("setSpeakerphoneOffForPid(") + .append(pid).append(")").toString(); + updateSpeakerphoneOn(eventSource); + } + @GuardedBy("mDeviceStateLock") private void updateSpeakerphoneOn(String eventSource) { if (isSpeakerphoneOnRequested()) { @@ -488,6 +511,10 @@ import java.util.concurrent.atomic.AtomicBoolean; /*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode, @NonNull String eventSource) { synchronized (mDeviceStateLock) { + // Cancel speakerphone ON request by this same client: speakerphone and BT SCO routes + // are mutually exclusive. + // See symmetrical operation for setSpeakerphoneOn(true). + setSpeakerphoneOffForPid(Binder.getCallingPid()); mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource); } } @@ -1381,6 +1408,16 @@ import java.util.concurrent.atomic.AtomicBoolean; return false; } + @GuardedBy("mDeviceStateLock") + private SpeakerphoneClient getSpeakerphoneClientForPid(int pid) { + for (SpeakerphoneClient cl : mSpeakerphoneClients) { + if (cl.getPid() == pid) { + return cl; + } + } + return null; + } + // List of clients requesting speakerPhone ON @GuardedBy("mDeviceStateLock") private final @NonNull ArrayList<SpeakerphoneClient> mSpeakerphoneClients = diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index b4c41b274dbe..7616557ac80f 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -432,19 +432,36 @@ public class BtHelper { // and this must be done on behalf of system server to make sure permissions are granted. final long ident = Binder.clearCallingIdentity(); if (client != null) { - AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource)); - client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, - SCO_MODE_VIRTUAL_CALL); - // If a disconnection is pending, the client will be removed whne clearAllScoClients() - // is called form receiveBtEvent() - if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ - && mScoAudioState != SCO_STATE_DEACTIVATING) { - client.remove(false /*stop */, true /*unregister*/); - } + stopAndRemoveClient(client, eventSource); } Binder.restoreCallingIdentity(ident); } + // @GuardedBy("AudioDeviceBroker.mSetModeLock") + @GuardedBy("AudioDeviceBroker.mDeviceStateLock") + /*package*/ synchronized void stopBluetoothScoForPid(int pid) { + ScoClient client = getScoClientForPid(pid); + if (client == null) { + return; + } + final String eventSource = new StringBuilder("stopBluetoothScoForPid(") + .append(pid).append(")").toString(); + stopAndRemoveClient(client, eventSource); + } + + @GuardedBy("AudioDeviceBroker.mDeviceStateLock") + // @GuardedBy("BtHelper.this") + private void stopAndRemoveClient(ScoClient client, @NonNull String eventSource) { + AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource)); + client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, + SCO_MODE_VIRTUAL_CALL); + // If a disconnection is pending, the client will be removed when clearAllScoClients() + // is called form receiveBtEvent() + if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ + && mScoAudioState != SCO_STATE_DEACTIVATING) { + client.remove(false /*stop */, true /*unregister*/); + } + } /*package*/ synchronized void setHearingAidVolume(int index, int streamType) { if (mHearingAid == null) { @@ -974,6 +991,16 @@ public class BtHelper { return null; } + @GuardedBy("BtHelper.this") + private ScoClient getScoClientForPid(int pid) { + for (ScoClient cl : mScoClients) { + if (cl.getPid() == pid) { + return cl; + } + } + return null; + } + // @GuardedBy("AudioDeviceBroker.mSetModeLock") //@GuardedBy("AudioDeviceBroker.mDeviceStateLock") @GuardedBy("BtHelper.this") |