diff options
| author | 2017-06-25 01:26:41 +0000 | |
|---|---|---|
| committer | 2017-06-25 01:26:49 +0000 | |
| commit | f05929af73eaa5f439e7b71de2ac6c1ab0cc9555 (patch) | |
| tree | 69fc8dc9e788d4633eaae5dd4154e6bce9e261d3 | |
| parent | 10a41f9b128fe465521f099aaf0a4d2b6047e03b (diff) | |
| parent | 74d002be26ec9800cb494471f0773493bc83d8f7 (diff) | |
Merge "Consider double tap of the play/pause as the next track" into oc-dr1-dev
| -rw-r--r-- | media/java/android/media/session/MediaSession.java | 78 | 
1 files changed, 59 insertions, 19 deletions
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index dfd2bb35d6ea..44bd252a349e 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -43,6 +43,7 @@ import android.service.media.MediaBrowserService;  import android.text.TextUtils;  import android.util.Log;  import android.view.KeyEvent; +import android.view.ViewConfiguration;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy; @@ -200,8 +201,7 @@ public final class MediaSession {                  return;              }              if (mCallback != null) { -                // We're updating the callback, clear the session from the old -                // one. +                // We're updating the callback, clear the session from the old one.                  mCallback.mCallback.mSession = null;              }              if (handler == null) { @@ -735,6 +735,8 @@ public final class MediaSession {       */      public abstract static class Callback {          private MediaSession mSession; +        private CallbackMessageHandler mHandler; +        private boolean mMediaPlayPauseKeyPending;          public Callback() {          } @@ -766,13 +768,41 @@ public final class MediaSession {           * @return True if the event was handled, false otherwise.           */          public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) { -            if (mSession != null +            if (mSession != null && mHandler != null                      && Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) {                  KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);                  if (ke != null && ke.getAction() == KeyEvent.ACTION_DOWN) {                      PlaybackState state = mSession.mPlaybackState;                      long validActions = state == null ? 0 : state.getActions();                      switch (ke.getKeyCode()) { +                        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: +                        case KeyEvent.KEYCODE_HEADSETHOOK: +                            if (ke.getRepeatCount() > 0) { +                                // Consider long-press as a single tap. +                                handleMediaPlayPauseKeySingleTapIfPending(); +                            } else if (mMediaPlayPauseKeyPending) { +                                // Consider double tap as the next. +                                mHandler.removeMessages(CallbackMessageHandler +                                        .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT); +                                mMediaPlayPauseKeyPending = false; +                                if ((validActions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) { +                                    onSkipToNext(); +                                } +                            } else { +                                mMediaPlayPauseKeyPending = true; +                                mHandler.sendEmptyMessageDelayed(CallbackMessageHandler +                                        .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT, +                                        ViewConfiguration.getDoubleTapTimeout()); +                            } +                            return true; +                        default: +                            // If another key is pressed within double tap timeout, consider the +                            // pending play/pause as a single tap to handle media keys in order. +                            handleMediaPlayPauseKeySingleTapIfPending(); +                            break; +                    } + +                    switch (ke.getKeyCode()) {                          case KeyEvent.KEYCODE_MEDIA_PLAY:                              if ((validActions & PlaybackState.ACTION_PLAY) != 0) {                                  onPlay(); @@ -815,28 +845,33 @@ public final class MediaSession {                                  return true;                              }                              break; -                        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: -                        case KeyEvent.KEYCODE_HEADSETHOOK: -                            boolean isPlaying = state == null ? false -                                    : state.getState() == PlaybackState.STATE_PLAYING; -                            boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE -                                    | PlaybackState.ACTION_PLAY)) != 0; -                            boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE -                                    | PlaybackState.ACTION_PAUSE)) != 0; -                            if (isPlaying && canPause) { -                                onPause(); -                                return true; -                            } else if (!isPlaying && canPlay) { -                                onPlay(); -                                return true; -                            } -                            break;                      }                  }              }              return false;          } +        private void handleMediaPlayPauseKeySingleTapIfPending() { +            if (!mMediaPlayPauseKeyPending) { +                return; +            } +            mMediaPlayPauseKeyPending = false; +            mHandler.removeMessages(CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT); +            PlaybackState state = mSession.mPlaybackState; +            long validActions = state == null ? 0 : state.getActions(); +            boolean isPlaying = state != null +                    && state.getState() == PlaybackState.STATE_PLAYING; +            boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE +                        | PlaybackState.ACTION_PLAY)) != 0; +            boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE +                        | PlaybackState.ACTION_PAUSE)) != 0; +            if (isPlaying && canPause) { +                onPause(); +            } else if (!isPlaying && canPlay) { +                onPlay(); +            } +        } +          /**           * Override to handle requests to prepare playback. During the preparation, a session should           * not hold audio focus in order to allow other sessions play seamlessly. The state of @@ -1294,12 +1329,14 @@ public final class MediaSession {          private static final int MSG_CUSTOM_ACTION = 20;          private static final int MSG_ADJUST_VOLUME = 21;          private static final int MSG_SET_VOLUME = 22; +        private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;          private MediaSession.Callback mCallback;          public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {              super(looper, null, true);              mCallback = callback; +            mCallback.mHandler = this;          }          public void post(int what, Object obj, Bundle bundle) { @@ -1401,6 +1438,9 @@ public final class MediaSession {                          vp.onSetVolumeTo((int) msg.obj);                      }                      break; +                case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT: +                    mCallback.handleMediaPlayPauseKeySingleTapIfPending(); +                    break;              }          }      }  |