From c5ceefd6097a84c07159e2293316b7ff9fb7954f Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 16 Sep 2019 11:26:44 +0100 Subject: [PATCH] Fix playback speed in MediaSessionConnector The playback speed set in MediaSession's PlaybackStateCompat needs to be the actual speed at which the playback position progresses and not the user-defined target speed. This fixed a bug where the position advances although the player lost audio focus. Issue:#6203 PiperOrigin-RevId: 269295249 --- .../mediasession/MediaSessionConnector.java | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index 27a6c82c8c..c07ddc8d09 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -132,6 +132,15 @@ public final class MediaSessionConnector { /** The default rewind increment, in milliseconds. */ public static final int DEFAULT_REWIND_MS = 5000; + /** + * The name of the {@link PlaybackStateCompat} float extra with the value of {@link + * PlaybackParameters#speed}. + */ + public static final String EXTRAS_SPEED = "EXO_SPEED"; + /** + * The name of the {@link PlaybackStateCompat} float extra with the value of {@link + * PlaybackParameters#pitch}. + */ public static final String EXTRAS_PITCH = "EXO_PITCH"; private static final long BASE_PLAYBACK_ACTIONS = @@ -686,7 +695,13 @@ public final class MediaSessionConnector { PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder(); @Nullable Player player = this.player; if (player == null) { - builder.setActions(buildPrepareActions()).setState(PlaybackStateCompat.STATE_NONE, 0, 0, 0); + builder + .setActions(buildPrepareActions()) + .setState( + PlaybackStateCompat.STATE_NONE, + /* position= */ 0, + /* playbackSpeed= */ 0, + /* updateTime= */ SystemClock.elapsedRealtime()); mediaSession.setPlaybackState(builder.build()); return; } @@ -702,16 +717,13 @@ public final class MediaSessionConnector { } customActionMap = Collections.unmodifiableMap(currentActions); - int playbackState = player.getPlaybackState(); Bundle extras = new Bundle(); - @Nullable - ExoPlaybackException playbackError = - playbackState == Player.STATE_IDLE ? player.getPlaybackError() : null; + @Nullable ExoPlaybackException playbackError = player.getPlaybackError(); boolean reportError = playbackError != null || customError != null; int sessionPlaybackState = reportError ? PlaybackStateCompat.STATE_ERROR - : mapPlaybackState(player.getPlaybackState(), player.getPlayWhenReady()); + : getMediaSessionPlaybackState(player.getPlaybackState(), player.getPlayWhenReady()); if (customError != null) { builder.setErrorMessage(customError.first, customError.second); if (customErrorExtras != null) { @@ -726,6 +738,10 @@ public final class MediaSessionConnector { ? queueNavigator.getActiveQueueItemId(player) : MediaSessionCompat.QueueItem.UNKNOWN_ID; extras.putFloat(EXTRAS_PITCH, player.getPlaybackParameters().pitch); + PlaybackParameters playbackParameters = player.getPlaybackParameters(); + extras.putFloat(EXTRAS_SPEED, playbackParameters.speed); + extras.putFloat(EXTRAS_PITCH, playbackParameters.pitch); + float sessionPlaybackSpeed = player.isPlaying() ? playbackParameters.speed : 0f; builder .setActions(buildPrepareActions() | buildPlaybackActions(player)) .setActiveQueueItemId(activeQueueItemId) @@ -733,8 +749,8 @@ public final class MediaSessionConnector { .setState( sessionPlaybackState, player.getCurrentPosition(), - player.getPlaybackParameters().speed, - SystemClock.elapsedRealtime()) + sessionPlaybackSpeed, + /* updateTime= */ SystemClock.elapsedRealtime()) .setExtras(extras); mediaSession.setPlaybackState(builder.build()); } @@ -831,19 +847,6 @@ public final class MediaSessionConnector { return actions; } - private int mapPlaybackState(int exoPlayerPlaybackState, boolean playWhenReady) { - switch (exoPlayerPlaybackState) { - case Player.STATE_BUFFERING: - return PlaybackStateCompat.STATE_BUFFERING; - case Player.STATE_READY: - return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED; - case Player.STATE_ENDED: - return PlaybackStateCompat.STATE_STOPPED; - default: - return PlaybackStateCompat.STATE_NONE; - } - } - @EnsuresNonNullIf(result = true, expression = "player") private boolean canDispatchPlaybackAction(long action) { return player != null && (enabledPlaybackActions & action) != 0; @@ -910,6 +913,20 @@ public final class MediaSessionConnector { controlDispatcher.dispatchSeekTo(player, windowIndex, positionMs); } + private static int getMediaSessionPlaybackState( + @Player.State int exoPlayerPlaybackState, boolean playWhenReady) { + switch (exoPlayerPlaybackState) { + case Player.STATE_BUFFERING: + return PlaybackStateCompat.STATE_BUFFERING; + case Player.STATE_READY: + return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED; + case Player.STATE_ENDED: + return PlaybackStateCompat.STATE_STOPPED; + default: + return PlaybackStateCompat.STATE_NONE; + } + } + /** * Provides a default {@link MediaMetadataCompat} with properties and extras taken from the {@link * MediaDescriptionCompat} of the {@link MediaSessionCompat.QueueItem} of the active queue item. @@ -1045,6 +1062,11 @@ public final class MediaSessionConnector { invalidateMediaSessionPlaybackState(); } + @Override + public void onIsPlayingChanged(boolean isPlaying) { + invalidateMediaSessionPlaybackState(); + } + @Override public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { mediaSession.setRepeatMode(