diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java index 830ab52e19..1d247af8f3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java @@ -570,9 +570,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource= fromIndex; index--) { - shuffleOrder = shuffleOrder.cloneAndRemove(index); - } + shuffleOrder = shuffleOrder.cloneAndRemove(fromIndex, toIndex); } for (int index = toIndex - 1; index >= fromIndex; index--) { removeMediaSourceInternal(index); @@ -581,7 +579,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource moveMessage = (MessageData) Util.castNonNull(message); - shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index); + shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index, moveMessage.index + 1); shuffleOrder = shuffleOrder.cloneAndInsert(moveMessage.customData, 1); moveMediaSourceInternal(moveMessage.index, moveMessage.customData); scheduleListenerNotification(moveMessage.actionOnCompletion); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java index 90e2576d76..5af9dbd20a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ShuffleOrder.java @@ -135,15 +135,16 @@ public interface ShuffleOrder { } @Override - public ShuffleOrder cloneAndRemove(int removalIndex) { - int[] newShuffled = new int[shuffled.length - 1]; - boolean foundRemovedElement = false; + public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) { + int numberOfElementsToRemove = indexToExclusive - indexFrom; + int[] newShuffled = new int[shuffled.length - numberOfElementsToRemove]; + int foundElementsCount = 0; for (int i = 0; i < shuffled.length; i++) { - if (shuffled[i] == removalIndex) { - foundRemovedElement = true; + if (shuffled[i] >= indexFrom && shuffled[i] < indexToExclusive) { + foundElementsCount++; } else { - newShuffled[foundRemovedElement ? i - 1 : i] = shuffled[i] > removalIndex - ? shuffled[i] - 1 : shuffled[i]; + newShuffled[i - foundElementsCount] = + shuffled[i] >= indexFrom ? shuffled[i] - numberOfElementsToRemove : shuffled[i]; } } return new DefaultShuffleOrder(newShuffled, new Random(random.nextLong())); @@ -213,8 +214,8 @@ public interface ShuffleOrder { } @Override - public ShuffleOrder cloneAndRemove(int removalIndex) { - return new UnshuffledShuffleOrder(length - 1); + public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) { + return new UnshuffledShuffleOrder(length - indexToExclusive + indexFrom); } @Override @@ -268,12 +269,14 @@ public interface ShuffleOrder { ShuffleOrder cloneAndInsert(int insertionIndex, int insertionCount); /** - * Returns a copy of the shuffle order with one element removed. + * Returns a copy of the shuffle order with a range of elements removed. * - * @param removalIndex The index of the element in the unshuffled order which is to be removed. - * @return A copy of this {@link ShuffleOrder} without the removed element. + * @param indexFrom The starting index in the unshuffled order of the range to remove. + * @param indexToExclusive The smallest index (must be greater or equal to {@code indexFrom}) that + * will not be removed. + * @return A copy of this {@link ShuffleOrder} without the elements in the removed range. */ - ShuffleOrder cloneAndRemove(int removalIndex); + ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive); /** Returns a copy of the shuffle order with all elements removed. */ ShuffleOrder cloneAndClear(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java index 06f39409e7..430ceb87f1 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ShuffleOrderTest.java @@ -45,10 +45,32 @@ public final class ShuffleOrderTest { testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 5); } } - testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0); - testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2); - testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4); - testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0); + testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0, 1); + testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2, 3); + testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4, 5); + testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0, 1); + testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 1000); + testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 999); + testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 500); + testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 100, 600); + testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 500, 1000); + } + + @Test + public void testDefaultShuffleOrderSideloaded() { + int[] shuffledIndices = new int[] {2, 1, 0, 4, 3}; + ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED); + assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2); + assertThat(shuffleOrder.getLastIndex()).isEqualTo(3); + for (int i = 0; i < 4; i++) { + assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]); + } + assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET); + for (int i = 4; i > 0; i--) { + assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i])) + .isEqualTo(shuffledIndices[i - 1]); + } + assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET); } @Test @@ -63,10 +85,15 @@ public final class ShuffleOrderTest { testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 5); } } - testCloneAndRemove(new UnshuffledShuffleOrder(5), 0); - testCloneAndRemove(new UnshuffledShuffleOrder(5), 2); - testCloneAndRemove(new UnshuffledShuffleOrder(5), 4); - testCloneAndRemove(new UnshuffledShuffleOrder(1), 0); + testCloneAndRemove(new UnshuffledShuffleOrder(5), 0, 1); + testCloneAndRemove(new UnshuffledShuffleOrder(5), 2, 3); + testCloneAndRemove(new UnshuffledShuffleOrder(5), 4, 5); + testCloneAndRemove(new UnshuffledShuffleOrder(1), 0, 1); + testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 1000); + testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 999); + testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 500); + testCloneAndRemove(new UnshuffledShuffleOrder(1000), 100, 600); + testCloneAndRemove(new UnshuffledShuffleOrder(1000), 500, 1000); } @Test @@ -79,23 +106,6 @@ public final class ShuffleOrderTest { } } - @Test - public void testSideloadedShuffleOrder() { - int[] shuffledIndices = new int[] {2, 1, 0, 4, 3}; - ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED); - assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2); - assertThat(shuffleOrder.getLastIndex()).isEqualTo(3); - for (int i = 0; i < 4; i++) { - assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]); - } - assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET); - for (int i = 4; i > 0; i--) { - assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i])) - .isEqualTo(shuffledIndices[i - 1]); - } - assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET); - } - private static void assertShuffleOrderCorrectness(ShuffleOrder shuffleOrder, int length) { assertThat(shuffleOrder.getLength()).isEqualTo(length); if (length == 0) { @@ -137,22 +147,24 @@ public final class ShuffleOrderTest { } } - private static void testCloneAndRemove(ShuffleOrder shuffleOrder, int position) { - ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(position); - assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - 1); + private static void testCloneAndRemove( + ShuffleOrder shuffleOrder, int indexFrom, int indexToExclusive) { + int numberOfElementsToRemove = indexToExclusive - indexFrom; + ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(indexFrom, indexToExclusive); + assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - numberOfElementsToRemove); // Assert all elements still have the relative same order for (int i = 0; i < shuffleOrder.getLength(); i++) { - if (i == position) { + if (i >= indexFrom && i < indexToExclusive) { continue; } int expectedNextIndex = shuffleOrder.getNextIndex(i); - if (expectedNextIndex == position) { + while (expectedNextIndex >= indexFrom && expectedNextIndex < indexToExclusive) { expectedNextIndex = shuffleOrder.getNextIndex(expectedNextIndex); } - if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= position) { - expectedNextIndex--; + if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= indexFrom) { + expectedNextIndex -= numberOfElementsToRemove; } - int newNextIndex = newOrder.getNextIndex(i < position ? i : i - 1); + int newNextIndex = newOrder.getNextIndex(i < indexFrom ? i : i - numberOfElementsToRemove); assertThat(newNextIndex).isEqualTo(expectedNextIndex); } } diff --git a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeShuffleOrder.java b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeShuffleOrder.java index cb70c75bdb..4b3a0d5051 100644 --- a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeShuffleOrder.java +++ b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeShuffleOrder.java @@ -61,8 +61,8 @@ public final class FakeShuffleOrder implements ShuffleOrder { } @Override - public ShuffleOrder cloneAndRemove(int removalIndex) { - return new FakeShuffleOrder(length - 1); + public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) { + return new FakeShuffleOrder(length - indexToExclusive + indexFrom); } @Override