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. */
|
/** The default rewind increment, in milliseconds. */
|
||||||
public static final int DEFAULT_REWIND_MS = 5000;
|
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";
|
public static final String EXTRAS_PITCH = "EXO_PITCH";
|
||||||
|
|
||||||
private static final long BASE_PLAYBACK_ACTIONS =
|
private static final long BASE_PLAYBACK_ACTIONS =
|
||||||
@ -686,7 +695,13 @@ public final class MediaSessionConnector {
|
|||||||
PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder();
|
PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder();
|
||||||
@Nullable Player player = this.player;
|
@Nullable Player player = this.player;
|
||||||
if (player == null) {
|
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());
|
mediaSession.setPlaybackState(builder.build());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -702,16 +717,13 @@ public final class MediaSessionConnector {
|
|||||||
}
|
}
|
||||||
customActionMap = Collections.unmodifiableMap(currentActions);
|
customActionMap = Collections.unmodifiableMap(currentActions);
|
||||||
|
|
||||||
int playbackState = player.getPlaybackState();
|
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
@Nullable
|
@Nullable ExoPlaybackException playbackError = player.getPlaybackError();
|
||||||
ExoPlaybackException playbackError =
|
|
||||||
playbackState == Player.STATE_IDLE ? player.getPlaybackError() : null;
|
|
||||||
boolean reportError = playbackError != null || customError != null;
|
boolean reportError = playbackError != null || customError != null;
|
||||||
int sessionPlaybackState =
|
int sessionPlaybackState =
|
||||||
reportError
|
reportError
|
||||||
? PlaybackStateCompat.STATE_ERROR
|
? PlaybackStateCompat.STATE_ERROR
|
||||||
: mapPlaybackState(player.getPlaybackState(), player.getPlayWhenReady());
|
: getMediaSessionPlaybackState(player.getPlaybackState(), player.getPlayWhenReady());
|
||||||
if (customError != null) {
|
if (customError != null) {
|
||||||
builder.setErrorMessage(customError.first, customError.second);
|
builder.setErrorMessage(customError.first, customError.second);
|
||||||
if (customErrorExtras != null) {
|
if (customErrorExtras != null) {
|
||||||
@ -726,6 +738,10 @@ public final class MediaSessionConnector {
|
|||||||
? queueNavigator.getActiveQueueItemId(player)
|
? queueNavigator.getActiveQueueItemId(player)
|
||||||
: MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
: MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
||||||
extras.putFloat(EXTRAS_PITCH, player.getPlaybackParameters().pitch);
|
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
|
builder
|
||||||
.setActions(buildPrepareActions() | buildPlaybackActions(player))
|
.setActions(buildPrepareActions() | buildPlaybackActions(player))
|
||||||
.setActiveQueueItemId(activeQueueItemId)
|
.setActiveQueueItemId(activeQueueItemId)
|
||||||
@ -733,8 +749,8 @@ public final class MediaSessionConnector {
|
|||||||
.setState(
|
.setState(
|
||||||
sessionPlaybackState,
|
sessionPlaybackState,
|
||||||
player.getCurrentPosition(),
|
player.getCurrentPosition(),
|
||||||
player.getPlaybackParameters().speed,
|
sessionPlaybackSpeed,
|
||||||
SystemClock.elapsedRealtime())
|
/* updateTime= */ SystemClock.elapsedRealtime())
|
||||||
.setExtras(extras);
|
.setExtras(extras);
|
||||||
mediaSession.setPlaybackState(builder.build());
|
mediaSession.setPlaybackState(builder.build());
|
||||||
}
|
}
|
||||||
@ -831,19 +847,6 @@ public final class MediaSessionConnector {
|
|||||||
return actions;
|
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")
|
@EnsuresNonNullIf(result = true, expression = "player")
|
||||||
private boolean canDispatchPlaybackAction(long action) {
|
private boolean canDispatchPlaybackAction(long action) {
|
||||||
return player != null && (enabledPlaybackActions & action) != 0;
|
return player != null && (enabledPlaybackActions & action) != 0;
|
||||||
@ -910,6 +913,20 @@ public final class MediaSessionConnector {
|
|||||||
controlDispatcher.dispatchSeekTo(player, windowIndex, 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
|
* Provides a default {@link MediaMetadataCompat} with properties and extras taken from the {@link
|
||||||
* MediaDescriptionCompat} of the {@link MediaSessionCompat.QueueItem} of the active queue item.
|
* MediaDescriptionCompat} of the {@link MediaSessionCompat.QueueItem} of the active queue item.
|
||||||
@ -1045,6 +1062,11 @@ public final class MediaSessionConnector {
|
|||||||
invalidateMediaSessionPlaybackState();
|
invalidateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onIsPlayingChanged(boolean isPlaying) {
|
||||||
|
invalidateMediaSessionPlaybackState();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
||||||
mediaSession.setRepeatMode(
|
mediaSession.setRepeatMode(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user