Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db7927c2 authored by Jaewan Kim's avatar Jaewan Kim Committed by android-build-merger
Browse files

Merge "Consider double tap of the play/pause as the next track" into oc-dr1-dev

am: f05929af

Change-Id: I6cbcf4485db688a47135b3fe471a14fa78492cea
parents e504d0be f05929af
Loading
Loading
Loading
Loading
+59 −19
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ import android.service.media.MediaBrowserService;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.ViewConfiguration;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
@@ -200,8 +201,7 @@ public final class MediaSession {
                return;
                return;
            }
            }
            if (mCallback != null) {
            if (mCallback != null) {
                // We're updating the callback, clear the session from the old
                // We're updating the callback, clear the session from the old one.
                // one.
                mCallback.mCallback.mSession = null;
                mCallback.mCallback.mSession = null;
            }
            }
            if (handler == null) {
            if (handler == null) {
@@ -735,6 +735,8 @@ public final class MediaSession {
     */
     */
    public abstract static class Callback {
    public abstract static class Callback {
        private MediaSession mSession;
        private MediaSession mSession;
        private CallbackMessageHandler mHandler;
        private boolean mMediaPlayPauseKeyPending;


        public Callback() {
        public Callback() {
        }
        }
@@ -766,12 +768,40 @@ public final class MediaSession {
         * @return True if the event was handled, false otherwise.
         * @return True if the event was handled, false otherwise.
         */
         */
        public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
        public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
            if (mSession != null
            if (mSession != null && mHandler != null
                    && Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) {
                    && Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) {
                KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
                KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
                if (ke != null && ke.getAction() == KeyEvent.ACTION_DOWN) {
                if (ke != null && ke.getAction() == KeyEvent.ACTION_DOWN) {
                    PlaybackState state = mSession.mPlaybackState;
                    PlaybackState state = mSession.mPlaybackState;
                    long validActions = state == null ? 0 : state.getActions();
                    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()) {
                    switch (ke.getKeyCode()) {
                        case KeyEvent.KEYCODE_MEDIA_PLAY:
                        case KeyEvent.KEYCODE_MEDIA_PLAY:
                            if ((validActions & PlaybackState.ACTION_PLAY) != 0) {
                            if ((validActions & PlaybackState.ACTION_PLAY) != 0) {
@@ -815,27 +845,32 @@ public final class MediaSession {
                                return true;
                                return true;
                            }
                            }
                            break;
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                    }
                        case KeyEvent.KEYCODE_HEADSETHOOK:
                }
                            boolean isPlaying = state == null ? false
            }
                                    : state.getState() == PlaybackState.STATE_PLAYING;
            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
            boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
                        | PlaybackState.ACTION_PLAY)) != 0;
                        | PlaybackState.ACTION_PLAY)) != 0;
            boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
            boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
                        | PlaybackState.ACTION_PAUSE)) != 0;
                        | PlaybackState.ACTION_PAUSE)) != 0;
            if (isPlaying && canPause) {
            if (isPlaying && canPause) {
                onPause();
                onPause();
                                return true;
            } else if (!isPlaying && canPlay) {
            } else if (!isPlaying && canPlay) {
                onPlay();
                onPlay();
                                return true;
                            }
                            break;
                    }
            }
            }
        }
        }
            return false;
        }


        /**
        /**
         * Override to handle requests to prepare playback. During the preparation, a session should
         * Override to handle requests to prepare playback. During the preparation, a session should
@@ -1294,12 +1329,14 @@ public final class MediaSession {
        private static final int MSG_CUSTOM_ACTION = 20;
        private static final int MSG_CUSTOM_ACTION = 20;
        private static final int MSG_ADJUST_VOLUME = 21;
        private static final int MSG_ADJUST_VOLUME = 21;
        private static final int MSG_SET_VOLUME = 22;
        private static final int MSG_SET_VOLUME = 22;
        private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;


        private MediaSession.Callback mCallback;
        private MediaSession.Callback mCallback;


        public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
        public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
            super(looper, null, true);
            super(looper, null, true);
            mCallback = callback;
            mCallback = callback;
            mCallback.mHandler = this;
        }
        }


        public void post(int what, Object obj, Bundle bundle) {
        public void post(int what, Object obj, Bundle bundle) {
@@ -1401,6 +1438,9 @@ public final class MediaSession {
                        vp.onSetVolumeTo((int) msg.obj);
                        vp.onSetVolumeTo((int) msg.obj);
                    }
                    }
                    break;
                    break;
                case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT:
                    mCallback.handleMediaPlayPauseKeySingleTapIfPending();
                    break;
            }
            }
        }
        }
    }
    }