Avoid out of bounds when setting less media items than in playlist
Issue: androidx/media#86 #minor-release PiperOrigin-RevId: 455182232
This commit is contained in:
parent
12e7562730
commit
8f844b32fd
@ -185,6 +185,9 @@
|
||||
`MediaSession.Callback.onSetMediaUri`. The same functionality can be
|
||||
achieved by using `MediaController.setMediaItem` and
|
||||
`MediaSession.Callback.onAddMediaItems`.
|
||||
* Fix `IndexOutOfBoundsException` when setting less media items than in
|
||||
the current playlist
|
||||
([#86](https://github.com/androidx/media/issues/86)).
|
||||
* Data sources:
|
||||
* Rename `DummyDataSource` to `PlaceholderDataSource`.
|
||||
* Workaround OkHttp interrupt handling.
|
||||
|
@ -828,7 +828,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
Collections.singletonList(mediaItem),
|
||||
/* startIndex= */ C.INDEX_UNSET,
|
||||
/* startPositionMs= */ C.TIME_UNSET,
|
||||
/* resetToDefaultPosition= */ false);
|
||||
/* resetToDefaultPosition= */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -887,7 +887,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
mediaItems,
|
||||
/* startIndex= */ C.INDEX_UNSET,
|
||||
/* startPositionMs= */ C.TIME_UNSET,
|
||||
/* resetToDefaultPosition= */ false);
|
||||
/* resetToDefaultPosition= */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1832,12 +1832,18 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
throw new IllegalSeekPositionException(newTimeline, startIndex, startPositionMs);
|
||||
}
|
||||
|
||||
boolean correctedStartIndex = false;
|
||||
if (resetToDefaultPosition) {
|
||||
startIndex = newTimeline.getFirstWindowIndex(playerInfo.shuffleModeEnabled);
|
||||
startPositionMs = C.TIME_UNSET;
|
||||
} else if (startIndex == C.INDEX_UNSET) {
|
||||
startIndex = playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex;
|
||||
startPositionMs = playerInfo.sessionPositionInfo.positionInfo.positionMs;
|
||||
if (startIndex >= newTimeline.getWindowCount()) {
|
||||
correctedStartIndex = true;
|
||||
startIndex = newTimeline.getFirstWindowIndex(playerInfo.shuffleModeEnabled);
|
||||
startPositionMs = C.TIME_UNSET;
|
||||
}
|
||||
}
|
||||
PositionInfo newPositionInfo;
|
||||
SessionPositionInfo newSessionPositionInfo;
|
||||
@ -1905,7 +1911,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
// Mask the playback state.
|
||||
int maskingPlaybackState = newPlayerInfo.playbackState;
|
||||
if (startIndex != C.INDEX_UNSET && newPlayerInfo.playbackState != STATE_IDLE) {
|
||||
if (newTimeline.isEmpty() || startIndex >= newTimeline.getWindowCount()) {
|
||||
if (newTimeline.isEmpty() || correctedStartIndex) {
|
||||
// Setting an empty timeline or invalid seek transitions to ended.
|
||||
maskingPlaybackState = STATE_ENDED;
|
||||
} else {
|
||||
|
@ -36,6 +36,7 @@ import android.os.RemoteException;
|
||||
import androidx.media3.common.AudioAttributes;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.HeartRating;
|
||||
import androidx.media3.common.IllegalSeekPositionException;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaLibraryInfo;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
@ -56,6 +57,7 @@ import androidx.media3.test.session.common.TestUtils;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -64,6 +66,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
@ -1055,4 +1058,95 @@ public class MediaControllerTest {
|
||||
|
||||
assertThat(mediaMetadata).isEqualTo(testMediaMetadata);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
setMediaItems_setLessMediaItemsThanCurrentMediaItemIndex_masksCurrentMediaItemIndexAndStateCorrectly()
|
||||
throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
List<MediaItem> threeItemsList =
|
||||
ImmutableList.of(
|
||||
MediaItem.fromUri("http://www.google.com/1"),
|
||||
MediaItem.fromUri("http://www.google.com/2"),
|
||||
MediaItem.fromUri("http://www.google.com/3"));
|
||||
List<MediaItem> twoItemsList =
|
||||
ImmutableList.of(
|
||||
MediaItem.fromUri("http://www.google.com/1"),
|
||||
MediaItem.fromUri("http://www.google.com/2"));
|
||||
|
||||
int[] currentMediaIndexAndState =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(
|
||||
() -> {
|
||||
controller.setMediaItems(threeItemsList);
|
||||
controller.prepare();
|
||||
controller.seekTo(/* mediaItemIndex= */ 2, /* positionMs= */ C.TIME_UNSET);
|
||||
controller.setMediaItems(twoItemsList);
|
||||
return new int[] {
|
||||
controller.getCurrentMediaItemIndex(), controller.getPlaybackState()
|
||||
};
|
||||
});
|
||||
|
||||
assertThat(currentMediaIndexAndState[0]).isEqualTo(0);
|
||||
assertThat(currentMediaIndexAndState[1]).isEqualTo(Player.STATE_BUFFERING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
setMediaItems_setLessMediaItemsThanCurrentMediaItemIndexResetPositionFalse_masksCurrentMediaItemIndexAndStateCorrectly()
|
||||
throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
List<MediaItem> threeItemsList =
|
||||
ImmutableList.of(
|
||||
MediaItem.fromUri("http://www.google.com/1"),
|
||||
MediaItem.fromUri("http://www.google.com/2"),
|
||||
MediaItem.fromUri("http://www.google.com/3"));
|
||||
List<MediaItem> twoItemsList =
|
||||
ImmutableList.of(
|
||||
MediaItem.fromUri("http://www.google.com/1"),
|
||||
MediaItem.fromUri("http://www.google.com/2"));
|
||||
|
||||
int[] currentMediaItemIndexAndState =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(
|
||||
() -> {
|
||||
controller.setMediaItems(threeItemsList);
|
||||
controller.prepare();
|
||||
controller.seekTo(/* mediaItemIndex= */ 2, /* positionMs= */ C.TIME_UNSET);
|
||||
controller.setMediaItems(twoItemsList, /* resetPosition= */ false);
|
||||
return new int[] {
|
||||
controller.getCurrentMediaItemIndex(), controller.getPlaybackState()
|
||||
};
|
||||
});
|
||||
|
||||
assertThat(currentMediaItemIndexAndState[0]).isEqualTo(0);
|
||||
assertThat(currentMediaItemIndexAndState[1]).isEqualTo(Player.STATE_ENDED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMediaItems_startIndexTooLarge_throwIllegalSeekPositionException()
|
||||
throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
List<MediaItem> threeItemsList =
|
||||
ImmutableList.of(
|
||||
MediaItem.fromUri("http://www.google.com/1"),
|
||||
MediaItem.fromUri("http://www.google.com/2"),
|
||||
MediaItem.fromUri("http://www.google.com/3"));
|
||||
|
||||
Assert.assertThrows(
|
||||
IllegalSeekPositionException.class,
|
||||
() ->
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(
|
||||
() -> {
|
||||
controller.setMediaItems(
|
||||
threeItemsList,
|
||||
/* startIndex= */ 99,
|
||||
/* startPositionMs= */ C.TIME_UNSET);
|
||||
return controller.getCurrentMediaItemIndex();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user