From 2bd07ff1daed36dc1ffd30134e50887996250927 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 26 Apr 2023 16:07:01 +0200 Subject: [PATCH] AudioDeviceBroker: fix deadlock with setA2dpSuspended There is a potential deadlock between AudioDeviceBroker and HFP HeadsetService when AudioManager.setA2dpSuspended (or setLeAudioSuspended) is called. To avoid it, process the suspend requests in the message handler instead of synchronously. Bug: 278668288 Fixes: 279558132 Test: repro steps in bug Change-Id: I83e3a5e918224f63f39438e30221db06f1dc2ad0 --- .../android/server/audio/AudioDeviceBroker.java | 17 +++++++++++++++++ .../com/android/server/audio/AudioService.java | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 13c42eb66b69f..ada92f5545c23 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -957,6 +957,10 @@ import java.util.concurrent.atomic.AtomicBoolean; } } + /*package*/ void postSetA2dpSuspended(boolean enable, String eventSource) { + sendILMsgNoDelay(MSG_IL_SET_A2DP_SUSPENDED, SENDMSG_QUEUE, (enable ? 1 : 0), eventSource); + } + /*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: " @@ -985,6 +989,11 @@ import java.util.concurrent.atomic.AtomicBoolean; } } + /*package*/ void postSetLeAudioSuspended(boolean enable, String eventSource) { + sendILMsgNoDelay( + MSG_IL_SET_LEAUDIO_SUSPENDED, SENDMSG_QUEUE, (enable ? 1 : 0), eventSource); + } + /*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: " @@ -1795,6 +1804,12 @@ import java.util.concurrent.atomic.AtomicBoolean; final int capturePreset = msg.arg1; mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); } break; + case MSG_IL_SET_A2DP_SUSPENDED: { + setA2dpSuspended((msg.arg1 == 1), false /*internal*/, (String) msg.obj); + } break; + case MSG_IL_SET_LEAUDIO_SUSPENDED: { + setLeAudioSuspended((msg.arg1 == 1), false /*internal*/, (String) msg.obj); + } break; default: Log.wtf(TAG, "Invalid message " + msg.what); } @@ -1869,6 +1884,8 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47; private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48; private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49; + private static final int MSG_IL_SET_A2DP_SUSPENDED = 50; + private static final int MSG_IL_SET_LEAUDIO_SUSPENDED = 51; private static boolean isMessageHandledUnderWakelock(int msgId) { switch(msgId) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 3487fc2c14bee..20393250b5b78 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -6412,7 +6412,7 @@ public class AudioService extends IAudioService.Stub final String eventSource = new StringBuilder("setA2dpSuspended(").append(enable) .append(") from u/pid:").append(Binder.getCallingUid()).append("/") .append(Binder.getCallingPid()).toString(); - mDeviceBroker.setA2dpSuspended(enable, false /*internal*/, eventSource); + mDeviceBroker.postSetA2dpSuspended(enable, eventSource); } /** @see AudioManager#setA2dpSuspended(boolean) */ @@ -6422,7 +6422,7 @@ public class AudioService extends IAudioService.Stub final String eventSource = new StringBuilder("setLeAudioSuspended(").append(enable) .append(") from u/pid:").append(Binder.getCallingUid()).append("/") .append(Binder.getCallingPid()).toString(); - mDeviceBroker.setLeAudioSuspended(enable, false /*internal*/, eventSource); + mDeviceBroker.postSetLeAudioSuspended(enable, eventSource); } /** @see AudioManager#isBluetoothScoOn()