Callback when sleeping for offload and existing from it
#exo-offload PiperOrigin-RevId: 333497538
This commit is contained in:
parent
294ae10ef1
commit
f37d79a4dd
@ -1353,6 +1353,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
private final boolean isPlayingChanged;
|
private final boolean isPlayingChanged;
|
||||||
private final boolean playbackParametersChanged;
|
private final boolean playbackParametersChanged;
|
||||||
private final boolean offloadSchedulingEnabledChanged;
|
private final boolean offloadSchedulingEnabledChanged;
|
||||||
|
private final boolean sleepingForOffloadChanged;
|
||||||
|
|
||||||
public PlaybackInfoUpdate(
|
public PlaybackInfoUpdate(
|
||||||
PlaybackInfo playbackInfo,
|
PlaybackInfo playbackInfo,
|
||||||
@ -1394,6 +1395,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
!previousPlaybackInfo.playbackParameters.equals(playbackInfo.playbackParameters);
|
!previousPlaybackInfo.playbackParameters.equals(playbackInfo.playbackParameters);
|
||||||
offloadSchedulingEnabledChanged =
|
offloadSchedulingEnabledChanged =
|
||||||
previousPlaybackInfo.offloadSchedulingEnabled != playbackInfo.offloadSchedulingEnabled;
|
previousPlaybackInfo.offloadSchedulingEnabled != playbackInfo.offloadSchedulingEnabled;
|
||||||
|
sleepingForOffloadChanged =
|
||||||
|
previousPlaybackInfo.sleepingForOffload != playbackInfo.sleepingForOffload;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@ -1476,6 +1479,12 @@ import java.util.concurrent.TimeoutException;
|
|||||||
listener.onExperimentalOffloadSchedulingEnabledChanged(
|
listener.onExperimentalOffloadSchedulingEnabledChanged(
|
||||||
playbackInfo.offloadSchedulingEnabled));
|
playbackInfo.offloadSchedulingEnabled));
|
||||||
}
|
}
|
||||||
|
if (sleepingForOffloadChanged) {
|
||||||
|
invokeAll(
|
||||||
|
listenerSnapshot,
|
||||||
|
listener ->
|
||||||
|
listener.onExperimentalSleepingForOffloadChanged(playbackInfo.sleepingForOffload));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPlaying(PlaybackInfo playbackInfo) {
|
private static boolean isPlaying(PlaybackInfo playbackInfo) {
|
||||||
|
@ -960,14 +960,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
playbackInfo = playbackInfo.copyWithOffloadSchedulingEnabled(offloadSchedulingEnabled);
|
playbackInfo = playbackInfo.copyWithOffloadSchedulingEnabled(offloadSchedulingEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean sleepingForOffload = false;
|
||||||
if ((shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY)
|
if ((shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY)
|
||||||
|| playbackInfo.playbackState == Player.STATE_BUFFERING) {
|
|| playbackInfo.playbackState == Player.STATE_BUFFERING) {
|
||||||
maybeScheduleWakeup(operationStartTimeMs, ACTIVE_INTERVAL_MS);
|
sleepingForOffload = !maybeScheduleWakeup(operationStartTimeMs, ACTIVE_INTERVAL_MS);
|
||||||
} else if (enabledRendererCount != 0 && playbackInfo.playbackState != Player.STATE_ENDED) {
|
} else if (enabledRendererCount != 0 && playbackInfo.playbackState != Player.STATE_ENDED) {
|
||||||
scheduleNextWork(operationStartTimeMs, IDLE_INTERVAL_MS);
|
scheduleNextWork(operationStartTimeMs, IDLE_INTERVAL_MS);
|
||||||
} else {
|
} else {
|
||||||
handler.removeMessages(MSG_DO_SOME_WORK);
|
handler.removeMessages(MSG_DO_SOME_WORK);
|
||||||
}
|
}
|
||||||
|
if (playbackInfo.sleepingForOffload != sleepingForOffload) {
|
||||||
|
playbackInfo = playbackInfo.copyWithSleepingForOffload(sleepingForOffload);
|
||||||
|
}
|
||||||
requestForRendererSleep = false; // A sleep request is only valid for the current doSomeWork.
|
requestForRendererSleep = false; // A sleep request is only valid for the current doSomeWork.
|
||||||
|
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
@ -978,12 +982,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
handler.sendEmptyMessageAtTime(MSG_DO_SOME_WORK, thisOperationStartTimeMs + intervalMs);
|
handler.sendEmptyMessageAtTime(MSG_DO_SOME_WORK, thisOperationStartTimeMs + intervalMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeScheduleWakeup(long operationStartTimeMs, long intervalMs) {
|
private boolean maybeScheduleWakeup(long operationStartTimeMs, long intervalMs) {
|
||||||
if (offloadSchedulingEnabled && requestForRendererSleep) {
|
if (offloadSchedulingEnabled && requestForRendererSleep) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleNextWork(operationStartTimeMs, intervalMs);
|
scheduleNextWork(operationStartTimeMs, intervalMs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackException {
|
private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackException {
|
||||||
@ -1308,7 +1313,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
startPositionUs,
|
startPositionUs,
|
||||||
/* totalBufferedDurationUs= */ 0,
|
/* totalBufferedDurationUs= */ 0,
|
||||||
startPositionUs,
|
startPositionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
/* sleepingForOffload= */ false);
|
||||||
if (releaseMediaSourceList) {
|
if (releaseMediaSourceList) {
|
||||||
mediaSourceList.release();
|
mediaSourceList.release();
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
public final PlaybackParameters playbackParameters;
|
public final PlaybackParameters playbackParameters;
|
||||||
/** Whether offload scheduling is enabled for the main player loop. */
|
/** Whether offload scheduling is enabled for the main player loop. */
|
||||||
public final boolean offloadSchedulingEnabled;
|
public final boolean offloadSchedulingEnabled;
|
||||||
|
/** Whether the main player loop is sleeping, while using offload scheduling. */
|
||||||
|
public final boolean sleepingForOffload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Position up to which media is buffered in {@link #loadingMediaPeriodId) relative to the start
|
* Position up to which media is buffered in {@link #loadingMediaPeriodId) relative to the start
|
||||||
@ -109,7 +111,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
/* bufferedPositionUs= */ 0,
|
/* bufferedPositionUs= */ 0,
|
||||||
/* totalBufferedDurationUs= */ 0,
|
/* totalBufferedDurationUs= */ 0,
|
||||||
/* positionUs= */ 0,
|
/* positionUs= */ 0,
|
||||||
/* offloadSchedulingEnabled= */ false);
|
/* offloadSchedulingEnabled= */ false,
|
||||||
|
/* sleepingForOffload= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,6 +134,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
* @param totalBufferedDurationUs See {@link #totalBufferedDurationUs}.
|
* @param totalBufferedDurationUs See {@link #totalBufferedDurationUs}.
|
||||||
* @param positionUs See {@link #positionUs}.
|
* @param positionUs See {@link #positionUs}.
|
||||||
* @param offloadSchedulingEnabled See {@link #offloadSchedulingEnabled}.
|
* @param offloadSchedulingEnabled See {@link #offloadSchedulingEnabled}.
|
||||||
|
* @param sleepingForOffload See {@link #sleepingForOffload}.
|
||||||
*/
|
*/
|
||||||
public PlaybackInfo(
|
public PlaybackInfo(
|
||||||
Timeline timeline,
|
Timeline timeline,
|
||||||
@ -148,7 +152,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
long bufferedPositionUs,
|
long bufferedPositionUs,
|
||||||
long totalBufferedDurationUs,
|
long totalBufferedDurationUs,
|
||||||
long positionUs,
|
long positionUs,
|
||||||
boolean offloadSchedulingEnabled) {
|
boolean offloadSchedulingEnabled,
|
||||||
|
boolean sleepingForOffload) {
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
this.periodId = periodId;
|
this.periodId = periodId;
|
||||||
this.requestedContentPositionUs = requestedContentPositionUs;
|
this.requestedContentPositionUs = requestedContentPositionUs;
|
||||||
@ -165,6 +170,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
this.totalBufferedDurationUs = totalBufferedDurationUs;
|
this.totalBufferedDurationUs = totalBufferedDurationUs;
|
||||||
this.positionUs = positionUs;
|
this.positionUs = positionUs;
|
||||||
this.offloadSchedulingEnabled = offloadSchedulingEnabled;
|
this.offloadSchedulingEnabled = offloadSchedulingEnabled;
|
||||||
|
this.sleepingForOffload = sleepingForOffload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a placeholder period id for an empty timeline. */
|
/** Returns a placeholder period id for an empty timeline. */
|
||||||
@ -209,7 +215,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,7 +243,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,7 +271,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -290,7 +299,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,7 +327,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -344,7 +355,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -375,7 +387,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -402,7 +415,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -430,6 +444,35 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||||||
bufferedPositionUs,
|
bufferedPositionUs,
|
||||||
totalBufferedDurationUs,
|
totalBufferedDurationUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
offloadSchedulingEnabled);
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies playback info with new sleepingForOffload.
|
||||||
|
*
|
||||||
|
* @param sleepingForOffload New main player loop sleeping state. See {@link #sleepingForOffload}.
|
||||||
|
* @return Copied playback info with new main player loop sleeping state.
|
||||||
|
*/
|
||||||
|
@CheckResult
|
||||||
|
public PlaybackInfo copyWithSleepingForOffload(boolean sleepingForOffload) {
|
||||||
|
return new PlaybackInfo(
|
||||||
|
timeline,
|
||||||
|
periodId,
|
||||||
|
requestedContentPositionUs,
|
||||||
|
playbackState,
|
||||||
|
playbackError,
|
||||||
|
isLoading,
|
||||||
|
trackGroups,
|
||||||
|
trackSelectorResult,
|
||||||
|
loadingMediaPeriodId,
|
||||||
|
playWhenReady,
|
||||||
|
playbackSuppressionReason,
|
||||||
|
playbackParameters,
|
||||||
|
bufferedPositionUs,
|
||||||
|
totalBufferedDurationUs,
|
||||||
|
positionUs,
|
||||||
|
offloadSchedulingEnabled,
|
||||||
|
sleepingForOffload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,6 +604,12 @@ public interface Player {
|
|||||||
* <p>This method is experimental, and will be renamed or removed in a future release.
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
*/
|
*/
|
||||||
default void onExperimentalOffloadSchedulingEnabledChanged(boolean offloadSchedulingEnabled) {}
|
default void onExperimentalOffloadSchedulingEnabledChanged(boolean offloadSchedulingEnabled) {}
|
||||||
|
/**
|
||||||
|
* Called when the player has started or finished sleeping for offload.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*/
|
||||||
|
default void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSample
|
|||||||
import static com.google.android.exoplayer2.testutil.TestExoPlayer.playUntilStartOfWindow;
|
import static com.google.android.exoplayer2.testutil.TestExoPlayer.playUntilStartOfWindow;
|
||||||
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilPlaybackState;
|
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilPlaybackState;
|
||||||
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilReceiveOffloadSchedulingEnabledNewState;
|
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilReceiveOffloadSchedulingEnabledNewState;
|
||||||
|
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilSleepingForOffload;
|
||||||
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilTimelineChanged;
|
import static com.google.android.exoplayer2.testutil.TestExoPlayer.runUntilTimelineChanged;
|
||||||
import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
|
import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@ -111,7 +112,6 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
@ -8249,16 +8249,14 @@ public final class ExoPlayerTest {
|
|||||||
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
|
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
|
||||||
player.setMediaSource(new FakeMediaSource(timeline, ExoPlayerTestRunner.AUDIO_FORMAT));
|
player.setMediaSource(new FakeMediaSource(timeline, ExoPlayerTestRunner.AUDIO_FORMAT));
|
||||||
player.experimentalSetOffloadSchedulingEnabled(true);
|
player.experimentalSetOffloadSchedulingEnabled(true);
|
||||||
runUntilReceiveOffloadSchedulingEnabledNewState(player);
|
|
||||||
player.prepare();
|
player.prepare();
|
||||||
player.play();
|
player.play();
|
||||||
runMainLooperUntil(sleepRenderer::isSleeping);
|
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ true);
|
||||||
|
|
||||||
player.experimentalSetOffloadSchedulingEnabled(false);
|
player.experimentalSetOffloadSchedulingEnabled(false);
|
||||||
|
|
||||||
assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isFalse();
|
assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enableOffloadScheduling_isEnable_playerSleeps() throws Exception {
|
public void enableOffloadScheduling_isEnable_playerSleeps() throws Exception {
|
||||||
FakeSleepRenderer sleepRenderer = new FakeSleepRenderer(C.TRACK_TYPE_AUDIO);
|
FakeSleepRenderer sleepRenderer = new FakeSleepRenderer(C.TRACK_TYPE_AUDIO);
|
||||||
@ -8271,14 +8269,7 @@ public final class ExoPlayerTest {
|
|||||||
|
|
||||||
sleepRenderer.sleepOnNextRender();
|
sleepRenderer.sleepOnNextRender();
|
||||||
|
|
||||||
runMainLooperUntil(sleepRenderer::isSleeping);
|
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ true);
|
||||||
// TODO(b/163303129): There is currently no way to check that the player is sleeping for
|
|
||||||
// offload, for now use a timeout to check that the renderer is never woken up.
|
|
||||||
final int renderTimeoutMs = 500;
|
|
||||||
assertThrows(
|
|
||||||
TimeoutException.class,
|
|
||||||
() ->
|
|
||||||
runMainLooperUntil(() -> !sleepRenderer.isSleeping(), renderTimeoutMs, Clock.DEFAULT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -8292,11 +8283,11 @@ public final class ExoPlayerTest {
|
|||||||
player.experimentalSetOffloadSchedulingEnabled(true);
|
player.experimentalSetOffloadSchedulingEnabled(true);
|
||||||
player.prepare();
|
player.prepare();
|
||||||
player.play();
|
player.play();
|
||||||
runMainLooperUntil(sleepRenderer::isSleeping);
|
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ true);
|
||||||
|
|
||||||
player.experimentalSetOffloadSchedulingEnabled(false); // Force the player to exit offload sleep
|
player.experimentalSetOffloadSchedulingEnabled(false); // Force the player to exit offload sleep
|
||||||
|
|
||||||
runMainLooperUntil(() -> !sleepRenderer.isSleeping());
|
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ false);
|
||||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8309,11 +8300,11 @@ public final class ExoPlayerTest {
|
|||||||
player.experimentalSetOffloadSchedulingEnabled(true);
|
player.experimentalSetOffloadSchedulingEnabled(true);
|
||||||
player.prepare();
|
player.prepare();
|
||||||
player.play();
|
player.play();
|
||||||
runMainLooperUntil(sleepRenderer::isSleeping);
|
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ true);
|
||||||
|
|
||||||
sleepRenderer.wakeup();
|
sleepRenderer.wakeup();
|
||||||
|
|
||||||
runMainLooperUntil(() -> !sleepRenderer.isSleeping());
|
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ false);
|
||||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8350,13 +8341,11 @@ public final class ExoPlayerTest {
|
|||||||
private static class FakeSleepRenderer extends FakeRenderer {
|
private static class FakeSleepRenderer extends FakeRenderer {
|
||||||
private static final long WAKEUP_DEADLINE_MS = 60 * C.MICROS_PER_SECOND;
|
private static final long WAKEUP_DEADLINE_MS = 60 * C.MICROS_PER_SECOND;
|
||||||
private final AtomicBoolean sleepOnNextRender;
|
private final AtomicBoolean sleepOnNextRender;
|
||||||
private final AtomicBoolean isSleeping;
|
|
||||||
private final AtomicReference<Renderer.WakeupListener> wakeupListenerReceiver;
|
private final AtomicReference<Renderer.WakeupListener> wakeupListenerReceiver;
|
||||||
|
|
||||||
public FakeSleepRenderer(int trackType) {
|
public FakeSleepRenderer(int trackType) {
|
||||||
super(trackType);
|
super(trackType);
|
||||||
sleepOnNextRender = new AtomicBoolean(false);
|
sleepOnNextRender = new AtomicBoolean(false);
|
||||||
isSleeping = new AtomicBoolean(false);
|
|
||||||
wakeupListenerReceiver = new AtomicReference<>();
|
wakeupListenerReceiver = new AtomicReference<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8372,14 +8361,6 @@ public final class ExoPlayerTest {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether {@link Renderer.WakeupListener#onSleep(long)} was called on the last {@link
|
|
||||||
* #render(long, long)}
|
|
||||||
*/
|
|
||||||
public boolean isSleeping() {
|
|
||||||
return isSleeping.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException {
|
public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException {
|
||||||
if (what == MSG_SET_WAKEUP_LISTENER) {
|
if (what == MSG_SET_WAKEUP_LISTENER) {
|
||||||
@ -8394,11 +8375,6 @@ public final class ExoPlayerTest {
|
|||||||
super.render(positionUs, elapsedRealtimeUs);
|
super.render(positionUs, elapsedRealtimeUs);
|
||||||
if (sleepOnNextRender.compareAndSet(/* expect= */ true, /* update= */ false)) {
|
if (sleepOnNextRender.compareAndSet(/* expect= */ true, /* update= */ false)) {
|
||||||
wakeupListenerReceiver.get().onSleep(WAKEUP_DEADLINE_MS);
|
wakeupListenerReceiver.get().onSleep(WAKEUP_DEADLINE_MS);
|
||||||
// TODO(b/163303129): Use an actual message from the player instead of guessing that the
|
|
||||||
// player will always sleep for offload after calling `onSleep`.
|
|
||||||
isSleeping.set(true);
|
|
||||||
} else {
|
|
||||||
isSleeping.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,8 @@ public final class MediaPeriodQueueTest {
|
|||||||
/* bufferedPositionUs= */ 0,
|
/* bufferedPositionUs= */ 0,
|
||||||
/* totalBufferedDurationUs= */ 0,
|
/* totalBufferedDurationUs= */ 0,
|
||||||
/* positionUs= */ 0,
|
/* positionUs= */ 0,
|
||||||
/* offloadSchedulingEnabled= */ false);
|
/* offloadSchedulingEnabled= */ false,
|
||||||
|
/* sleepingForOffload= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void advance() {
|
private void advance() {
|
||||||
|
@ -466,6 +466,32 @@ public class TestExoPlayer {
|
|||||||
return Assertions.checkNotNull(offloadSchedulingEnabledReceiver.get());
|
return Assertions.checkNotNull(offloadSchedulingEnabledReceiver.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs tasks of the main {@link Looper} until a {@link
|
||||||
|
* Player.EventListener#onExperimentalSleepingForOffloadChanged(boolean)} callback occurred.
|
||||||
|
*
|
||||||
|
* @param player The {@link Player}.
|
||||||
|
* @param expectedSleepForOffload The expected sleep of offload state.
|
||||||
|
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||||
|
* exceeded.
|
||||||
|
*/
|
||||||
|
public static void runUntilSleepingForOffload(Player player, boolean expectedSleepForOffload)
|
||||||
|
throws TimeoutException {
|
||||||
|
verifyMainTestThread(player);
|
||||||
|
AtomicBoolean receiverCallback = new AtomicBoolean(false);
|
||||||
|
Player.EventListener listener =
|
||||||
|
new Player.EventListener() {
|
||||||
|
@Override
|
||||||
|
public void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {
|
||||||
|
if (sleepingForOffload == expectedSleepForOffload) {
|
||||||
|
receiverCallback.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
player.addListener(listener);
|
||||||
|
runMainLooperUntil(receiverCallback::get);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs tasks of the main {@link Looper} until the {@link VideoListener#onRenderedFirstFrame}
|
* Runs tasks of the main {@link Looper} until the {@link VideoListener#onRenderedFirstFrame}
|
||||||
* callback has been called.
|
* callback has been called.
|
||||||
@ -504,7 +530,7 @@ public class TestExoPlayer {
|
|||||||
verifyMainTestThread(player);
|
verifyMainTestThread(player);
|
||||||
Handler testHandler = Util.createHandlerForCurrentOrMainLooper();
|
Handler testHandler = Util.createHandlerForCurrentOrMainLooper();
|
||||||
|
|
||||||
AtomicBoolean messageHandled = new AtomicBoolean();
|
AtomicBoolean messageHandled = new AtomicBoolean(false);
|
||||||
player
|
player
|
||||||
.createMessage(
|
.createMessage(
|
||||||
(messageType, payload) -> {
|
(messageType, payload) -> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user