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
This commit is contained in:
tonihei 2019-09-16 11:26:44 +01:00 committed by Oliver Woodman
parent 73654e27da
commit c5ceefd609

View File

@ -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(