From 1d1884405bf186828c46cba7581cd0d8963e8eb8 Mon Sep 17 00:00:00 2001 From: Sharad Sangle Date: Tue, 9 May 2017 16:05:40 +0530 Subject: [PATCH] AudioService: Don't honour SCO ON request if SCO is not connected Usecase: 1. Pair and connect BT headset supporting HFP. 2. Make VOIP calls using application that calls setBluetoothScoOn(true) before SCO is actually connected. Failure: No audio / ANR are observed on connecting and disconnecting BT headset during VOIP call. Rootcause: On BT connection during VOIP call, app is calling startBluetoothSco() to setup BT SCO connection. Even before remote BT device SCO connection establishment(which is taking around 4 secs in issue case), VOIP app is calling force SCO routing using setBluetoothScoOn() API. This will result audio modules to force route VOIP call to BT SCO, which results audio failure/side effects as BT driver return failures. As SCO routing retry continues several iterations (because of connection delays), this results ADSP render buffer full followed by improper behavior. Fix: Check if SCO connection is establisted before honouring the setBluetoothScoOn request, if SCO is not connected then do not process SCO connection. Only modify internal state when calls to setBluetoothScoOn() are from system component Inform audio HAL of SCO audio state via setParameters. Test: 1. Pair and connect BT headset supporting HFP 2. Make VOIP calls using application that calls setBluetoothScoOn(true) before SCO is actually connected. Bug: 62051216 Bug: 63740200 Change-Id: Iab8e83613e21831abf5502a0268b1c4f89d6bba5 --- .../android/server/audio/AudioService.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 11d0470ee8e5a..3c1f2d42707a6 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -461,6 +461,8 @@ public class AudioService extends IAudioService.Stub // Forced device usage for communications private int mForcedUseForComm; + private int mForcedUseForCommExt; // External state returned by getters: always consistent + // with requests by setters // List of binder death handlers for setMode() client processes. // The last process to have called setMode() is at the top of the list. @@ -2890,13 +2892,14 @@ public class AudioService extends IAudioService.Stub mForcedUseForComm = AudioSystem.FORCE_NONE; } + mForcedUseForCommExt = mForcedUseForComm; sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); } /** @see AudioManager#isSpeakerphoneOn() */ public boolean isSpeakerphoneOn() { - return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); + return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); } /** @see AudioManager#setBluetoothScoOn(boolean) */ @@ -2904,6 +2907,13 @@ public class AudioService extends IAudioService.Stub if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { return; } + + // Only enable calls from system components + if (Binder.getCallingUid() >= FIRST_APPLICATION_UID) { + mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; + return; + } + // for logging only final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on) .append(") from u/pid:").append(Binder.getCallingUid()).append("/") @@ -2913,11 +2923,21 @@ public class AudioService extends IAudioService.Stub public void setBluetoothScoOnInt(boolean on, String eventSource) { if (on) { + // do not accept SCO ON if SCO audio is not connected + synchronized(mScoClients) { + if ((mBluetoothHeadset != null) && + (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + != BluetoothHeadset.STATE_AUDIO_CONNECTED)) { + mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; + return; + } + } mForcedUseForComm = AudioSystem.FORCE_BT_SCO; } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { mForcedUseForComm = AudioSystem.FORCE_NONE; } - + mForcedUseForCommExt = mForcedUseForComm; + AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off")); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, @@ -2926,7 +2946,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#isBluetoothScoOn() */ public boolean isBluetoothScoOn() { - return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); + return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO); } /** @see AudioManager#setBluetoothA2dpOn(boolean) */