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 f8d81d05a4
commit bbb739d1de

View File

@ -131,6 +131,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 =
@ -684,7 +693,13 @@ public final class MediaSessionConnector {
public final void invalidateMediaSessionPlaybackState() {
PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder();
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;
}
@ -699,15 +714,13 @@ public final class MediaSessionConnector {
}
customActionMap = Collections.unmodifiableMap(currentActions);
int playbackState = player.getPlaybackState();
Bundle extras = new Bundle();
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) {
@ -722,6 +735,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)
@ -729,8 +746,8 @@ public final class MediaSessionConnector {
.setState(
sessionPlaybackState,
player.getCurrentPosition(),
player.getPlaybackParameters().speed,
SystemClock.elapsedRealtime())
sessionPlaybackSpeed,
/* updateTime= */ SystemClock.elapsedRealtime())
.setExtras(extras);
mediaSession.setPlaybackState(builder.build());
}
@ -823,19 +840,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;
}
}
private boolean canDispatchPlaybackAction(long action) {
return player != null && (enabledPlaybackActions & action) != 0;
}
@ -888,6 +892,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.
@ -1022,6 +1040,11 @@ public final class MediaSessionConnector {
invalidateMediaSessionPlaybackState();
}
@Override
public void onIsPlayingChanged(boolean isPlaying) {
invalidateMediaSessionPlaybackState();
}
@Override
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
mediaSession.setRepeatMode(