Skip to content

Commit

Permalink
Transform double-tap of HEADSETHOOK to skip-to-next
Browse files Browse the repository at this point in the history
As reported in Issue: #1493 we already use `HEADSETHOOK` to start
waiting for a double-tap, but we don't consider it for the second tap.

Similarly, we previously considered `PLAY` for the second tap, but not the first.
Only `HEADSETHOOK` and `PLAY_PAUSE` are
[documented](https://developer.android.com/reference/androidx/media3/session/MediaSession#media-key-events-mapping)
to transform double-tap to `seekToNext`. So this change removes the
`PLAY` detection from the second tap.

#cherrypick

PiperOrigin-RevId: 651017522
  • Loading branch information
icbaker authored and copybara-github committed Jul 10, 2024
1 parent e8778d7 commit c64dacf
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 2 deletions.
4 changes: 4 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
playback can't be suppressed without the system crashing the service
with a `ForegroundServiceDidNotStartInTimeException`
([#1528](https://github.com/google/ExoPlayer/issues/1528)).
* Transform a double-tap of `KEYCODE_HEADSETHOOK` into a 'seek to next'
action, as
[documented](https://developer.android.com/reference/androidx/media3/session/MediaSession#media-key-events-mapping)
([#1493](https://github.com/androidx/media/issues/1493)).
* UI:
* Downloads:
* OkHttp Extension:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,8 @@ private void handleAvailablePlayerCommandsChanged(Player.Commands availableComma
}

if (!isMediaNotificationControllerConnected()) {
if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE && doubleTapCompleted) {
if ((keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_HEADSETHOOK)
&& doubleTapCompleted) {
// Double tap completion for legacy when media notification controller is disabled.
sessionLegacyStub.onSkipToNext();
return true;
Expand All @@ -1262,7 +1263,7 @@ private boolean applyMediaButtonKeyEvent(KeyEvent keyEvent, boolean doubleTapCom
ControllerInfo controllerInfo = checkNotNull(instance.getMediaNotificationControllerInfo());
Runnable command;
int keyCode = keyEvent.getKeyCode();
if ((keyCode == KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KEYCODE_MEDIA_PLAY)
if ((keyCode == KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_HEADSETHOOK)
&& doubleTapCompleted) {
keyCode = KEYCODE_MEDIA_NEXT;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,20 @@ public void playPauseKeyEvent_doubleTapOnPlayPause_seekNext() throws Exception {
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
}

@Test
public void playPauseKeyEvent_doubleTapOnHeadsetHook_seekNext() throws Exception {
Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19.
handler.postAndSync(
() -> {
player.playWhenReady = true;
player.playbackState = Player.STATE_READY;
});

dispatchMediaKeyEvent(KeyEvent.KEYCODE_HEADSETHOOK, /* doubleTap= */ true);

player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
}

private MediaController connectMediaNotificationController() throws Exception {
return threadTestRule
.getHandler()
Expand Down

0 comments on commit c64dacf

Please sign in to comment.