diff options
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioDeviceBroker.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 130 |
2 files changed, 111 insertions, 32 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 0fd22c583192..2bbe08d22020 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -1321,9 +1321,9 @@ public class AudioDeviceBroker { sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info); } - /*package*/ void postSetModeOwner(int mode, int pid, int uid) { - sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE, - new AudioModeInfo(mode, pid, uid)); + /*package*/ void postSetModeOwner(int mode, int pid, int uid, boolean signal) { + sendILMsgNoDelay(MSG_IL_SET_MODE_OWNER, SENDMSG_REPLACE, + signal ? 1 : 0, new AudioModeInfo(mode, pid, uid)); } /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) { @@ -2025,7 +2025,7 @@ public class AudioDeviceBroker { mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); } break; - case MSG_I_SET_MODE_OWNER: + case MSG_IL_SET_MODE_OWNER: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { int btScoRequesterUid = bluetoothScoRequestOwnerUid(); @@ -2036,6 +2036,9 @@ public class AudioDeviceBroker { } } } + if (msg.arg1 == 1 /*signal*/) { + mAudioService.decrementAudioModeResetCount(); + } break; case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: @@ -2224,7 +2227,7 @@ public class AudioDeviceBroker { private static final int MSG_REPORT_NEW_ROUTES = 13; private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; - private static final int MSG_I_SET_MODE_OWNER = 16; + private static final int MSG_IL_SET_MODE_OWNER = 16; private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22; private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index e83b03690a24..561030e77e61 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1915,7 +1915,7 @@ public class AudioService extends IAudioService.Stub // Restore call state synchronized (mDeviceBroker.mSetModeLock) { onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(), - mContext.getPackageName(), true /*force*/); + mContext.getPackageName(), true /*force*/, false /*signal*/); } final int forSys; synchronized (mSettingsLock) { @@ -4743,14 +4743,47 @@ public class AudioService extends IAudioService.Stub } } if (updateAudioMode) { - sendMsg(mAudioHandler, - MSG_UPDATE_AUDIO_MODE, - existingMsgPolicy, - AudioSystem.MODE_CURRENT, - android.os.Process.myPid(), - mContext.getPackageName(), - delay); + postUpdateAudioMode(existingMsgPolicy, AudioSystem.MODE_CURRENT, + android.os.Process.myPid(), mContext.getPackageName(), + false /*signal*/, delay); + } + } + } + + static class UpdateAudioModeInfo { + UpdateAudioModeInfo(int mode, int pid, String packageName, boolean signal) { + mMode = mode; + mPid = pid; + mPackageName = packageName; + mSignal = signal; + } + private final int mMode; + private final int mPid; + private final String mPackageName; + private final boolean mSignal; + + int getMode() { + return mMode; + } + int getPid() { + return mPid; + } + String getPackageName() { + return mPackageName; + } + boolean getSignal() { + return mSignal; + } + } + + void postUpdateAudioMode(int msgPolicy, int mode, int pid, String packageName, + boolean signal, int delay) { + synchronized (mAudioModeResetLock) { + if (signal) { + mAudioModeResetCount++; } + sendMsg(mAudioHandler, MSG_UPDATE_AUDIO_MODE, msgPolicy, 0, 0, + new UpdateAudioModeInfo(mode, pid, packageName, signal), delay); } } @@ -6152,13 +6185,9 @@ public class AudioService extends IAudioService.Stub } else { SetModeDeathHandler h = mSetModeDeathHandlers.get(index); mSetModeDeathHandlers.remove(index); - sendMsg(mAudioHandler, - MSG_UPDATE_AUDIO_MODE, - SENDMSG_QUEUE, - AudioSystem.MODE_CURRENT, - android.os.Process.myPid(), - mContext.getPackageName(), - 0); + postUpdateAudioMode(SENDMSG_QUEUE, AudioSystem.MODE_CURRENT, + android.os.Process.myPid(), mContext.getPackageName(), + false /*signal*/, 0); } } } @@ -6404,19 +6433,14 @@ public class AudioService extends IAudioService.Stub } } - sendMsg(mAudioHandler, - MSG_UPDATE_AUDIO_MODE, - SENDMSG_REPLACE, - mode, - pid, - callingPackage, - 0); + postUpdateAudioMode(SENDMSG_REPLACE, mode, pid, callingPackage, + hasModifyPhoneStatePermission && mode == AudioSystem.MODE_NORMAL, 0); } } @GuardedBy("mDeviceBroker.mSetModeLock") void onUpdateAudioMode(int requestedMode, int requesterPid, String requesterPackage, - boolean force) { + boolean force, boolean signal) { if (requestedMode == AudioSystem.MODE_CURRENT) { requestedMode = getMode(); } @@ -6431,7 +6455,7 @@ public class AudioService extends IAudioService.Stub } if (DEBUG_MODE) { Log.v(TAG, "onUpdateAudioMode() new mode: " + mode + ", current mode: " - + mMode.get() + " requested mode: " + requestedMode); + + mMode.get() + " requested mode: " + requestedMode + " signal: " + signal); } if (mode != mMode.get() || force) { int status = AudioSystem.SUCCESS; @@ -6477,7 +6501,7 @@ public class AudioService extends IAudioService.Stub // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO // connections not started by the application changing the mode when pid changes - mDeviceBroker.postSetModeOwner(mode, pid, uid); + mDeviceBroker.postSetModeOwner(mode, pid, uid, signal); } else { Log.w(TAG, "onUpdateAudioMode: failed to set audio mode to: " + mode); } @@ -10162,7 +10186,7 @@ public class AudioService extends IAudioService.Stub h.setRecordingActive(isRecordingActiveForUid(h.getUid())); if (wasActive != h.isActive()) { onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(), - mContext.getPackageName(), false /*force*/); + mContext.getPackageName(), false /*force*/, false /*signal*/); } } break; @@ -10192,7 +10216,9 @@ public class AudioService extends IAudioService.Stub case MSG_UPDATE_AUDIO_MODE: synchronized (mDeviceBroker.mSetModeLock) { - onUpdateAudioMode(msg.arg1, msg.arg2, (String) msg.obj, false /*force*/); + UpdateAudioModeInfo info = (UpdateAudioModeInfo) msg.obj; + onUpdateAudioMode(info.getMode(), info.getPid(), info.getPackageName(), + false /*force*/, info.getSignal()); } break; @@ -10895,9 +10921,59 @@ public class AudioService extends IAudioService.Stub return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } mmi.record(); + //delay abandon focus requests from Telecom if an audio mode reset from Telecom + // is still being processed + final boolean abandonFromTelecom = (mContext.checkCallingOrSelfPermission( + MODIFY_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) + && ((aa != null && aa.getUsage() == AudioAttributes.USAGE_VOICE_COMMUNICATION) + || AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)); + if (abandonFromTelecom) { + synchronized (mAudioModeResetLock) { + final long start = java.lang.System.currentTimeMillis(); + long elapsed = 0; + while (mAudioModeResetCount > 0) { + if (DEBUG_MODE) { + Log.i(TAG, "Abandon focus from Telecom, waiting for mode change"); + } + try { + mAudioModeResetLock.wait( + AUDIO_MODE_RESET_TIMEOUT_MS - elapsed); + } catch (InterruptedException e) { + Log.w(TAG, "Interrupted while waiting for audio mode reset"); + } + elapsed = java.lang.System.currentTimeMillis() - start; + if (elapsed >= AUDIO_MODE_RESET_TIMEOUT_MS) { + Log.e(TAG, "Timeout waiting for audio mode reset"); + break; + } + } + if (DEBUG_MODE && elapsed != 0) { + Log.i(TAG, "Abandon focus from Telecom done waiting"); + } + } + } return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName); } + /** synchronization between setMode(NORMAL) and abandonAudioFocus() frmo Telecom */ + private static final long AUDIO_MODE_RESET_TIMEOUT_MS = 3000; + + private final Object mAudioModeResetLock = new Object(); + + @GuardedBy("mAudioModeResetLock") + private int mAudioModeResetCount = 0; + + void decrementAudioModeResetCount() { + synchronized (mAudioModeResetLock) { + if (mAudioModeResetCount > 0) { + mAudioModeResetCount--; + } else { + Log.w(TAG, "mAudioModeResetCount already 0"); + } + mAudioModeResetLock.notify(); + } + } + /** see {@link AudioManager#abandonAudioFocusForTest(AudioFocusRequest, String)} */ public int abandonAudioFocusForTest(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa, String callingPackageName) { |