mirror of
https://github.com/samsonjs/media.git
synced 2026-03-27 09:45:47 +00:00
Call new onPositionDiscontinuity callback in CastPlayer
PiperOrigin-RevId: 367020270
This commit is contained in:
parent
6f4db96da1
commit
4c33c5110e
2 changed files with 656 additions and 59 deletions
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.ext.cast;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Util.castNonNull;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
import android.os.Looper;
|
||||
|
|
@ -39,6 +40,7 @@ import com.google.android.exoplayer2.util.Clock;
|
|||
import com.google.android.exoplayer2.util.ListenerSet;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.android.gms.cast.CastStatusCodes;
|
||||
import com.google.android.gms.cast.MediaInfo;
|
||||
import com.google.android.gms.cast.MediaQueueItem;
|
||||
|
|
@ -129,6 +131,7 @@ public final class CastPlayer extends BasePlayer {
|
|||
private int pendingSeekCount;
|
||||
private int pendingSeekWindowIndex;
|
||||
private long pendingSeekPositionMs;
|
||||
@Nullable private PositionInfo pendingMediaItemRemovalPosition;
|
||||
|
||||
/**
|
||||
* Creates a new cast player that uses a {@link DefaultMediaItemConverter}.
|
||||
|
|
@ -460,23 +463,29 @@ public final class CastPlayer extends BasePlayer {
|
|||
if (getCurrentWindowIndex() != windowIndex) {
|
||||
remoteMediaClient.queueJumpToItem((int) currentTimeline.getPeriod(windowIndex, period).uid,
|
||||
positionMs, null).setResultCallback(seekResultCallback);
|
||||
} else {
|
||||
remoteMediaClient.seek(positionMs).setResultCallback(seekResultCallback);
|
||||
}
|
||||
PositionInfo oldPosition = getCurrentPositionInfo();
|
||||
pendingSeekCount++;
|
||||
pendingSeekWindowIndex = windowIndex;
|
||||
pendingSeekPositionMs = positionMs;
|
||||
PositionInfo newPosition = getCurrentPositionInfo();
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_POSITION_DISCONTINUITY,
|
||||
listener -> {
|
||||
listener.onPositionDiscontinuity(DISCONTINUITY_REASON_SEEK);
|
||||
listener.onPositionDiscontinuity(oldPosition, newPosition, DISCONTINUITY_REASON_SEEK);
|
||||
});
|
||||
if (oldPosition.windowIndex != newPosition.windowIndex) {
|
||||
// TODO(internal b/182261884): queue `onMediaItemTransition` event when the media item is
|
||||
// repeated.
|
||||
MediaItem mediaItem = currentTimeline.getWindow(windowIndex, window).mediaItem;
|
||||
MediaItem mediaItem = getCurrentTimeline().getWindow(windowIndex, window).mediaItem;
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||
listener ->
|
||||
listener.onMediaItemTransition(mediaItem, MEDIA_ITEM_TRANSITION_REASON_SEEK));
|
||||
} else {
|
||||
remoteMediaClient.seek(positionMs).setResultCallback(seekResultCallback);
|
||||
}
|
||||
pendingSeekCount++;
|
||||
pendingSeekWindowIndex = windowIndex;
|
||||
pendingSeekPositionMs = positionMs;
|
||||
// TODO(b/181262841): call new onPositionDiscontinuity callback
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_POSITION_DISCONTINUITY,
|
||||
listener -> listener.onPositionDiscontinuity(DISCONTINUITY_REASON_SEEK));
|
||||
updateAvailableCommandsAndNotifyIfChanged();
|
||||
} else if (pendingSeekCount == 0) {
|
||||
listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed);
|
||||
|
|
@ -657,7 +666,12 @@ public final class CastPlayer extends BasePlayer {
|
|||
// There is no session. We leave the state of the player as it is now.
|
||||
return;
|
||||
}
|
||||
int previousWindowIndex = this.currentWindowIndex;
|
||||
int oldWindowIndex = this.currentWindowIndex;
|
||||
@Nullable
|
||||
Object oldPeriodUid =
|
||||
!getCurrentTimeline().isEmpty()
|
||||
? getCurrentTimeline().getPeriod(oldWindowIndex, period, /* setIds= */ true).uid
|
||||
: null;
|
||||
boolean wasPlaying = playbackState == Player.STATE_READY && playWhenReady.value;
|
||||
updatePlayerStateAndNotifyIfChanged(/* resultCallback= */ null);
|
||||
boolean isPlaying = playbackState == Player.STATE_READY && playWhenReady.value;
|
||||
|
|
@ -667,16 +681,49 @@ public final class CastPlayer extends BasePlayer {
|
|||
}
|
||||
updateRepeatModeAndNotifyIfChanged(/* resultCallback= */ null);
|
||||
boolean playingPeriodChangedByTimelineChange = updateTimelineAndNotifyIfChanged();
|
||||
|
||||
int currentWindowIndex = fetchCurrentWindowIndex(remoteMediaClient, currentTimeline);
|
||||
Timeline currentTimeline = getCurrentTimeline();
|
||||
currentWindowIndex = fetchCurrentWindowIndex(remoteMediaClient, currentTimeline);
|
||||
@Nullable
|
||||
Object currentPeriodUid =
|
||||
!currentTimeline.isEmpty()
|
||||
? currentTimeline.getPeriod(currentWindowIndex, period, /* setIds= */ true).uid
|
||||
: null;
|
||||
if (!playingPeriodChangedByTimelineChange
|
||||
&& previousWindowIndex != currentWindowIndex
|
||||
&& !Util.areEqual(oldPeriodUid, currentPeriodUid)
|
||||
&& pendingSeekCount == 0) {
|
||||
this.currentWindowIndex = currentWindowIndex;
|
||||
// TODO(b/181262841): call new onPositionDiscontinuity callback
|
||||
// Report discontinuity and media item auto transition.
|
||||
currentTimeline.getPeriod(oldWindowIndex, period, /* setIds= */ true);
|
||||
currentTimeline.getWindow(oldWindowIndex, window);
|
||||
long windowDurationMs = window.getDurationMs();
|
||||
PositionInfo oldPosition =
|
||||
new PositionInfo(
|
||||
window.uid,
|
||||
period.windowIndex,
|
||||
period.uid,
|
||||
period.windowIndex,
|
||||
/* positionMs= */ windowDurationMs,
|
||||
/* contentPositionMs= */ windowDurationMs,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
currentTimeline.getPeriod(currentWindowIndex, period, /* setIds= */ true);
|
||||
currentTimeline.getWindow(currentWindowIndex, window);
|
||||
PositionInfo newPosition =
|
||||
new PositionInfo(
|
||||
window.uid,
|
||||
period.windowIndex,
|
||||
period.uid,
|
||||
period.windowIndex,
|
||||
/* positionMs= */ window.getDefaultPositionMs(),
|
||||
/* contentPositionMs= */ window.getDefaultPositionMs(),
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_POSITION_DISCONTINUITY,
|
||||
listener -> listener.onPositionDiscontinuity(DISCONTINUITY_REASON_AUTO_TRANSITION));
|
||||
listener -> {
|
||||
listener.onPositionDiscontinuity(DISCONTINUITY_REASON_AUTO_TRANSITION);
|
||||
listener.onPositionDiscontinuity(
|
||||
oldPosition, newPosition, DISCONTINUITY_REASON_AUTO_TRANSITION);
|
||||
});
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||
listener ->
|
||||
|
|
@ -731,13 +778,14 @@ public final class CastPlayer extends BasePlayer {
|
|||
*/
|
||||
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||
private boolean updateTimelineAndNotifyIfChanged() {
|
||||
Timeline previousTimeline = currentTimeline;
|
||||
int previousWindowIndex = currentWindowIndex;
|
||||
Timeline oldTimeline = currentTimeline;
|
||||
int oldWindowIndex = currentWindowIndex;
|
||||
boolean playingPeriodChanged = false;
|
||||
if (updateTimeline()) {
|
||||
// TODO: Differentiate TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED and
|
||||
// TIMELINE_CHANGE_REASON_SOURCE_UPDATE [see internal: b/65152553].
|
||||
Timeline timeline = currentTimeline;
|
||||
// Call onTimelineChanged.
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_TIMELINE_CHANGED,
|
||||
listener -> {
|
||||
|
|
@ -746,15 +794,48 @@ public final class CastPlayer extends BasePlayer {
|
|||
listener.onTimelineChanged(timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
|
||||
});
|
||||
|
||||
updateAvailableCommandsAndNotifyIfChanged();
|
||||
|
||||
if (currentTimeline.isEmpty() != previousTimeline.isEmpty()) {
|
||||
// Timeline initially populated or timeline cleared.
|
||||
playingPeriodChanged = true;
|
||||
} else if (!currentTimeline.isEmpty()) {
|
||||
Object previousWindowUid = previousTimeline.getWindow(previousWindowIndex, window).uid;
|
||||
playingPeriodChanged = currentTimeline.getIndexOfPeriod(previousWindowUid) == C.INDEX_UNSET;
|
||||
// Call onPositionDiscontinuity if required.
|
||||
Timeline currentTimeline = getCurrentTimeline();
|
||||
boolean playingPeriodRemoved = false;
|
||||
if (!oldTimeline.isEmpty()) {
|
||||
Object oldPeriodUid =
|
||||
castNonNull(oldTimeline.getPeriod(oldWindowIndex, period, /* setIds= */ true).uid);
|
||||
playingPeriodRemoved = currentTimeline.getIndexOfPeriod(oldPeriodUid) == C.INDEX_UNSET;
|
||||
}
|
||||
if (playingPeriodRemoved) {
|
||||
PositionInfo oldPosition;
|
||||
if (pendingMediaItemRemovalPosition != null) {
|
||||
oldPosition = pendingMediaItemRemovalPosition;
|
||||
pendingMediaItemRemovalPosition = null;
|
||||
} else {
|
||||
// If the media item has been removed by another client, we don't know the removal
|
||||
// position. We use the current position as a fallback.
|
||||
oldTimeline.getPeriod(oldWindowIndex, period, /* setIds= */ true);
|
||||
oldTimeline.getWindow(period.windowIndex, window);
|
||||
oldPosition =
|
||||
new PositionInfo(
|
||||
window.uid,
|
||||
period.windowIndex,
|
||||
period.uid,
|
||||
period.windowIndex,
|
||||
getCurrentPosition(),
|
||||
getContentPosition(),
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
}
|
||||
PositionInfo newPosition = getCurrentPositionInfo();
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_POSITION_DISCONTINUITY,
|
||||
listener -> {
|
||||
listener.onPositionDiscontinuity(DISCONTINUITY_REASON_REMOVE);
|
||||
listener.onPositionDiscontinuity(
|
||||
oldPosition, newPosition, DISCONTINUITY_REASON_REMOVE);
|
||||
});
|
||||
}
|
||||
|
||||
// Call onMediaItemTransition if required.
|
||||
playingPeriodChanged =
|
||||
currentTimeline.isEmpty() != oldTimeline.isEmpty() || playingPeriodRemoved;
|
||||
if (playingPeriodChanged) {
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||
|
|
@ -762,6 +843,7 @@ public final class CastPlayer extends BasePlayer {
|
|||
listener.onMediaItemTransition(
|
||||
getCurrentMediaItem(), MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
}
|
||||
updateAvailableCommandsAndNotifyIfChanged();
|
||||
}
|
||||
return playingPeriodChanged;
|
||||
}
|
||||
|
|
@ -856,6 +938,10 @@ public final class CastPlayer extends BasePlayer {
|
|||
startWindowIndex = getCurrentWindowIndex();
|
||||
startPositionMs = getCurrentPosition();
|
||||
}
|
||||
Timeline currentTimeline = getCurrentTimeline();
|
||||
if (!currentTimeline.isEmpty()) {
|
||||
pendingMediaItemRemovalPosition = getCurrentPositionInfo();
|
||||
}
|
||||
return remoteMediaClient.queueLoad(
|
||||
mediaQueueItems,
|
||||
min(startWindowIndex, mediaQueueItems.length - 1),
|
||||
|
|
@ -891,9 +977,41 @@ public final class CastPlayer extends BasePlayer {
|
|||
if (remoteMediaClient == null || getMediaStatus() == null) {
|
||||
return null;
|
||||
}
|
||||
Timeline timeline = getCurrentTimeline();
|
||||
if (!timeline.isEmpty()) {
|
||||
Object periodUid =
|
||||
castNonNull(timeline.getPeriod(getCurrentPeriodIndex(), period, /* setIds= */ true).uid);
|
||||
for (int uid : uids) {
|
||||
if (periodUid.equals(uid)) {
|
||||
pendingMediaItemRemovalPosition = getCurrentPositionInfo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return remoteMediaClient.queueRemoveItems(uids, /* customData= */ null);
|
||||
}
|
||||
|
||||
private PositionInfo getCurrentPositionInfo() {
|
||||
Timeline currentTimeline = getCurrentTimeline();
|
||||
@Nullable
|
||||
Object newPeriodUid =
|
||||
!currentTimeline.isEmpty()
|
||||
? currentTimeline.getPeriod(getCurrentPeriodIndex(), period, /* setIds= */ true).uid
|
||||
: null;
|
||||
@Nullable
|
||||
Object newWindowUid =
|
||||
newPeriodUid != null ? currentTimeline.getWindow(period.windowIndex, window).uid : null;
|
||||
return new PositionInfo(
|
||||
newWindowUid,
|
||||
getCurrentWindowIndex(),
|
||||
newPeriodUid,
|
||||
getCurrentPeriodIndex(),
|
||||
getCurrentPosition(),
|
||||
getContentPosition(),
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
}
|
||||
|
||||
private void setRepeatModeAndNotifyIfChanged(@Player.RepeatMode int repeatMode) {
|
||||
if (this.repeatMode.value != repeatMode) {
|
||||
this.repeatMode.value = repeatMode;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ import static com.google.android.exoplayer2.Player.COMMAND_SET_SHUFFLE_MODE;
|
|||
import static com.google.android.exoplayer2.Player.COMMAND_SET_SPEED_AND_PITCH;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_SET_VIDEO_SURFACE;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_SET_VOLUME;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_REMOVE;
|
||||
import static com.google.android.exoplayer2.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
|
|
@ -49,6 +51,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
|
|
@ -292,6 +295,109 @@ public class CastPlayerTest {
|
|||
assertThat(mediaQueueItems[1].getMedia().getContentId()).isEqualTo(uri2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Verifies deprecated callback being called correctly.
|
||||
@Test
|
||||
public void setMediaItems_replaceExistingPlaylist_notifiesMediaItemTransition() {
|
||||
List<MediaItem> firstPlaylist = new ArrayList<>();
|
||||
String uri1 = "http://www.google.com/video1";
|
||||
String uri2 = "http://www.google.com/video2";
|
||||
firstPlaylist.add(
|
||||
new MediaItem.Builder().setUri(uri1).setMimeType(MimeTypes.APPLICATION_MPD).build());
|
||||
firstPlaylist.add(
|
||||
new MediaItem.Builder().setUri(uri2).setMimeType(MimeTypes.APPLICATION_MP4).build());
|
||||
ImmutableList<MediaItem> secondPlaylist =
|
||||
ImmutableList.of(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.EMPTY)
|
||||
.setMimeType(MimeTypes.APPLICATION_MPD)
|
||||
.build());
|
||||
|
||||
castPlayer.setMediaItems(
|
||||
firstPlaylist, /* startWindowIndex= */ 1, /* startPositionMs= */ 2000L);
|
||||
updateTimeLine(
|
||||
firstPlaylist, /* mediaQueueItemIds= */ new int[] {1, 2}, /* currentItemId= */ 2);
|
||||
// Replacing existing playlist.
|
||||
castPlayer.setMediaItems(
|
||||
secondPlaylist, /* startWindowIndex= */ 0, /* startPositionMs= */ 1000L);
|
||||
updateTimeLine(secondPlaylist, /* mediaQueueItemIds= */ new int[] {3}, /* currentItemId= */ 3);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener, times(2))
|
||||
.onMediaItemTransition(
|
||||
mediaItemCaptor.capture(), eq(MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
assertThat(mediaItemCaptor.getAllValues().get(1).playbackProperties.tag).isEqualTo(3);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Verifies deprecated callback being called correctly.
|
||||
@Test
|
||||
public void setMediaItems_replaceExistingPlaylist_notifiesPositionDiscontinuity() {
|
||||
List<MediaItem> firstPlaylist = new ArrayList<>();
|
||||
String uri1 = "http://www.google.com/video1";
|
||||
String uri2 = "http://www.google.com/video2";
|
||||
firstPlaylist.add(
|
||||
new MediaItem.Builder().setUri(uri1).setMimeType(MimeTypes.APPLICATION_MPD).build());
|
||||
firstPlaylist.add(
|
||||
new MediaItem.Builder().setUri(uri2).setMimeType(MimeTypes.APPLICATION_MP4).build());
|
||||
ImmutableList<MediaItem> secondPlaylist =
|
||||
ImmutableList.of(
|
||||
new MediaItem.Builder()
|
||||
.setUri(Uri.EMPTY)
|
||||
.setMimeType(MimeTypes.APPLICATION_MPD)
|
||||
.build());
|
||||
|
||||
castPlayer.setMediaItems(
|
||||
firstPlaylist, /* startWindowIndex= */ 1, /* startPositionMs= */ 2000L);
|
||||
updateTimeLine(
|
||||
firstPlaylist,
|
||||
/* mediaQueueItemIds= */ new int[] {1, 2},
|
||||
/* currentItemId= */ 2,
|
||||
/* streamTypes= */ new int[] {
|
||||
MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED
|
||||
},
|
||||
/* durationsMs= */ new long[] {20_000, 20_000},
|
||||
/* positionMs= */ 2000L);
|
||||
// Replacing existing playlist.
|
||||
castPlayer.setMediaItems(
|
||||
secondPlaylist, /* startWindowIndex= */ 0, /* startPositionMs= */ 1000L);
|
||||
updateTimeLine(
|
||||
secondPlaylist,
|
||||
/* mediaQueueItemIds= */ new int[] {3},
|
||||
/* currentItemId= */ 3,
|
||||
/* streamTypes= */ new int[] {MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {20_000},
|
||||
/* positionMs= */ 1000L);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 2,
|
||||
/* windowIndex= */ 1,
|
||||
/* periodUid= */ 2,
|
||||
/* periodIndex= */ 1,
|
||||
/* positionMs= */ 2000,
|
||||
/* contentPositionMs= */ 2000,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 3,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 3,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 1000,
|
||||
/* contentPositionMs= */ 1000,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder.verify(mockListener).onPositionDiscontinuity(eq(DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(eq(oldPosition), eq(newPosition), eq(DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addMediaItems_callsRemoteMediaClient() {
|
||||
MediaItem.Builder builder = new MediaItem.Builder();
|
||||
|
|
@ -486,12 +592,14 @@ public class CastPlayerTest {
|
|||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
|
||||
verify(mockListener)
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(
|
||||
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
assertThat(mediaItemCaptor.getValue().playbackProperties.tag)
|
||||
.isEqualTo(mediaItem.playbackProperties.tag);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -501,17 +609,74 @@ public class CastPlayerTest {
|
|||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
|
||||
castPlayer.clearMediaItems();
|
||||
updateTimeLine(
|
||||
/* mediaItems= */ ImmutableList.of(),
|
||||
/* mediaQueueItemIds= */ new int[0],
|
||||
/* currentItemId= */ C.INDEX_UNSET);
|
||||
verify(mockListener)
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(
|
||||
/* mediaItem= */ null, Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
|
||||
verify(mockListener, times(2)).onMediaItemTransition(any(), anyInt());
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void clearMediaItems_notifiesPositionDiscontinuity() {
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(
|
||||
mediaItems,
|
||||
mediaQueueItemIds,
|
||||
/* currentItemId= */ 1,
|
||||
new int[] {MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {20_000L, 30_000L},
|
||||
/* positionMs= */ 1234);
|
||||
castPlayer.clearMediaItems();
|
||||
updateTimeLine(
|
||||
/* mediaItems= */ ImmutableList.of(),
|
||||
/* mediaQueueItemIds= */ new int[0],
|
||||
/* currentItemId= */ C.INDEX_UNSET,
|
||||
new int[] {MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {20_000L},
|
||||
/* positionMs= */ 0);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 1234,
|
||||
/* contentPositionMs= */ 1234,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ null,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ null,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 0,
|
||||
/* contentPositionMs= */ 0,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(
|
||||
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -523,19 +688,160 @@ public class CastPlayerTest {
|
|||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
|
||||
castPlayer.removeMediaItem(/* index= */ 0);
|
||||
// Update with the new timeline after removal.
|
||||
updateTimeLine(
|
||||
ImmutableList.of(mediaItem2),
|
||||
/* mediaQueueItemIds= */ new int[] {2},
|
||||
/* currentItemId= */ 2);
|
||||
verify(mockListener, times(2))
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener, times(2))
|
||||
.onMediaItemTransition(
|
||||
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
assertThat(mediaItemCaptor.getValue().playbackProperties.tag)
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
assertThat(mediaItemCaptor.getAllValues().get(0).playbackProperties.tag)
|
||||
.isEqualTo(mediaItem1.playbackProperties.tag);
|
||||
assertThat(mediaItemCaptor.getAllValues().get(1).playbackProperties.tag)
|
||||
.isEqualTo(mediaItem2.playbackProperties.tag);
|
||||
verify(mockListener, times(2)).onMediaItemTransition(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void removeCurrentMediaItem_notifiesPositionDiscontinuity() {
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(
|
||||
mediaItems,
|
||||
mediaQueueItemIds,
|
||||
/* currentItemId= */ 1,
|
||||
new int[] {MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {20_000L, 30_000L},
|
||||
/* positionMs= */ 1234);
|
||||
castPlayer.removeMediaItem(/* index= */ 0);
|
||||
// Update with the new timeline after removal.
|
||||
updateTimeLine(
|
||||
ImmutableList.of(mediaItem2),
|
||||
/* mediaQueueItemIds= */ new int[] {2},
|
||||
/* currentItemId= */ 2,
|
||||
new int[] {MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {20_000L},
|
||||
/* positionMs= */ 0);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 1234,
|
||||
/* contentPositionMs= */ 1234,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 2,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 2,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 0,
|
||||
/* contentPositionMs= */ 0,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(
|
||||
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeCurrentMediaItem_byRemoteClient_notifiesMediaItemTransition() {
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, new int[] {1, 2}, /* currentItemId= */ 1);
|
||||
// Update with the new timeline after removal on the device.
|
||||
updateTimeLine(
|
||||
ImmutableList.of(mediaItem2),
|
||||
/* mediaQueueItemIds= */ new int[] {2},
|
||||
/* currentItemId= */ 2);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener, times(2))
|
||||
.onMediaItemTransition(
|
||||
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
List<MediaItem> capturedMediaItems = mediaItemCaptor.getAllValues();
|
||||
assertThat(capturedMediaItems.get(0).playbackProperties.tag)
|
||||
.isEqualTo(mediaItem1.playbackProperties.tag);
|
||||
assertThat(capturedMediaItems.get(1).playbackProperties.tag)
|
||||
.isEqualTo(mediaItem2.playbackProperties.tag);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void removeCurrentMediaItem_byRemoteClient_notifiesPositionDiscontinuity() {
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(
|
||||
mediaItems,
|
||||
new int[] {1, 2},
|
||||
/* currentItemId= */ 1,
|
||||
new int[] {MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {20_000L, 30_000L},
|
||||
/* positionMs= */ 1234);
|
||||
// Update with the new timeline after removal on the device.
|
||||
updateTimeLine(
|
||||
ImmutableList.of(mediaItem2),
|
||||
/* mediaQueueItemIds= */ new int[] {2},
|
||||
/* currentItemId= */ 2,
|
||||
new int[] {MediaInfo.STREAM_TYPE_BUFFERED},
|
||||
/* durationsMs= */ new long[] {30_000L},
|
||||
/* positionMs= */ 0);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 0, // position at which we receive the timeline change
|
||||
/* contentPositionMs= */ 0, // position at which we receive the timeline change
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 2,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 2,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 0,
|
||||
/* contentPositionMs= */ 0,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(
|
||||
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_REMOVE));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -547,14 +853,37 @@ public class CastPlayerTest {
|
|||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
|
||||
castPlayer.removeMediaItem(/* index= */ 1);
|
||||
updateTimeLine(
|
||||
ImmutableList.of(mediaItem1),
|
||||
/* mediaQueueItemIds= */ new int[] {1},
|
||||
/* currentItemId= */ 1);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void removeNonCurrentMediaItem_doesNotNotifyPositionDiscontinuity() {
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
castPlayer.removeMediaItem(/* index= */ 1);
|
||||
updateTimeLine(
|
||||
ImmutableList.of(mediaItem1),
|
||||
/* mediaQueueItemIds= */ new int[] {1},
|
||||
/* currentItemId= */ 1);
|
||||
|
||||
verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -568,15 +897,63 @@ public class CastPlayerTest {
|
|||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
castPlayer.seekTo(/* windowIndex= */ 1, /* positionMs= */ 1234);
|
||||
|
||||
castPlayer.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0);
|
||||
verify(mockListener)
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(
|
||||
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_SEEK));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
assertThat(mediaItemCaptor.getValue().playbackProperties.tag)
|
||||
.isEqualTo(mediaItem2.playbackProperties.tag);
|
||||
verify(mockListener, times(2)).onMediaItemTransition(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void seekTo_otherWindow_notifiesPositionDiscontinuity() {
|
||||
when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null)))
|
||||
.thenReturn(mockPendingResult);
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
castPlayer.seekTo(/* windowIndex= */ 1, /* positionMs= */ 1234);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 0,
|
||||
/* contentPositionMs= */ 0,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 2,
|
||||
/* windowIndex= */ 1,
|
||||
/* periodUid= */ 2,
|
||||
/* periodIndex= */ 1,
|
||||
/* positionMs= */ 1234,
|
||||
/* contentPositionMs= */ 1234,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_SEEK));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(
|
||||
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_SEEK));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -588,15 +965,82 @@ public class CastPlayerTest {
|
|||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 1234);
|
||||
|
||||
castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 0);
|
||||
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void autoTransition_notifiesMediaItemTransitionAndPositionDiscontinuity() {
|
||||
public void seekTo_sameWindow_notifiesPositionDiscontinuity() {
|
||||
when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult);
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 1234);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 0,
|
||||
/* contentPositionMs= */ 0,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 1234,
|
||||
/* contentPositionMs= */ 1234,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_SEEK));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(
|
||||
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_SEEK));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoTransition_notifiesMediaItemTransition() {
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
// When the remote Cast player transitions to an item that wasn't played before, the media state
|
||||
// delivers the duration for that media item which updates the timeline accordingly.
|
||||
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
|
||||
|
||||
castPlayer.addMediaItems(mediaItems);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 2);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(
|
||||
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_AUTO));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
assertThat(mediaItemCaptor.getValue().playbackProperties.tag).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||
public void autoTransition_notifiesPositionDiscontinuity() {
|
||||
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||
int[] streamTypes = {MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED};
|
||||
long[] durationsFirstMs = {12500, C.TIME_UNSET};
|
||||
|
|
@ -611,25 +1055,44 @@ public class CastPlayerTest {
|
|||
mediaQueueItemIds,
|
||||
/* currentItemId= */ 1,
|
||||
/* streamTypes= */ streamTypes,
|
||||
/* durationsMs= */ durationsFirstMs);
|
||||
/* durationsMs= */ durationsFirstMs,
|
||||
/* positionMs= */ C.TIME_UNSET);
|
||||
updateTimeLine(
|
||||
mediaItems,
|
||||
mediaQueueItemIds,
|
||||
/* currentItemId= */ 2,
|
||||
/* streamTypes= */ streamTypes,
|
||||
/* durationsMs= */ durationsSecondMs);
|
||||
/* durationsMs= */ durationsSecondMs,
|
||||
/* positionMs= */ C.TIME_UNSET);
|
||||
|
||||
Player.PositionInfo oldPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 1,
|
||||
/* windowIndex= */ 0,
|
||||
/* periodUid= */ 1,
|
||||
/* periodIndex= */ 0,
|
||||
/* positionMs= */ 12500,
|
||||
/* contentPositionMs= */ 12500,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
Player.PositionInfo newPosition =
|
||||
new Player.PositionInfo(
|
||||
/* windowUid= */ 2,
|
||||
/* windowIndex= */ 1,
|
||||
/* periodUid= */ 2,
|
||||
/* periodIndex= */ 1,
|
||||
/* positionMs= */ 0,
|
||||
/* contentPositionMs= */ 0,
|
||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||
InOrder inOrder = Mockito.inOrder(mockListener);
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
|
||||
inOrder
|
||||
.verify(mockListener)
|
||||
.onMediaItemTransition(any(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_AUTO));
|
||||
inOrder.verify(mockListener, never()).onMediaItemTransition(any(), anyInt());
|
||||
.onPositionDiscontinuity(
|
||||
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||
}
|
||||
|
|
@ -674,7 +1137,13 @@ public class CastPlayerTest {
|
|||
long[] durationsMs = new long[] {C.TIME_UNSET};
|
||||
|
||||
castPlayer.addMediaItem(mediaItem);
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */ 1, streamTypes, durationsMs);
|
||||
updateTimeLine(
|
||||
mediaItems,
|
||||
mediaQueueItemIds,
|
||||
/* currentItemId= */ 1,
|
||||
streamTypes,
|
||||
durationsMs,
|
||||
/* positionMs= */ C.TIME_UNSET);
|
||||
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse();
|
||||
}
|
||||
|
|
@ -1041,7 +1510,13 @@ public class CastPlayerTest {
|
|||
int[] streamTypes = new int[mediaItems.size()];
|
||||
Arrays.fill(streamTypes, MediaInfo.STREAM_TYPE_BUFFERED);
|
||||
long[] durationsMs = new long[mediaItems.size()];
|
||||
updateTimeLine(mediaItems, mediaQueueItemIds, currentItemId, streamTypes, durationsMs);
|
||||
updateTimeLine(
|
||||
mediaItems,
|
||||
mediaQueueItemIds,
|
||||
currentItemId,
|
||||
streamTypes,
|
||||
durationsMs,
|
||||
/* positionMs= */ C.TIME_UNSET);
|
||||
}
|
||||
|
||||
private void updateTimeLine(
|
||||
|
|
@ -1049,7 +1524,8 @@ public class CastPlayerTest {
|
|||
int[] mediaQueueItemIds,
|
||||
int currentItemId,
|
||||
int[] streamTypes,
|
||||
long[] durationsMs) {
|
||||
long[] durationsMs,
|
||||
long positionMs) {
|
||||
// Set up mocks to allow the player to update the timeline.
|
||||
List<MediaQueueItem> queueItems = new ArrayList<>();
|
||||
for (int i = 0; i < mediaQueueItemIds.length; i++) {
|
||||
|
|
@ -1074,6 +1550,9 @@ public class CastPlayerTest {
|
|||
when(mockMediaStatus.getMediaInfo()).thenReturn(mediaInfo);
|
||||
}
|
||||
}
|
||||
if (positionMs != C.TIME_UNSET) {
|
||||
when(mockRemoteMediaClient.getApproximateStreamPosition()).thenReturn(positionMs);
|
||||
}
|
||||
when(mockMediaQueue.getItemIds()).thenReturn(mediaQueueItemIds);
|
||||
when(mockMediaStatus.getQueueItems()).thenReturn(queueItems);
|
||||
when(mockMediaStatus.getCurrentItemId())
|
||||
|
|
|
|||
Loading…
Reference in a new issue