Skip to content

Commit

Permalink
Fix playback speed in MediaSessionConnector
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tonihei authored and ojw28 committed Sep 16, 2019
1 parent 73654e2 commit c5ceefd
Showing 1 changed file with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -686,7 +695,13 @@ public final void invalidateMediaSessionPlaybackState() {
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;
}
Expand All @@ -702,16 +717,13 @@ public final void invalidateMediaSessionPlaybackState() {
}
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) {
Expand All @@ -726,15 +738,19 @@ public final void invalidateMediaSessionPlaybackState() {
? 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)
.setBufferedPosition(player.getBufferedPosition())
.setState(
sessionPlaybackState,
player.getCurrentPosition(),
player.getPlaybackParameters().speed,
SystemClock.elapsedRealtime())
sessionPlaybackSpeed,
/* updateTime= */ SystemClock.elapsedRealtime())
.setExtras(extras);
mediaSession.setPlaybackState(builder.build());
}
Expand Down Expand Up @@ -831,19 +847,6 @@ private long buildPlaybackActions(Player player) {
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;
Expand Down Expand Up @@ -910,6 +913,20 @@ private void seekTo(Player player, int windowIndex, long positionMs) {
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.
Expand Down Expand Up @@ -1045,6 +1062,11 @@ public void onPlayerStateChanged(boolean playWhenReady, @Player.State int playba
invalidateMediaSessionPlaybackState();
}

@Override
public void onIsPlayingChanged(boolean isPlaying) {
invalidateMediaSessionPlaybackState();
}

@Override
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
mediaSession.setRepeatMode(
Expand Down

0 comments on commit c5ceefd

Please sign in to comment.