Commit 7b4b5cbf by gyumin Committed by Ian Baker

Preserve window indices of Timeline when bundling

PiperOrigin-RevId: 364324490
parent 10a8c603
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkState;
import android.net.Uri;
......@@ -1255,11 +1256,16 @@ public abstract class Timeline implements Bundleable {
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({FIELD_WINDOWS, FIELD_PERIODS})
@IntDef({
FIELD_WINDOWS,
FIELD_PERIODS,
FIELD_SHUFFLED_WINDOW_INDICES,
})
private @interface FieldNumber {}
private static final int FIELD_WINDOWS = 0;
private static final int FIELD_PERIODS = 1;
private static final int FIELD_SHUFFLED_WINDOW_INDICES = 2;
/**
* {@inheritDoc}
......@@ -1272,18 +1278,24 @@ public abstract class Timeline implements Bundleable {
public final Bundle toBundle() {
List<Bundle> windowBundles = new ArrayList<>();
int windowCount = getWindowCount();
Window window = new Window();
for (int i = 0; i < windowCount; i++) {
Window window = new Window();
getWindow(i, window, /* defaultPositionProjectionUs= */ 0);
windowBundles.add(window.toBundle());
windowBundles.add(getWindow(i, window, /* defaultPositionProjectionUs= */ 0).toBundle());
}
List<Bundle> periodBundles = new ArrayList<>();
int periodCount = getPeriodCount();
Period period = new Period();
for (int i = 0; i < periodCount; i++) {
Period period = new Period();
getPeriod(i, period, /* setIds= */ false);
periodBundles.add(period.toBundle());
periodBundles.add(getPeriod(i, period, /* setIds= */ false).toBundle());
}
int[] shuffledWindowIndices = new int[windowCount];
shuffledWindowIndices[0] = getFirstWindowIndex(/* shuffleModeEnabled= */ true);
for (int i = 1; i < windowCount; i++) {
shuffledWindowIndices[i] =
getNextWindowIndex(
shuffledWindowIndices[i - 1], Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true);
}
Bundle bundle = new Bundle();
......@@ -1291,6 +1303,7 @@ public abstract class Timeline implements Bundleable {
bundle, keyForField(FIELD_WINDOWS), new BundleListRetriever(windowBundles));
BundleCompat.putBinder(
bundle, keyForField(FIELD_PERIODS), new BundleListRetriever(periodBundles));
bundle.putIntArray(keyForField(FIELD_SHUFFLED_WINDOW_INDICES), shuffledWindowIndices);
return bundle;
}
......@@ -1310,7 +1323,14 @@ public abstract class Timeline implements Bundleable {
ImmutableList<Period> periods =
fromBundleListRetriever(
Period.CREATOR, BundleCompat.getBinder(bundle, keyForField(FIELD_PERIODS)));
return new RemotableTimeline(windows, periods);
@Nullable
int[] shuffledWindowIndices = bundle.getIntArray(keyForField(FIELD_SHUFFLED_WINDOW_INDICES));
return new RemotableTimeline(
windows,
periods,
shuffledWindowIndices == null
? generateUnshuffledIndices(windows.size())
: shuffledWindowIndices);
}
private static <T extends Bundleable> ImmutableList<T> fromBundleListRetriever(
......@@ -1330,6 +1350,14 @@ public abstract class Timeline implements Bundleable {
return Integer.toString(field, Character.MAX_RADIX);
}
private static int[] generateUnshuffledIndices(int n) {
int[] indices = new int[n];
for (int i = 0; i < n; i++) {
indices[i] = i;
}
return indices;
}
/**
* A concrete class of {@link Timeline} to restore a {@link Timeline} instance from a {@link
* Bundle} sent by another process via {@link IBinder}.
......@@ -1338,10 +1366,19 @@ public abstract class Timeline implements Bundleable {
private final ImmutableList<Window> windows;
private final ImmutableList<Period> periods;
private final int[] shuffledWindowIndices;
private final int[] windowIndicesInShuffled;
public RemotableTimeline(ImmutableList<Window> windows, ImmutableList<Period> periods) {
public RemotableTimeline(
ImmutableList<Window> windows, ImmutableList<Period> periods, int[] shuffledWindowIndices) {
checkArgument(windows.size() == shuffledWindowIndices.length);
this.windows = windows;
this.periods = periods;
this.shuffledWindowIndices = shuffledWindowIndices;
windowIndicesInShuffled = new int[shuffledWindowIndices.length];
for (int i = 0; i < shuffledWindowIndices.length; i++) {
windowIndicesInShuffled[shuffledWindowIndices[i]] = i;
}
}
@Override
......@@ -1373,6 +1410,56 @@ public abstract class Timeline implements Bundleable {
}
@Override
public int getNextWindowIndex(
int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) {
if (repeatMode == Player.REPEAT_MODE_ONE) {
return windowIndex;
}
if (windowIndex == getLastWindowIndex(shuffleModeEnabled)) {
return repeatMode == Player.REPEAT_MODE_ALL
? getFirstWindowIndex(shuffleModeEnabled)
: C.INDEX_UNSET;
}
return shuffleModeEnabled
? shuffledWindowIndices[windowIndicesInShuffled[windowIndex] + 1]
: windowIndex + 1;
}
@Override
public int getPreviousWindowIndex(
int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) {
if (repeatMode == Player.REPEAT_MODE_ONE) {
return windowIndex;
}
if (windowIndex == getFirstWindowIndex(shuffleModeEnabled)) {
return repeatMode == Player.REPEAT_MODE_ALL
? getLastWindowIndex(shuffleModeEnabled)
: C.INDEX_UNSET;
}
return shuffleModeEnabled
? shuffledWindowIndices[windowIndicesInShuffled[windowIndex] - 1]
: windowIndex - 1;
}
@Override
public int getLastWindowIndex(boolean shuffleModeEnabled) {
if (isEmpty()) {
return C.INDEX_UNSET;
}
return shuffleModeEnabled
? shuffledWindowIndices[getWindowCount() - 1]
: getWindowCount() - 1;
}
@Override
public int getFirstWindowIndex(boolean shuffleModeEnabled) {
if (isEmpty()) {
return C.INDEX_UNSET;
}
return shuffleModeEnabled ? shuffledWindowIndices[0] : 0;
}
@Override
public int getPeriodCount() {
return periods.size();
}
......
......@@ -238,6 +238,47 @@ public class TimelineTest {
}
@Test
public void roundtripViaBundle_ofTimeline_preservesWindowIndices() {
int windowCount = 10;
FakeTimeline timeline = new FakeTimeline(windowCount);
Timeline restoredTimeline = Timeline.CREATOR.fromBundle(timeline.toBundle());
assertThat(restoredTimeline.getLastWindowIndex(/* shuffleModeEnabled= */ false))
.isEqualTo(timeline.getLastWindowIndex(/* shuffleModeEnabled= */ false));
assertThat(restoredTimeline.getLastWindowIndex(/* shuffleModeEnabled= */ true))
.isEqualTo(timeline.getLastWindowIndex(/* shuffleModeEnabled= */ true));
assertThat(restoredTimeline.getFirstWindowIndex(/* shuffleModeEnabled= */ false))
.isEqualTo(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ false));
assertThat(restoredTimeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true))
.isEqualTo(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true));
TimelineAsserts.assertEqualNextWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ false);
TimelineAsserts.assertEqualNextWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true);
TimelineAsserts.assertEqualNextWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ false);
TimelineAsserts.assertEqualNextWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ true);
TimelineAsserts.assertEqualNextWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ false);
TimelineAsserts.assertEqualNextWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ true);
TimelineAsserts.assertEqualPreviousWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ false);
TimelineAsserts.assertEqualPreviousWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true);
TimelineAsserts.assertEqualPreviousWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ false);
TimelineAsserts.assertEqualPreviousWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ true);
TimelineAsserts.assertEqualPreviousWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ false);
TimelineAsserts.assertEqualPreviousWindowIndices(
timeline, restoredTimeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ true);
}
@Test
public void roundtripViaBundle_ofWindow_yieldsEqualInstanceExceptUidAndManifest() {
Timeline.Window window = new Timeline.Window();
window.uid = new Object();
......
......@@ -1707,40 +1707,6 @@ public final class ExoPlayerTest {
}
@Test
public void
testInvalidSeekPositionAfterSourceInfoRefreshWithShuffleModeEnabledUsesCorrectFirstPeriod()
throws Exception {
FakeMediaSource mediaSource = new FakeMediaSource(new FakeTimeline(/* windowCount= */ 2));
AtomicInteger windowIndexAfterUpdate = new AtomicInteger();
ActionSchedule actionSchedule =
new ActionSchedule.Builder(TAG)
.setShuffleOrder(new FakeShuffleOrder(/* length= */ 0))
.setShuffleModeEnabled(true)
.waitForPlaybackState(Player.STATE_BUFFERING)
// Seeking to an invalid position will end playback.
.seek(
/* windowIndex= */ 100, /* positionMs= */ 0, /* catchIllegalSeekException= */ true)
.waitForPlaybackState(Player.STATE_ENDED)
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
windowIndexAfterUpdate.set(player.getCurrentWindowIndex());
}
})
.build();
new ExoPlayerTestRunner.Builder(context)
.setMediaSources(mediaSource)
.setActionSchedule(actionSchedule)
.build()
.start()
.blockUntilActionScheduleFinished(TIMEOUT_MS)
.blockUntilEnded(TIMEOUT_MS);
assertThat(windowIndexAfterUpdate.get()).isEqualTo(1);
}
@Test
public void restartAfterEmptyTimelineWithShuffleModeEnabledUsesCorrectFirstPeriod()
throws Exception {
ConcatenatingMediaSource concatenatingMediaSource =
......
......@@ -49,18 +49,28 @@ public class LoopingMediaSourceTest {
Timeline timeline = getLoopingTimeline(multiWindowTimeline, 1);
TimelineAsserts.assertWindowTags(timeline, 111, 222, 333);
TimelineAsserts.assertPeriodCounts(timeline, 1, 1, 1);
for (boolean shuffled : new boolean[] {false, true}) {
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, C.INDEX_UNSET, 0, 1);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 2, 0, 1);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, C.INDEX_UNSET);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 0);
}
boolean shuffled = false;
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, C.INDEX_UNSET, 0, 1);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 2, 0, 1);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, C.INDEX_UNSET);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 0);
shuffled = true; // FakeTimeline has FakeShuffleOrder which returns a reverse order.
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, C.INDEX_UNSET);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 0);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, C.INDEX_UNSET, 0, 1);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, shuffled, 2, 0, 1);
}
@Test
......@@ -68,20 +78,32 @@ public class LoopingMediaSourceTest {
Timeline timeline = getLoopingTimeline(multiWindowTimeline, 3);
TimelineAsserts.assertWindowTags(timeline, 111, 222, 333, 111, 222, 333, 111, 222, 333);
TimelineAsserts.assertPeriodCounts(timeline, 1, 1, 1, 1, 1, 1, 1, 1, 1);
for (boolean shuffled : new boolean[] {false, true}) {
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, C.INDEX_UNSET, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 8, 0, 1, 2, 3, 4, 5, 6, 7);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, 3, 4, 5, 6, 7, 8, C.INDEX_UNSET);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 3, 4, 5, 6, 7, 8, 0);
}
boolean shuffled = false;
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, C.INDEX_UNSET, 0, 1, 2, 3, 4, 5, 6, 7);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 8, 0, 1, 2, 3, 4, 5, 6, 7);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, 3, 4, 5, 6, 7, 8, C.INDEX_UNSET);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 3, 4, 5, 6, 7, 8, 0);
shuffled = true; // FakeTimeline has FakeShuffleOrder which returns a reverse order.
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, C.INDEX_UNSET, 4, 5, 0, 7, 8, 3);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 6, 4, 5, 0, 7, 8, 3);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 5, 0, 1, 8, 3, 4, C.INDEX_UNSET, 6, 7);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2, 3, 4, 5, 6, 7, 8);
TimelineAsserts.assertNextWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 5, 0, 1, 8, 3, 4, 2, 6, 7);
}
@Test
......@@ -89,17 +111,26 @@ public class LoopingMediaSourceTest {
Timeline timeline = getLoopingTimeline(multiWindowTimeline, Integer.MAX_VALUE);
TimelineAsserts.assertWindowTags(timeline, 111, 222, 333);
TimelineAsserts.assertPeriodCounts(timeline, 1, 1, 1);
for (boolean shuffled : new boolean[] {false, true}) {
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 2, 0, 1);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 2, 0, 1);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, 0);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 0);
}
boolean shuffled = false;
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 2, 0, 1);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 2, 0, 1);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, 0);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 0);
shuffled = true; // FakeTimeline has FakeShuffleOrder which returns a reverse order.
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_OFF, shuffled, 1, 2, 0);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertPreviousWindowIndices(
timeline, Player.REPEAT_MODE_ALL, shuffled, 1, 2, 0);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_OFF, shuffled, 2, 0, 1);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, shuffled, 0, 1, 2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, shuffled, 2, 0, 1);
}
@Test
......
......@@ -21,6 +21,7 @@ import android.net.Uri;
import android.util.Pair;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.util.Assertions;
......@@ -235,6 +236,7 @@ public final class FakeTimeline extends Timeline {
private final TimelineWindowDefinition[] windowDefinitions;
private final Object[] manifests;
private final int[] periodOffsets;
private final FakeShuffleOrder fakeShuffleOrder;
/**
* Returns an ad playback state with the specified number of ads in each of the specified ad
......@@ -308,6 +310,7 @@ public final class FakeTimeline extends Timeline {
for (int i = 0; i < windowDefinitions.length; i++) {
periodOffsets[i + 1] = periodOffsets[i] + windowDefinitions[i].periodCount;
}
fakeShuffleOrder = new FakeShuffleOrder(windowDefinitions.length);
}
@Override
......@@ -316,6 +319,48 @@ public final class FakeTimeline extends Timeline {
}
@Override
public int getNextWindowIndex(
int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) {
if (repeatMode == Player.REPEAT_MODE_ONE) {
return windowIndex;
}
if (windowIndex == getLastWindowIndex(shuffleModeEnabled)) {
return repeatMode == Player.REPEAT_MODE_ALL
? getFirstWindowIndex(shuffleModeEnabled)
: C.INDEX_UNSET;
}
return shuffleModeEnabled ? fakeShuffleOrder.getNextIndex(windowIndex) : windowIndex + 1;
}
@Override
public int getPreviousWindowIndex(
int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) {
if (repeatMode == Player.REPEAT_MODE_ONE) {
return windowIndex;
}
if (windowIndex == getFirstWindowIndex(shuffleModeEnabled)) {
return repeatMode == Player.REPEAT_MODE_ALL
? getLastWindowIndex(shuffleModeEnabled)
: C.INDEX_UNSET;
}
return shuffleModeEnabled ? fakeShuffleOrder.getPreviousIndex(windowIndex) : windowIndex - 1;
}
@Override
public int getLastWindowIndex(boolean shuffleModeEnabled) {
return shuffleModeEnabled
? fakeShuffleOrder.getLastIndex()
: super.getLastWindowIndex(/* shuffleModeEnabled= */ false);
}
@Override
public int getFirstWindowIndex(boolean shuffleModeEnabled) {
return shuffleModeEnabled
? fakeShuffleOrder.getFirstIndex()
: super.getFirstWindowIndex(/* shuffleModeEnabled= */ false);
}
@Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
window.set(
......
......@@ -105,6 +105,38 @@ public final class TimelineAsserts {
}
/**
* Asserts that previous window indices for each window of the actual timeline are equal to the
* indices of the expected timeline depending on the repeat mode and the shuffle mode.
*/
public static void assertEqualPreviousWindowIndices(
Timeline expectedTimeline,
Timeline actualTimeline,
@Player.RepeatMode int repeatMode,
boolean shuffleModeEnabled) {
for (int windowIndex = 0; windowIndex < actualTimeline.getWindowCount(); windowIndex++) {
assertThat(actualTimeline.getPreviousWindowIndex(windowIndex, repeatMode, shuffleModeEnabled))
.isEqualTo(
expectedTimeline.getPreviousWindowIndex(windowIndex, repeatMode, shuffleModeEnabled));
}
}
/**
* Asserts that next window indices for each window of the actual timeline are equal to the
* indices of the expected timeline depending on the repeat mode and the shuffle mode.
*/
public static void assertEqualNextWindowIndices(
Timeline expectedTimeline,
Timeline actualTimeline,
@Player.RepeatMode int repeatMode,
boolean shuffleModeEnabled) {
for (int windowIndex = 0; windowIndex < actualTimeline.getWindowCount(); windowIndex++) {
assertThat(actualTimeline.getNextWindowIndex(windowIndex, repeatMode, shuffleModeEnabled))
.isEqualTo(
expectedTimeline.getNextWindowIndex(windowIndex, repeatMode, shuffleModeEnabled));
}
}
/**
* Asserts that the durations of the periods in the {@link Timeline} and the durations in the
* given sequence are equal.
*/
......
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