Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
4c33c511
authored
Apr 06, 2021
by
bachinger
Committed by
marcbaechinger
Apr 09, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Call new onPositionDiscontinuity callback in CastPlayer
PiperOrigin-RevId: 367020270
parent
6f4db96d
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
654 additions
and
57 deletions
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
View file @
4c33c511
...
...
@@ -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
);
// TODO(internal b/182261884): queue `onMediaItemTransition` event when the media item is
// repeated.
MediaItem
mediaItem
=
currentTimeline
.
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
);
}
PositionInfo
oldPosition
=
getCurrentPositionInfo
();
pendingSeekCount
++;
pendingSeekWindowIndex
=
windowIndex
;
pendingSeekPositionMs
=
positionMs
;
// TODO(b/181262841): call new onPositionDiscontinuity callback
PositionInfo
newPosition
=
getCurrentPositionInfo
();
listeners
.
queueEvent
(
Player
.
EVENT_POSITION_DISCONTINUITY
,
listener
->
listener
.
onPositionDiscontinuity
(
DISCONTINUITY_REASON_SEEK
));
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
=
getCurrentTimeline
().
getWindow
(
windowIndex
,
window
).
mediaItem
;
listeners
.
queueEvent
(
Player
.
EVENT_MEDIA_ITEM_TRANSITION
,
listener
->
listener
.
onMediaItemTransition
(
mediaItem
,
MEDIA_ITEM_TRANSITION_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
previous
Timeline
=
currentTimeline
;
int
previous
WindowIndex
=
currentWindowIndex
;
Timeline
old
Timeline
=
currentTimeline
;
int
old
WindowIndex
=
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
;
...
...
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
View file @
4c33c511
...
...
@@ -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
);
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
());
assertThat
(
mediaItemCaptor
.
getAllValues
().
get
(
0
).
playbackProperties
.
tag
)
.
isEqualTo
(
mediaItem1
.
playbackProperties
.
tag
);
assertThat
(
mediaItemCaptor
.
getAllValues
().
get
(
1
).
playbackProperties
.
tag
)
.
isEqualTo
(
mediaItem2
.
playbackProperties
.
tag
);
}
@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
);
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
());
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
);
verify
(
mockListener
,
times
(
2
)).
onMediaItemTransition
(
any
(),
anyInt
());
}
@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
);
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
).
onMediaItemTransition
(
any
(),
anyInt
());
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
)
.
on
MediaItemTransition
(
any
(),
eq
(
Player
.
MEDIA_ITEM_TRANSITION_REASON_AUTO
));
inOrder
.
verify
(
mockListener
,
never
()).
onMediaItemTransition
(
any
(),
anyInt
(
));
.
on
PositionDiscontinuity
(
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
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment