From a0245642ced9831cdeb8513e5e031141cb877f25 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 11 Aug 2023 19:14:56 +0200 Subject: [PATCH] AudioDeviceBroker: fix communication route for idle apps AudioDeviceBroker.onUpdateCommunicationRouteClient() was just evaluating if SCO audio should be used by the audio policy for calls (which includes when SCO audio is already active from an external request - e.g. by Telecom) but not if no more active request to use SCO exists. Thus it was failing to stop internal SCO audio requests when no more communication route client was active. Also fix a spurious CONNECTING intent broadcast in BtHelper.requestScoState() Bug: 294167472 Test: repro steps in bug Change-Id: Ib94dc3aa8cfe7120a87661b6403ee4060a295f8c --- .../server/audio/AudioDeviceBroker.java | 38 ++++++++++++------- .../com/android/server/audio/BtHelper.java | 10 +++-- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 9f9e2eb382883..533ecf18938fe 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -391,7 +391,6 @@ public class AudioDeviceBroker { final boolean wasBtScoRequested = isBluetoothScoRequested(); CommunicationRouteClient client; - // Save previous client route in case of failure to start BT SCO audio AudioDeviceAttributes prevClientDevice = null; boolean prevPrivileged = false; @@ -1043,7 +1042,7 @@ public class AudioDeviceBroker { synchronized (mBluetoothAudioStateLock) { mBluetoothScoOn = on; updateAudioHalBluetoothState(); - postUpdateCommunicationRouteClient(eventSource); + postUpdateCommunicationRouteClient(isBluetoothScoRequested(), eventSource); } } @@ -1395,8 +1394,10 @@ public class AudioDeviceBroker { MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset); } - /*package*/ void postUpdateCommunicationRouteClient(String eventSource) { - sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE, eventSource); + /*package*/ void postUpdateCommunicationRouteClient( + boolean wasBtScoRequested, String eventSource) { + sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE, + wasBtScoRequested ? 1 : 0, eventSource); } /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) { @@ -1708,7 +1709,8 @@ public class AudioDeviceBroker { : AudioSystem.STREAM_DEFAULT); if (btInfo.mProfile == BluetoothProfile.LE_AUDIO || btInfo.mProfile == BluetoothProfile.HEARING_AID) { - onUpdateCommunicationRouteClient("setBluetoothActiveDevice"); + onUpdateCommunicationRouteClient(isBluetoothScoRequested(), + "setBluetoothActiveDevice"); } } } @@ -1762,9 +1764,11 @@ public class AudioDeviceBroker { case MSG_I_SET_MODE_OWNER: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { + boolean wasBtScoRequested = isBluetoothScoRequested(); mAudioModeOwner = (AudioModeInfo) msg.obj; if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) { - onUpdateCommunicationRouteClient("setNewModeOwner"); + onUpdateCommunicationRouteClient( + wasBtScoRequested, "setNewModeOwner"); } } } @@ -1787,10 +1791,10 @@ public class AudioDeviceBroker { } break; - case MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT: + case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { - onUpdateCommunicationRouteClient((String) msg.obj); + onUpdateCommunicationRouteClient(msg.arg1 == 1, (String) msg.obj); } } break; @@ -1973,7 +1977,7 @@ public class AudioDeviceBroker { private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38; private static final int MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT = 42; - private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43; + private static final int MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43; private static final int MSG_I_SCO_AUDIO_STATE_CHANGED = 44; private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45; @@ -2330,16 +2334,20 @@ public class AudioDeviceBroker { */ // @GuardedBy("mSetModeLock") @GuardedBy("mDeviceStateLock") - private void onUpdateCommunicationRouteClient(String eventSource) { - updateCommunicationRoute(eventSource); + private void onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource) { CommunicationRouteClient crc = topCommunicationRouteClient(); if (AudioService.DEBUG_COMM_RTE) { - Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " - + crc + " eventSource: " + eventSource); + Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc + + " wasBtScoRequested: " + wasBtScoRequested + " eventSource: " + eventSource); } if (crc != null) { setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(), BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource); + } else { + if (!isBluetoothScoRequested() && wasBtScoRequested) { + mBtHelper.stopBluetoothSco(eventSource); + } + updateCommunicationRoute(eventSource); } } @@ -2433,6 +2441,7 @@ public class AudioDeviceBroker { List recordConfigs) { synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { + final boolean wasBtScoRequested = isBluetoothScoRequested(); boolean updateCommunicationRoute = false; for (CommunicationRouteClient crc : mCommunicationRouteClients) { boolean wasActive = crc.isActive(); @@ -2461,7 +2470,8 @@ public class AudioDeviceBroker { } } if (updateCommunicationRoute) { - postUpdateCommunicationRouteClient("updateCommunicationRouteClientsActivity"); + postUpdateCommunicationRouteClient( + wasBtScoRequested, "updateCommunicationRouteClientsActivity"); } } } diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 3560797ce2cff..a4d26d3e96c05 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -329,7 +329,7 @@ public class BtHelper { default: break; } - if(broadcast) { + if (broadcast) { broadcastScoConnectionState(scoAudioState); //FIXME: this is to maintain compatibility with deprecated intent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. @@ -718,8 +718,10 @@ public class BtHelper { checkScoAudioState(); if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { // Make sure that the state transitions to CONNECTING even if we cannot initiate - // the connection. - broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); + // the connection except if already connected internally + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL) { + broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); + } switch (mScoAudioState) { case SCO_STATE_INACTIVE: mScoAudioMode = scoAudioMode; @@ -775,7 +777,7 @@ public class BtHelper { broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); break; case SCO_STATE_ACTIVE_INTERNAL: - Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return"); + // Already in ACTIVE mode, simply return break; case SCO_STATE_ACTIVE_EXTERNAL: /* Confirm SCO Audio connection to requesting app as it is already connected