diff options
author | Ihab Awad <ihab@google.com> | 2015-05-19 09:23:21 -0700 |
---|---|---|
committer | Ihab Awad <ihab@google.com> | 2015-05-19 12:04:37 -0700 |
commit | 731369c3983628e700f161138fe2ea3230033a1a (patch) | |
tree | 97e81f8ca36cf76fdbc8e4ea754aebaefb34fb69 /src/com/android/server | |
parent | cd9e3e9fb3c30cffc525324c274c77f83f7c2c55 (diff) | |
download | android_packages_services_Telecomm-731369c3983628e700f161138fe2ea3230033a1a.tar.gz android_packages_services_Telecomm-731369c3983628e700f161138fe2ea3230033a1a.tar.bz2 android_packages_services_Telecomm-731369c3983628e700f161138fe2ea3230033a1a.zip |
Sync for HeadsetMediaButton
Add synchronization and deferred execution to our interactions with
MediaSession, since MediaSession sometimes calls back via an RPC into
Telecom and can cause us to deadlock.
Bug: 21028885
Change-Id: I8fc0574269a81e817e1c139aa0fe56258c96bd64
Diffstat (limited to 'src/com/android/server')
4 files changed, 66 insertions, 24 deletions
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java index 845fe7fe..24214cb8 100644 --- a/src/com/android/server/telecom/CallsManager.java +++ b/src/com/android/server/telecom/CallsManager.java @@ -172,7 +172,7 @@ public class CallsManager extends Call.ListenerBase { context, statusBarNotifier, mWiredHeadsetManager, mDockManager, this); InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(mCallAudioManager, lock); mRinger = new Ringer(mCallAudioManager, this, playerFactory, context); - mHeadsetMediaButton = headsetMediaButtonFactory.create(context, this); + mHeadsetMediaButton = headsetMediaButtonFactory.create(context, this, mLock); mTtyManager = new TtyManager(context, mWiredHeadsetManager); mProximitySensorManager = proximitySensorManagerFactory.create(context, this); mPhoneStateBroadcaster = new PhoneStateBroadcaster(this); diff --git a/src/com/android/server/telecom/HeadsetMediaButton.java b/src/com/android/server/telecom/HeadsetMediaButton.java index 5d55edd2..93dc6dec 100644 --- a/src/com/android/server/telecom/HeadsetMediaButton.java +++ b/src/com/android/server/telecom/HeadsetMediaButton.java @@ -16,11 +16,13 @@ package com.android.server.telecom; -import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.media.AudioAttributes; import android.media.session.MediaSession; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.view.KeyEvent; /** @@ -36,35 +38,72 @@ public class HeadsetMediaButton extends CallsManagerListenerBase { .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION).build(); + private static final int MSG_MEDIA_SESSION_INITIALIZE = 0; + private static final int MSG_MEDIA_SESSION_SET_ACTIVE = 1; + private final MediaSession.Callback mSessionCallback = new MediaSession.Callback() { @Override public boolean onMediaButtonEvent(Intent intent) { KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); Log.v(this, "SessionCallback.onMediaButton()... event = %s.", event); if ((event != null) && (event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) { - Log.v(this, "SessionCallback: HEADSETHOOK"); - boolean consumed = handleHeadsetHook(event); - Log.v(this, "==> handleHeadsetHook(): consumed = %b.", consumed); - return consumed; + synchronized (mLock) { + Log.v(this, "SessionCallback: HEADSETHOOK"); + boolean consumed = handleHeadsetHook(event); + Log.v(this, "==> handleHeadsetHook(): consumed = %b.", consumed); + return consumed; + } } return true; } }; - private final CallsManager mCallsManager; + private final Handler mMediaSessionHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_MEDIA_SESSION_INITIALIZE: { + MediaSession session = new MediaSession( + mContext, + HeadsetMediaButton.class.getSimpleName()); + session.setCallback(mSessionCallback); + session.setFlags(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY + | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS); + session.setPlaybackToLocal(AUDIO_ATTRIBUTES); + mSession = session; + break; + } + case MSG_MEDIA_SESSION_SET_ACTIVE: { + if (mSession != null) { + boolean activate = msg.arg1 != 0; + if (activate != mSession.isActive()) { + mSession.setActive(activate); + } + } + break; + } + default: + break; + } + } + }; - private final MediaSession mSession; + private final Context mContext; + private final CallsManager mCallsManager; + private final TelecomSystem.SyncRoot mLock; + private MediaSession mSession; - public HeadsetMediaButton(Context context, CallsManager callsManager) { + public HeadsetMediaButton( + Context context, + CallsManager callsManager, + TelecomSystem.SyncRoot lock) { + mContext = context; mCallsManager = callsManager; + mLock = lock; // Create a MediaSession but don't enable it yet. This is a // replacement for MediaButtonReceiver - mSession = new MediaSession(context, HeadsetMediaButton.class.getSimpleName()); - mSession.setCallback(mSessionCallback); - mSession.setFlags(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY - | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS); - mSession.setPlaybackToLocal(AUDIO_ATTRIBUTES); + mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_INITIALIZE).sendToTarget(); } /** @@ -87,18 +126,14 @@ public class HeadsetMediaButton extends CallsManagerListenerBase { /** ${inheritDoc} */ @Override public void onCallAdded(Call call) { - if (!mSession.isActive()) { - mSession.setActive(true); - } + mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 1, 0).sendToTarget(); } /** ${inheritDoc} */ @Override public void onCallRemoved(Call call) { if (!mCallsManager.hasAnyCalls()) { - if (mSession.isActive()) { - mSession.setActive(false); - } + mMediaSessionHandler.obtainMessage(MSG_MEDIA_SESSION_SET_ACTIVE, 0, 0).sendToTarget(); } } } diff --git a/src/com/android/server/telecom/HeadsetMediaButtonFactory.java b/src/com/android/server/telecom/HeadsetMediaButtonFactory.java index becabbff..13d5e4f8 100644 --- a/src/com/android/server/telecom/HeadsetMediaButtonFactory.java +++ b/src/com/android/server/telecom/HeadsetMediaButtonFactory.java @@ -16,6 +16,8 @@ package com.android.server.telecom; +import com.android.server.telecom.components.TelecomService; + import android.content.Context; /** @@ -27,5 +29,8 @@ import android.content.Context; */ public interface HeadsetMediaButtonFactory { - HeadsetMediaButton create(Context context, CallsManager callsManager); + HeadsetMediaButton create( + Context context, + CallsManager callsManager, + TelecomSystem.SyncRoot lock); } diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java index f7f40540..529645ff 100644 --- a/src/com/android/server/telecom/components/TelecomService.java +++ b/src/com/android/server/telecom/components/TelecomService.java @@ -78,9 +78,11 @@ public class TelecomService extends Service implements TelecomSystem.Component { }, new HeadsetMediaButtonFactory() { @Override - public HeadsetMediaButton create(Context context, - CallsManager callsManager) { - return new HeadsetMediaButton(context, callsManager); + public HeadsetMediaButton create( + Context context, + CallsManager callsManager, + TelecomSystem.SyncRoot lock) { + return new HeadsetMediaButton(context, callsManager, lock); } }, new ProximitySensorManagerFactory() { |