AudioService: Do not disconnect SCO started externally
* AudioService should not disconnect Bluetooth SCO if it is started
externally
* When SCO has already started externally, all SCO connection attempts
through AudioManager API will fail with SCO_AUDIO_STATE_DISCONNECTED
intent
* Remove SCO_STATE_DEACTIVATE_EXT_REQ state since AudioService could no
longer disconnect SCO audio that is started externally
* Change SCO_STATE_* values so that they are consecutive
Bug: 79407565
Test: With Bluetooth HFP device connected:
Test1: make a outgoing call
Test2: make VoIP call during cellular call
Test3: make a VoIP call during another VoIP call
Change-Id: I1e0a10aeb0eac59d4826f9defa595aebd85f534c
(cherry picked from commit 33c3a17113ee93bfd4575241cc15e78afc300f0e)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 36e5340..3d25325 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -524,16 +524,13 @@
// SCO audio state is active or starting due to a request from AudioManager API
private static final int SCO_STATE_ACTIVE_INTERNAL = 3;
// SCO audio deactivation request waiting for headset service to connect
- private static final int SCO_STATE_DEACTIVATE_REQ = 5;
+ private static final int SCO_STATE_DEACTIVATE_REQ = 4;
// SCO audio deactivation in progress, waiting for Bluetooth audio intent
- private static final int SCO_STATE_DEACTIVATING = 6;
+ private static final int SCO_STATE_DEACTIVATING = 5;
// SCO audio state is active due to an action in BT handsfree (either voice recognition or
// in call audio)
private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
- // Deactivation request for all SCO connections (initiated by audio mode change)
- // waiting for headset service to connect
- private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4;
// Indicates the mode used for SCO audio connection. The mode is virtual call if the request
// originated from an app targeting an API version before JB MR2 and raw audio after that.
@@ -3580,33 +3577,19 @@
return result;
}
+ /**
+ * Disconnect all SCO connections started by {@link AudioManager} except those started by
+ * {@param exceptPid}
+ *
+ * @param exceptPid pid whose SCO connections through {@link AudioManager} should be kept
+ */
private void disconnectBluetoothSco(int exceptPid) {
synchronized(mScoClients) {
checkScoAudioState();
- if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL ||
- mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
- if (mBluetoothHeadsetDevice != null) {
- if (mBluetoothHeadset != null) {
- boolean status = disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, SCO_MODE_RAW)
- || disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, SCO_MODE_VIRTUAL_CALL)
- || disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, SCO_MODE_VR);
- if (status) {
- mScoAudioState = SCO_STATE_DEACTIVATING;
- } else {
- clearAllScoClients(exceptPid, false);
- mScoAudioState = SCO_STATE_INACTIVE;
- }
- } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL &&
- getBluetoothHeadset()) {
- mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ;
- }
- }
- } else {
- clearAllScoClients(exceptPid, true);
+ if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) {
+ return;
}
+ clearAllScoClients(exceptPid, true);
}
}
@@ -3772,8 +3755,7 @@
checkScoAudioState();
// Continue pending action if any
if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
- mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
- mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
+ mScoAudioState == SCO_STATE_DEACTIVATE_REQ) {
boolean status = false;
if (mBluetoothHeadsetDevice != null) {
switch (mScoAudioState) {
@@ -3791,17 +3773,6 @@
mScoAudioState = SCO_STATE_DEACTIVATING;
}
break;
- case SCO_STATE_DEACTIVATE_EXT_REQ:
- status = disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, SCO_MODE_RAW) ||
- disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, SCO_MODE_VIRTUAL_CALL) ||
- disconnectBluetoothScoAudioHelper(mBluetoothHeadset,
- mBluetoothHeadsetDevice, SCO_MODE_VR);
- if (status) {
- mScoAudioState = SCO_STATE_DEACTIVATING;
- }
- break;
}
}
if (!status) {
@@ -6384,8 +6355,7 @@
case BluetoothHeadset.STATE_AUDIO_CONNECTED:
scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
- mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
- mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
+ mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
}
setBluetoothScoOn(true);
@@ -6409,8 +6379,7 @@
break;
case BluetoothHeadset.STATE_AUDIO_CONNECTING:
if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
- mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
- mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
+ mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
}
default: