From 98003d36ddf10d1bf92d2a172da44bdd83512538 Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Fri, 24 Feb 2017 18:33:04 +0900 Subject: [PATCH] Send long-press of KEYCODE_HEADSETHOOK to the media key listener For the key events with the code KEYCODE_HEADSETHOOK, the MediaSessionService always starts the voice input for long-presses regardless of the media key listener, and only short-presses can be sent to the media key listener. This CL sends all media key events to the media key listener first if the listener is set. If the key event isn't consumed, short-presses will be sent to the media session and long-presses will start the voice input. Bug: 35348856 Test: Manual test (Install the OnMediaKeyListener test app and confirm that the app can consume the media key long-press) Change-Id: I82f8e5f355efe16867e6f4345c46470c690e1f80 --- .../media/session/MediaSessionManager.java | 11 ++-- .../server/media/MediaSessionService.java | 51 ++++++++++--------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 80d2a0c2149e7..1bfe6c5129e09 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -439,6 +439,9 @@ public final class MediaSessionManager { public interface OnMediaKeyListener { /** * Called when the media key is pressed. + *

If the listener consumes the initial down event (i.e. ACTION_DOWN with + * repeat count zero), it must also comsume all following key events. + * (i.e. ACTION_DOWN with repeat count more than zero, and ACTION_UP). *

If it takes more than 1s to return, the key event will be sent to * other media sessions. */ @@ -534,9 +537,11 @@ public final class MediaSessionManager { public void run() { boolean handled = mListener.onMediaKey(event); Log.d(TAG, "The media key listener is returned " + handled); - result.send( - handled ? RESULT_MEDIA_KEY_HANDLED : RESULT_MEDIA_KEY_NOT_HANDLED, - null); + if (result != null) { + result.send( + handled ? RESULT_MEDIA_KEY_HANDLED : RESULT_MEDIA_KEY_NOT_HANDLED, + null); + } } }); } diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index dfa2f863d0683..9ab685d508c4a 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -811,10 +811,26 @@ public class MediaSessionService extends SystemService implements Monitor { + "to the global priority session."); return; } + if (!isGlobalPriorityActive) { + // Only consider full user. + UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0)); + if (user.mOnMediaKeyListener != null) { + if (DEBUG_KEY_EVENT) { + Log.d(TAG, "Send " + keyEvent + " to media key listener"); + } + try { + user.mOnMediaKeyListener.onMediaKey(keyEvent, + new MediaKeyListenerResultReceiver(keyEvent, needWakeLock)); + return; + } catch (RemoteException e) { + Log.w(TAG, "Failed to send " + keyEvent + " to media key listener"); + } + } + } if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) { handleVoiceKeyEventLocked(keyEvent, needWakeLock); } else { - dispatchMediaKeyEventLocked(keyEvent, needWakeLock, true); + dispatchMediaKeyEventLocked(keyEvent, needWakeLock); } } } finally { @@ -1193,15 +1209,14 @@ public class MediaSessionService extends SystemService implements Monitor { if (!mVoiceButtonHandled && !keyEvent.isCanceled()) { // Resend the down then send this event through KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN); - dispatchMediaKeyEventLocked(downEvent, needWakeLock, true); - dispatchMediaKeyEventLocked(keyEvent, needWakeLock, true); + dispatchMediaKeyEventLocked(downEvent, needWakeLock); + dispatchMediaKeyEventLocked(keyEvent, needWakeLock); } } } } - private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock, - boolean checkMediaKeyListener) { + private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) { // If we don't have a media button receiver to fall back on // include non-playing sessions for dispatching. boolean useNotPlayingSessions = true; @@ -1220,25 +1235,6 @@ public class MediaSessionService extends SystemService implements Monitor { MediaSessionRecord session = mPriorityStack.getDefaultMediaButtonSession( mCurrentUserIdList, useNotPlayingSessions); - - if ((session == null - || !session.hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) - && checkMediaKeyListener) { - // Only consider full user. - UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0)); - if (user.mOnMediaKeyListener != null) { - if (DEBUG_KEY_EVENT) { - Log.d(TAG, "Send " + keyEvent + " to media key listener"); - } - try { - user.mOnMediaKeyListener.onMediaKey(keyEvent, - new MediaKeyListenerResultReceiver(keyEvent, needWakeLock)); - return; - } catch (RemoteException e) { - Log.w(TAG, "Failed to send " + keyEvent + " to media key listener"); - } - } - } if (session != null) { if (DEBUG_KEY_EVENT) { Log.d(TAG, "Sending " + keyEvent + " to " + session); @@ -1397,7 +1393,12 @@ public class MediaSessionService extends SystemService implements Monitor { mHandled = true; mHandler.removeCallbacks(this); synchronized (mLock) { - dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock, false); + if (!mPriorityStack.isGlobalPriorityActive() + && isVoiceKey(mKeyEvent.getKeyCode())) { + handleVoiceKeyEventLocked(mKeyEvent, mNeedWakeLock); + } else { + dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock); + } } } }