Loading services/core/java/com/android/server/audio/AudioDeviceBroker.java +8 −5 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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(); Loading @@ -2036,6 +2036,9 @@ public class AudioDeviceBroker { } } } if (msg.arg1 == 1 /*signal*/) { mAudioService.decrementAudioModeResetCount(); } break; case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: Loading Loading @@ -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; Loading services/core/java/com/android/server/audio/AudioService.java +103 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } Loading Loading @@ -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); } } } Loading Loading @@ -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(); } Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading
services/core/java/com/android/server/audio/AudioDeviceBroker.java +8 −5 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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(); Loading @@ -2036,6 +2036,9 @@ public class AudioDeviceBroker { } } } if (msg.arg1 == 1 /*signal*/) { mAudioService.decrementAudioModeResetCount(); } break; case MSG_L_SET_COMMUNICATION_DEVICE_FOR_CLIENT: Loading Loading @@ -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; Loading
services/core/java/com/android/server/audio/AudioService.java +103 −27 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } Loading Loading @@ -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); } } } Loading Loading @@ -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(); } Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading