MediaController: stop advancing content position when player is paused

MediaController.getContentPosition() estimates the content position
based on the last position info sent by the player and the elapsed
real-time since the position info was received. After calling
MediaController's play/pause/setPlayWhenReady, the position estimation
logic is still applying, therefore advancing the position until the
underlying player's actual position is received. This can make the
MediaController's content position to be out of sync with player's
actual content position.

With this change, MediaController stops making content position
estimations after any of play/pause/setPlayWhenReady is called and
until a new position info is received from the underlying player.

Tested manually with the the session demo app, pausing/resuming content
from the UI.

PiperOrigin-RevId: 418000800
This commit is contained in:
christosts 2021-12-23 14:51:17 +00:00 committed by tonihei
parent a9660de192
commit 036a28b292

View File

@ -186,6 +186,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
private int surfaceWidth;
private int surfaceHeight;
@Nullable private IMediaSession iSession;
private long lastReturnedContentPositionMs;
private long lastSetPlayWhenReadyCalledTimeMs;
public MediaControllerImplBase(
Context context, MediaController instance, SessionToken token, Bundle connectionHints) {
@ -228,6 +230,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
this.instance.runOnApplicationLooper(MediaControllerImplBase.this.instance::release);
}
flushCommandQueueHandler = new FlushCommandQueueHandler(instance.getApplicationLooper());
lastReturnedContentPositionMs = C.TIME_UNSET;
lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET;
}
@Override
@ -662,9 +666,22 @@ import org.checkerframework.checker.nullness.qual.NonNull;
@Override
public long getContentPosition() {
boolean receivedUpdatedPositionInfo =
lastSetPlayWhenReadyCalledTimeMs != C.TIME_UNSET
&& lastSetPlayWhenReadyCalledTimeMs < playerInfo.sessionPositionInfo.eventTimeMs;
if (!playerInfo.isPlaying || playerInfo.sessionPositionInfo.isPlayingAd) {
return playerInfo.sessionPositionInfo.positionInfo.contentPositionMs;
if (receivedUpdatedPositionInfo || lastReturnedContentPositionMs == C.TIME_UNSET) {
lastReturnedContentPositionMs =
playerInfo.sessionPositionInfo.positionInfo.contentPositionMs;
}
return lastReturnedContentPositionMs;
}
if (!receivedUpdatedPositionInfo && lastReturnedContentPositionMs != C.TIME_UNSET) {
// We need an updated content position to make a new position estimation.
return lastReturnedContentPositionMs;
}
long elapsedTimeMs =
(instance.getTimeDiffMs() != C.TIME_UNSET)
? instance.getTimeDiffMs()
@ -672,9 +689,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
long estimatedPositionMs =
playerInfo.sessionPositionInfo.positionInfo.contentPositionMs
+ (long) (elapsedTimeMs * playerInfo.playbackParameters.speed);
return playerInfo.sessionPositionInfo.contentDurationMs == C.TIME_UNSET
? estimatedPositionMs
: Math.min(estimatedPositionMs, playerInfo.sessionPositionInfo.contentDurationMs);
if (playerInfo.sessionPositionInfo.contentDurationMs != C.TIME_UNSET) {
estimatedPositionMs =
Math.min(estimatedPositionMs, playerInfo.sessionPositionInfo.contentDurationMs);
}
lastReturnedContentPositionMs = estimatedPositionMs;
return lastReturnedContentPositionMs;
}
@Override
@ -2051,6 +2071,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
&& playerInfo.playbackSuppressionReason == playbackSuppressionReason) {
return;
}
// Stop estimating content position until a new positionInfo arrives from the player
lastSetPlayWhenReadyCalledTimeMs = SystemClock.elapsedRealtime();
PlayerInfo playerInfo =
this.playerInfo.copyWithPlayWhenReady(
playWhenReady, playWhenReadyChangeReason, playbackSuppressionReason);