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:
parent
73654e27da
commit
c5ceefd609
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user