Commit 2186b6d3 by tonihei Committed by christosts

Avoid sending periodic position updates while paused and not loading

The period updates were introduced to ensure the buffered position is
updated regularly and that any playback position drift is corrected.

None of these updates need to happen while the player is paused or
not loading and we can avoid the constant binder interactions.

PiperOrigin-RevId: 496329800
(cherry picked from commit 0749b059)
parent da6c2dfa
...@@ -121,6 +121,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; ...@@ -121,6 +121,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
@Nullable private final BroadcastReceiver broadcastReceiver; @Nullable private final BroadcastReceiver broadcastReceiver;
private final Handler applicationHandler; private final Handler applicationHandler;
private final BitmapLoader bitmapLoader; private final BitmapLoader bitmapLoader;
private final Runnable periodicSessionPositionInfoUpdateRunnable;
@Nullable private PlayerListener playerListener; @Nullable private PlayerListener playerListener;
@Nullable private MediaSession.Listener mediaSessionListener; @Nullable private MediaSession.Listener mediaSessionListener;
...@@ -246,8 +247,9 @@ import org.checkerframework.checker.initialization.qual.Initialized; ...@@ -246,8 +247,9 @@ import org.checkerframework.checker.initialization.qual.Initialized;
/* oldPlayerWrapper= */ null, /* newPlayerWrapper= */ playerWrapper)); /* oldPlayerWrapper= */ null, /* newPlayerWrapper= */ playerWrapper));
sessionPositionUpdateDelayMs = DEFAULT_SESSION_POSITION_UPDATE_DELAY_MS; sessionPositionUpdateDelayMs = DEFAULT_SESSION_POSITION_UPDATE_DELAY_MS;
applicationHandler.postDelayed( periodicSessionPositionInfoUpdateRunnable =
thisRef::notifyPeriodicSessionPositionInfoChangesOnHandler, sessionPositionUpdateDelayMs); thisRef::notifyPeriodicSessionPositionInfoChangesOnHandler;
postOrRun(applicationHandler, thisRef::schedulePeriodicSessionPositionInfoChanges);
} }
public void setPlayer(Player player) { public void setPlayer(Player player) {
...@@ -567,10 +569,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; ...@@ -567,10 +569,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
protected void setSessionPositionUpdateDelayMsOnHandler(long updateDelayMs) { protected void setSessionPositionUpdateDelayMsOnHandler(long updateDelayMs) {
verifyApplicationThread(); verifyApplicationThread();
sessionPositionUpdateDelayMs = updateDelayMs; sessionPositionUpdateDelayMs = updateDelayMs;
schedulePeriodicSessionPositionInfoChanges();
applicationHandler.removeCallbacks(this::notifyPeriodicSessionPositionInfoChangesOnHandler);
applicationHandler.postDelayed(
this::notifyPeriodicSessionPositionInfoChangesOnHandler, updateDelayMs);
} }
@Nullable @Nullable
...@@ -718,9 +717,15 @@ import org.checkerframework.checker.initialization.qual.Initialized; ...@@ -718,9 +717,15 @@ import org.checkerframework.checker.initialization.qual.Initialized;
SessionPositionInfo sessionPositionInfo = playerWrapper.createSessionPositionInfoForBundling(); SessionPositionInfo sessionPositionInfo = playerWrapper.createSessionPositionInfoForBundling();
dispatchRemoteControllerTaskWithoutReturn( dispatchRemoteControllerTaskWithoutReturn(
(callback, seq) -> callback.onPeriodicSessionPositionInfoChanged(seq, sessionPositionInfo)); (callback, seq) -> callback.onPeriodicSessionPositionInfoChanged(seq, sessionPositionInfo));
if (sessionPositionUpdateDelayMs > 0) { schedulePeriodicSessionPositionInfoChanges();
}
private void schedulePeriodicSessionPositionInfoChanges() {
applicationHandler.removeCallbacks(periodicSessionPositionInfoUpdateRunnable);
if (sessionPositionUpdateDelayMs > 0
&& (playerWrapper.isPlaying() || playerWrapper.isLoading())) {
applicationHandler.postDelayed( applicationHandler.postDelayed(
this::notifyPeriodicSessionPositionInfoChangesOnHandler, sessionPositionUpdateDelayMs); periodicSessionPositionInfoUpdateRunnable, sessionPositionUpdateDelayMs);
} }
} }
...@@ -859,6 +864,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; ...@@ -859,6 +864,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
/* excludeTimeline= */ true, /* excludeTracks= */ true); /* excludeTimeline= */ true, /* excludeTracks= */ true);
session.dispatchRemoteControllerTaskToLegacyStub( session.dispatchRemoteControllerTaskToLegacyStub(
(callback, seq) -> callback.onIsPlayingChanged(seq, isPlaying)); (callback, seq) -> callback.onIsPlayingChanged(seq, isPlaying));
session.schedulePeriodicSessionPositionInfoChanges();
} }
@Override @Override
...@@ -877,6 +883,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; ...@@ -877,6 +883,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
/* excludeTimeline= */ true, /* excludeTracks= */ true); /* excludeTimeline= */ true, /* excludeTracks= */ true);
session.dispatchRemoteControllerTaskToLegacyStub( session.dispatchRemoteControllerTaskToLegacyStub(
(callback, seq) -> callback.onIsLoadingChanged(seq, isLoading)); (callback, seq) -> callback.onIsLoadingChanged(seq, isLoading));
session.schedulePeriodicSessionPositionInfoChanges();
} }
@Override @Override
......
...@@ -24,6 +24,7 @@ import static androidx.media3.test.session.common.MediaSessionConstants.KEY_AVAI ...@@ -24,6 +24,7 @@ import static androidx.media3.test.session.common.MediaSessionConstants.KEY_AVAI
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_SESSION_ACTIVITY; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_SESSION_ACTIVITY;
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_IS_SESSION_COMMAND_AVAILABLE; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_IS_SESSION_COMMAND_AVAILABLE;
import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS; import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS;
import static androidx.media3.test.session.common.TestUtils.NO_RESPONSE_TIMEOUT_MS;
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS; import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
...@@ -984,11 +985,18 @@ public class MediaControllerTest { ...@@ -984,11 +985,18 @@ public class MediaControllerTest {
@Test @Test
public void getBufferedPosition_withPeriodicUpdate_updatedWithoutCallback() throws Exception { public void getBufferedPosition_withPeriodicUpdate_updatedWithoutCallback() throws Exception {
long testBufferedPosition = 999L; long testBufferedPosition = 999L;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder()
.setPlayWhenReady(true)
.setPlaybackSuppressionReason(Player.PLAYBACK_SUPPRESSION_REASON_NONE)
.setPlaybackState(Player.STATE_READY)
.setIsLoading(true)
.build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken()); MediaController controller = controllerTestRule.createController(remoteSession.getToken());
remoteSession.getMockPlayer().setBufferedPosition(testBufferedPosition); remoteSession.setSessionPositionUpdateDelayMs(10L);
remoteSession.setSessionPositionUpdateDelayMs(0L);
remoteSession.getMockPlayer().setBufferedPosition(testBufferedPosition);
PollingCheck.waitFor( PollingCheck.waitFor(
TIMEOUT_MS, TIMEOUT_MS,
() -> { () -> {
...@@ -999,6 +1007,31 @@ public class MediaControllerTest { ...@@ -999,6 +1007,31 @@ public class MediaControllerTest {
} }
@Test @Test
public void getBufferedPosition_whilePausedAndNotLoading_isNotUpdatedPeriodically()
throws Exception {
long testBufferedPosition = 999L;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder()
.setPlayWhenReady(false)
.setPlaybackSuppressionReason(Player.PLAYBACK_SUPPRESSION_REASON_NONE)
.setPlaybackState(Player.STATE_READY)
.setIsLoading(false)
.build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
remoteSession.setSessionPositionUpdateDelayMs(10L);
remoteSession.getMockPlayer().setBufferedPosition(testBufferedPosition);
Thread.sleep(NO_RESPONSE_TIMEOUT_MS);
AtomicLong bufferedPositionAfterDelay = new AtomicLong();
threadTestRule
.getHandler()
.postAndSync(() -> bufferedPositionAfterDelay.set(controller.getBufferedPosition()));
assertThat(bufferedPositionAfterDelay.get()).isNotEqualTo(testBufferedPosition);
}
@Test
public void getContentBufferedPosition_byDefault_returnsZero() throws Exception { public void getContentBufferedPosition_byDefault_returnsZero() throws Exception {
MediaController controller = controllerTestRule.createController(remoteSession.getToken()); MediaController controller = controllerTestRule.createController(remoteSession.getToken());
long contentBufferedPositionMs = long contentBufferedPositionMs =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment