summaryrefslogtreecommitdiffstats
path: root/src/com/android/server
diff options
context:
space:
mode:
authorIhab Awad <ihab@google.com>2015-05-19 09:23:21 -0700
committerIhab Awad <ihab@google.com>2015-05-19 12:04:37 -0700
commit731369c3983628e700f161138fe2ea3230033a1a (patch)
tree97e81f8ca36cf76fdbc8e4ea754aebaefb34fb69 /src/com/android/server
parentcd9e3e9fb3c30cffc525324c274c77f83f7c2c55 (diff)
downloadandroid_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')
-rw-r--r--src/com/android/server/telecom/CallsManager.java2
-rw-r--r--src/com/android/server/telecom/HeadsetMediaButton.java73
-rw-r--r--src/com/android/server/telecom/HeadsetMediaButtonFactory.java7
-rw-r--r--src/com/android/server/telecom/components/TelecomService.java8
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() {