Commit 86cc9168 by tonihei Committed by Rohit Singh

Allow duplicated MediaItems in a legacy session

MediaItems are not meant to be unique in a playlist. If a legacy
session publishes multiple items that get converted to equal MediaItems,
the current code fails because we look up queue ids in a Map (that
doesn't allow duplicate entries).

Fix this by storing a simple list of items with additional data.

Issue: androidx/media#290
PiperOrigin-RevId: 521993802
(cherry picked from commit 219967c5)
parent 10e2dfd2
......@@ -1795,7 +1795,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
currentTimeline =
isQueueChanged
? QueueTimeline.create(newLegacyPlayerInfo.queue)
: new QueueTimeline((QueueTimeline) oldControllerInfo.playerInfo.timeline);
: ((QueueTimeline) oldControllerInfo.playerInfo.timeline).copy();
boolean isMetadataCompatChanged =
oldLegacyPlayerInfo.mediaMetadataCompat != newLegacyPlayerInfo.mediaMetadataCompat
......@@ -1987,8 +1987,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
Integer mediaItemTransitionReason;
boolean isOldTimelineEmpty = oldControllerInfo.playerInfo.timeline.isEmpty();
boolean isNewTimelineEmpty = newControllerInfo.playerInfo.timeline.isEmpty();
int newCurrentMediaItemIndex =
newControllerInfo.playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex;
if (isOldTimelineEmpty && isNewTimelineEmpty) {
// Still empty Timelines.
discontinuityReason = null;
......@@ -2000,13 +1998,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
} else {
MediaItem oldCurrentMediaItem =
checkStateNotNull(oldControllerInfo.playerInfo.getCurrentMediaItem());
int oldCurrentMediaItemIndexInNewTimeline =
((QueueTimeline) newControllerInfo.playerInfo.timeline).indexOf(oldCurrentMediaItem);
if (oldCurrentMediaItemIndexInNewTimeline == C.INDEX_UNSET) {
boolean oldCurrentMediaItemExistsInNewTimeline =
((QueueTimeline) newControllerInfo.playerInfo.timeline).contains(oldCurrentMediaItem);
if (!oldCurrentMediaItemExistsInNewTimeline) {
// Old current item is removed.
discontinuityReason = Player.DISCONTINUITY_REASON_REMOVE;
mediaItemTransitionReason = Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED;
} else if (oldCurrentMediaItemIndexInNewTimeline == newCurrentMediaItemIndex) {
} else if (oldCurrentMediaItem.equals(newControllerInfo.playerInfo.getCurrentMediaItem())) {
// Current item is the same.
long oldCurrentPosition =
MediaUtils.convertToCurrentPositionMs(
......
......@@ -78,6 +78,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.ext.truth.os.BundleSubject;
import androidx.test.filters.MediumTest;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Range;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
......@@ -415,6 +416,41 @@ public class MediaControllerWithMediaSessionCompatTest {
}
@Test
public void setQueue_withDuplicatedMediaItems_updatesAndNotifiesTimeline() throws Exception {
MediaController controller = controllerTestRule.createController(session.getSessionToken());
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<Timeline> timelineFromParamRef = new AtomicReference<>();
AtomicReference<Timeline> timelineFromGetterRef = new AtomicReference<>();
AtomicInteger reasonRef = new AtomicInteger();
Player.Listener listener =
new Player.Listener() {
@Override
public void onTimelineChanged(
Timeline timeline, @Player.TimelineChangeReason int reason) {
timelineFromParamRef.set(timeline);
timelineFromGetterRef.set(controller.getCurrentTimeline());
reasonRef.set(reason);
latch.countDown();
}
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 2);
Timeline testTimeline =
MediaTestUtils.createTimeline(
ImmutableList.copyOf(Iterables.concat(mediaItems, mediaItems)));
List<QueueItem> testQueue =
MediaTestUtils.convertToQueueItemsWithoutBitmap(
MediaUtils.convertToMediaItemList(testTimeline));
session.setQueue(testQueue);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
MediaTestUtils.assertMediaIdEquals(testTimeline, timelineFromParamRef.get());
MediaTestUtils.assertMediaIdEquals(testTimeline, timelineFromGetterRef.get());
assertThat(reasonRef.get()).isEqualTo(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
}
@Test
public void setQueue_withDescription_notifiesTimelineWithMetadata() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<Timeline> timelineRef = new AtomicReference<>();
......
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