summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/media
diff options
context:
space:
mode:
authorDongwon Kang <dwkang@google.com>2015-06-16 15:28:17 -0700
committerDongwon Kang <dwkang@google.com>2015-06-17 15:37:50 -0700
commita38e1f4ed997bea3cbfbf8094a52c23570d59d2a (patch)
tree12c13f805feb71d70e87d59e256b03ee120c6332 /services/core/java/com/android/server/media
parent2d4dc8db64d0f75e530451acb2c0bea97b9264ff (diff)
downloadframeworks_base-a38e1f4ed997bea3cbfbf8094a52c23570d59d2a.zip
frameworks_base-a38e1f4ed997bea3cbfbf8094a52c23570d59d2a.tar.gz
frameworks_base-a38e1f4ed997bea3cbfbf8094a52c23570d59d2a.tar.bz2
Make MediaSessionService not blocked by AudioService.
Backgroud: As noted in b/20823981, MediaSessionService calls some audio service methods while holding a lock and the audio service methods also talk to other system services. And, deadlock happens when the other system service fires another request to MediaSessionService while holding its lock. Example1) --- resolved by the change in MediaSessionRecord.java T1: MediaSessionService.dispatchAdjustVolumeLocked() -> MediaSessionRecord.adjustVolume() -> +++AudioServiceInternal.adjustSuggestedStreamVolumeForUid()+++ -> AudioService.adjustSuggestedStreamVolume() -> telecom.TelecomManager.isInCall() --- blocked by lock in TelecomManager. T2: telecom.ConnectionServiceWrapper.handleCreateConnectionComplete() -> MediaSession.setActive() -> MediaSessionRecord$SessionStub.setActive() -> MediaSessionService.updateSession() --- blocked by lock in MediaSessionService. Example2) --- resolved by the change in IAudioService.aidl T1: MediaSessionService.dispatchAdjustVolumeLocked() -> IAudioService.adjustSuggestedStreamVolume() -> AudioService.adjustSuggestedStreamVolume() -> telecom.TelecomManager.isInCall() --- blocked by lock in TelecomManager. T2: telecom.ConnectionServiceWrapper.handleCreateConnectionComplete() -> MediaSession.setActive() -> MediaSessionRecord$SessionStub.setActive() -> MediaSessionService.updateSession() --- blocked by lock in MediaSessionService. Here, this change prevents the deadlock by making related audio IPC oneway and calling the internal audio method without holding the lock. Bug: 20823981 Change-Id: I4c4b2fc796f23d83be67f7edaacd7496c145d985
Diffstat (limited to 'services/core/java/com/android/server/media')
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java34
1 files changed, 27 insertions, 7 deletions
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index dca762c..569a0fc 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -242,19 +242,17 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
+ // Adjust the volume with a handler not to be blocked by other system service.
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
- mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction,
- flags, packageName, uid);
+ postAdjustSuggestedStreamVolume(stream, direction, flags, packageName, uid);
} else {
flags |= previousFlagPlaySound;
- mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
- AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName,
- uid);
+ postAdjustSuggestedStreamVolume(AudioManager.USE_DEFAULT_STREAM_TYPE, direction,
+ flags, packageName, uid);
}
} else {
- mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
- packageName, uid);
+ postAdjustStreamVolume(stream, direction, flags, packageName, uid);
}
} else {
if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
@@ -461,6 +459,28 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return mPackageName + "/" + mTag;
}
+ private void postAdjustSuggestedStreamVolume(final int streamType, final int direction,
+ final int flags, final String callingPackage, final int uid) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(streamType, direction,
+ flags, callingPackage, uid);
+ }
+ });
+ }
+
+ private void postAdjustStreamVolume(final int streamType, final int direction, final int flags,
+ final String callingPackage, final int uid) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAudioManagerInternal.adjustStreamVolumeForUid(streamType, direction, flags,
+ callingPackage, uid);
+ }
+ });
+ }
+
private String getShortMetadataString() {
int fields = mMetadata == null ? 0 : mMetadata.size();
MediaDescription description = mMetadata == null ? null : mMetadata