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
851c915e
authored
Mar 10, 2021
by
kimvde
Committed by
Ian Baker
Mar 12, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM to available commands
PiperOrigin-RevId: 362036291
parent
383b6d42
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
434 additions
and
160 deletions
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java
library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java
library/common/src/main/java/com/google/android/exoplayer2/Player.java
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
View file @
851c915e
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
ext
.
cast
;
package
com
.
google
.
android
.
exoplayer2
.
ext
.
cast
;
import
static
com
.
google
.
android
.
exoplayer2
.
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
;
import
static
com
.
google
.
android
.
exoplayer2
.
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
;
import
static
com
.
google
.
android
.
exoplayer2
.
Player
.
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyInt
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyInt
;
...
@@ -45,6 +46,7 @@ import com.google.android.gms.cast.framework.media.MediaQueue;
...
@@ -45,6 +46,7 @@ import com.google.android.gms.cast.framework.media.MediaQueue;
import
com.google.android.gms.cast.framework.media.RemoteMediaClient
;
import
com.google.android.gms.cast.framework.media.RemoteMediaClient
;
import
com.google.android.gms.common.api.PendingResult
;
import
com.google.android.gms.common.api.PendingResult
;
import
com.google.android.gms.common.api.ResultCallback
;
import
com.google.android.gms.common.api.ResultCallback
;
import
com.google.android.gms.common.api.Status
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableList
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
...
@@ -69,11 +71,13 @@ public class CastPlayerTest {
...
@@ -69,11 +71,13 @@ public class CastPlayerTest {
@Mock
private
MediaStatus
mockMediaStatus
;
@Mock
private
MediaStatus
mockMediaStatus
;
@Mock
private
MediaInfo
mockMediaInfo
;
@Mock
private
MediaInfo
mockMediaInfo
;
@Mock
private
MediaQueue
mockMediaQueue
;
@Mock
private
MediaQueue
mockMediaQueue
;
@Mock
private
MediaQueueItem
mockMediaQueueItem
;
@Mock
private
CastContext
mockCastContext
;
@Mock
private
CastContext
mockCastContext
;
@Mock
private
SessionManager
mockSessionManager
;
@Mock
private
SessionManager
mockSessionManager
;
@Mock
private
CastSession
mockCastSession
;
@Mock
private
CastSession
mockCastSession
;
@Mock
private
Player
.
EventListener
mockListener
;
@Mock
private
Player
.
EventListener
mockListener
;
@Mock
private
PendingResult
<
RemoteMediaClient
.
MediaChannelResult
>
mockPendingResult
;
@Mock
private
PendingResult
<
RemoteMediaClient
.
MediaChannelResult
>
mockPendingResult
;
@Mock
private
RemoteMediaClient
.
MediaChannelResult
mediaChannelResultMock
;
@Captor
@Captor
private
ArgumentCaptor
<
ResultCallback
<
RemoteMediaClient
.
MediaChannelResult
>>
private
ArgumentCaptor
<
ResultCallback
<
RemoteMediaClient
.
MediaChannelResult
>>
...
@@ -93,6 +97,8 @@ public class CastPlayerTest {
...
@@ -93,6 +97,8 @@ public class CastPlayerTest {
when
(
mockRemoteMediaClient
.
getMediaStatus
()).
thenReturn
(
mockMediaStatus
);
when
(
mockRemoteMediaClient
.
getMediaStatus
()).
thenReturn
(
mockMediaStatus
);
when
(
mockRemoteMediaClient
.
getMediaQueue
()).
thenReturn
(
mockMediaQueue
);
when
(
mockRemoteMediaClient
.
getMediaQueue
()).
thenReturn
(
mockMediaQueue
);
when
(
mockMediaQueue
.
getItemIds
()).
thenReturn
(
new
int
[
0
]);
when
(
mockMediaQueue
.
getItemIds
()).
thenReturn
(
new
int
[
0
]);
when
(
mockRemoteMediaClient
.
getCurrentItem
()).
thenReturn
(
mockMediaQueueItem
);
when
(
mediaChannelResultMock
.
getStatus
()).
thenReturn
(
Status
.
RESULT_SUCCESS
);
// Make the remote media client present the same default values as ExoPlayer:
// Make the remote media client present the same default values as ExoPlayer:
when
(
mockRemoteMediaClient
.
isPaused
()).
thenReturn
(
true
);
when
(
mockRemoteMediaClient
.
isPaused
()).
thenReturn
(
true
);
when
(
mockMediaStatus
.
getQueueRepeatMode
()).
thenReturn
(
MediaStatus
.
REPEAT_MODE_REPEAT_OFF
);
when
(
mockMediaStatus
.
getQueueRepeatMode
()).
thenReturn
(
MediaStatus
.
REPEAT_MODE_REPEAT_OFF
);
...
@@ -463,7 +469,8 @@ public class CastPlayerTest {
...
@@ -463,7 +469,8 @@ public class CastPlayerTest {
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem
);
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
)
verify
(
mockListener
)
.
onMediaItemTransition
(
.
onMediaItemTransition
(
...
@@ -478,10 +485,15 @@ public class CastPlayerTest {
...
@@ -478,10 +485,15 @@ public class CastPlayerTest {
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
clearMediaItemsAndUpdateTimeline
();
castPlayer
.
clearMediaItems
();
updateTimeLine
(
/* mediaItems= */
ImmutableList
.
of
(),
/* mediaQueueItemIds= */
new
int
[
0
],
/* currentItemId= */
C
.
INDEX_UNSET
);
verify
(
mockListener
)
verify
(
mockListener
)
.
onMediaItemTransition
(
.
onMediaItemTransition
(
/* mediaItem= */
null
,
Player
.
MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
);
/* mediaItem= */
null
,
Player
.
MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
);
...
@@ -495,11 +507,15 @@ public class CastPlayerTest {
...
@@ -495,11 +507,15 @@ public class CastPlayerTest {
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
);
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
removeMediaItemsAndUpdateTimeline
(
castPlayer
.
removeMediaItem
(
/* index= */
0
);
mediaItems
,
mediaQueueItemIds
,
/* fromIndex= */
0
,
/* toIndex= */
1
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem2
),
/* mediaQueueItemIds= */
new
int
[]
{
2
},
/* currentItemId= */
2
);
verify
(
mockListener
,
times
(
2
))
verify
(
mockListener
,
times
(
2
))
.
onMediaItemTransition
(
.
onMediaItemTransition
(
mediaItemCaptor
.
capture
(),
eq
(
Player
.
MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
));
mediaItemCaptor
.
capture
(),
eq
(
Player
.
MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
));
...
@@ -510,14 +526,20 @@ public class CastPlayerTest {
...
@@ -510,14 +526,20 @@ public class CastPlayerTest {
@Test
@Test
public
void
removeNonCurrentMediaItem_doesNotNotifyMediaItemTransition
()
{
public
void
removeNonCurrentMediaItem_doesNotNotifyMediaItemTransition
()
{
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
removeMediaItemsAndUpdateTimeline
(
castPlayer
.
removeMediaItem
(
/* index= */
1
);
mediaItems
,
mediaQueueItemIds
,
/* fromIndex= */
1
,
/* toIndex= */
2
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
),
/* mediaQueueItemIds= */
new
int
[]
{
1
},
/* currentItemId= */
1
);
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
}
}
...
@@ -530,7 +552,8 @@ public class CastPlayerTest {
...
@@ -530,7 +552,8 @@ public class CastPlayerTest {
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
);
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
castPlayer
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
castPlayer
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
...
@@ -549,7 +572,8 @@ public class CastPlayerTest {
...
@@ -549,7 +572,8 @@ public class CastPlayerTest {
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
mockListener
).
onMediaItemTransition
(
any
(),
anyInt
());
castPlayer
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
castPlayer
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
...
@@ -557,89 +581,232 @@ public class CastPlayerTest {
...
@@ -557,89 +581,232 @@ public class CastPlayerTest {
}
}
@Test
@Test
public
void
seekTo_
other
Window_notifiesAvailableCommandsChanged
()
{
public
void
seekTo_
next
Window_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
queueJumpToItem
(
anyInt
(),
anyLong
(),
eq
(
null
)))
when
(
mockRemoteMediaClient
.
queueJumpToItem
(
anyInt
(),
anyLong
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
.
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
new
Player
.
Commands
.
Builder
().
add
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
,
3
};
Player
.
Commands
commandsWithHasNextAndPrevious
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
,
3
,
4
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
castPlayer
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
castPlayer
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNextAndPrevious
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
castPlayer
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
castPlayer
.
seekTo
(
/* windowIndex= */
3
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
seekTo_previousWindow_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
queueJumpToItem
(
anyInt
(),
anyLong
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasNextAndPrevious
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
,
3
,
4
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
4
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
castPlayer
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
castPlayer
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNextAndPrevious
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
castPlayer
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
castPlayer
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
castPlayer
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
castPlayer
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
}
}
@Test
@Test
public
void
addMediaItems_whenLastPlaying_notifiesAvailableCommandsChanged
()
{
@SuppressWarnings
(
"deprecation"
)
// Mocks deprecated method used by the CastPlayer.
Player
.
Commands
commandsWithHasNext
=
public
void
seekTo_sameWindow_doesNotNotifyAvailableCommandsChanged
()
{
new
Player
.
Commands
.
Builder
().
add
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
(
);
when
(
mockRemoteMediaClient
.
seek
(
anyLong
())).
thenReturn
(
mockPendingResult
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
castPlayer
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
200
);
castPlayer
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
100
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
addMediaItem_atTheEnd_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
MediaItem
mediaItem3
=
createMediaItem
(
/* mediaQueueItemId= */
3
);
castPlayer
.
addMediaItem
(
mediaItem1
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
),
/* mediaQueueItemIds= */
new
int
[]
{
1
},
/* currentItemId= */
1
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
int
[]
mediaQueueItemIdsToAdd
=
new
int
[]
{
2
};
castPlayer
.
addMediaItem
(
mediaItem2
);
List
<
MediaItem
>
mediaItemsToAdd
=
createMediaItems
(
mediaQueueItemIdsToAdd
);
updateTimeLine
(
addMediaItemsAndUpdateTimeline
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
),
/* existingMediaItems= */
mediaItems
,
/* mediaQueueItemIds= */
new
int
[]
{
1
,
2
},
/* existingMediaQueueItemIds= */
mediaQueueItemIds
,
/* currentItemId= */
1
);
mediaItemsToAdd
,
mediaQueueItemIdsToAdd
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
mediaQueueItemIdsToAdd
=
new
int
[]
{
3
};
castPlayer
.
addMediaItem
(
mediaItem3
);
mediaItemsToAdd
=
createMediaItems
(
mediaQueueItemIdsToAdd
);
updateTimeLine
(
addMediaItemsAndUpdateTimeline
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
,
mediaItem3
),
/* existingMediaItems= */
mediaItems
,
/* mediaQueueItemIds= */
new
int
[]
{
1
,
2
,
3
},
/* existingMediaQueueItemIds= */
mediaQueueItemIds
,
/* currentItemId= */
1
);
mediaItemsToAdd
,
mediaQueueItemIdsToAdd
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
}
@Test
@Test
public
void
removeMediaItems_followingCurrent_notifiesAvailableCommandsChanged
()
{
public
void
addMediaItem_atTheStart_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
new
Player
.
Commands
.
Builder
().
add
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
MediaItem
mediaItem3
=
createMediaItem
(
/* mediaQueueItemId= */
3
);
MediaItem
mediaItem3
=
createMediaItem
(
/* mediaQueueItemId= */
3
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
,
2
,
3
};
List
<
MediaItem
>
mediaItems
=
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
,
mediaItem3
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItem
(
mediaItem1
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
),
/* mediaQueueItemIds= */
new
int
[]
{
1
},
/* currentItemId= */
1
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
castPlayer
.
addMediaItem
(
/* index= */
0
,
mediaItem2
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem2
,
mediaItem1
),
/* mediaQueueItemIds= */
new
int
[]
{
2
,
1
},
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
castPlayer
.
addMediaItem
(
/* index= */
0
,
mediaItem3
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem3
,
mediaItem2
,
mediaItem1
),
/* mediaQueueItemIds= */
new
int
[]
{
3
,
2
,
1
},
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
MediaItem
mediaItem3
=
createMediaItem
(
/* mediaQueueItemId= */
3
);
castPlayer
.
addMediaItems
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
,
mediaItem3
));
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
,
mediaItem3
),
/* mediaQueueItemIds= */
new
int
[]
{
1
,
2
,
3
},
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
removeMediaItemsAndUpdateTimeline
(
castPlayer
.
removeMediaItem
(
/* index= */
2
);
/* existingMediaItems= */
mediaItems
,
updateTimeLine
(
/* existingMediaQueueItemIds= */
mediaQueueItemIds
,
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
),
/* fromIndex= */
2
,
/* mediaQueueItemIds= */
new
int
[]
{
1
,
2
},
/* toIndex= */
3
);
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
castPlayer
.
removeMediaItem
(
/* index= */
1
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
),
/* mediaQueueItemIds= */
new
int
[]
{
1
},
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
castPlayer
.
removeMediaItem
(
/* index= */
0
);
updateTimeLine
(
ImmutableList
.
of
(),
/* mediaQueueItemIds= */
new
int
[
0
],
/* currentItemId= */
C
.
INDEX_UNSET
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItem_atTheStart_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
queueJumpToItem
(
anyInt
(),
anyLong
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
MediaItem
mediaItem3
=
createMediaItem
(
/* mediaQueueItemId= */
3
);
castPlayer
.
addMediaItems
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
,
mediaItem3
));
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
,
mediaItem3
),
/* mediaQueueItemIds= */
new
int
[]
{
1
,
2
,
3
},
/* currentItemId= */
3
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
castPlayer
.
removeMediaItem
(
/* index= */
0
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem2
,
mediaItem3
),
/* mediaQueueItemIds= */
new
int
[]
{
2
,
3
},
/* currentItemId= */
3
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
castPlayer
.
removeMediaItem
(
/* index= */
0
);
updateTimeLine
(
ImmutableList
.
of
(
mediaItem3
),
/* mediaQueueItemIds= */
new
int
[]
{
3
},
/* currentItemId= */
3
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
castPlayer
.
removeMediaItem
(
/* index= */
0
);
updateTimeLine
(
ImmutableList
.
of
(),
/* mediaQueueItemIds= */
new
int
[
0
],
/* currentItemId= */
C
.
INDEX_UNSET
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItem_current_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
MediaItem
mediaItem2
=
createMediaItem
(
/* mediaQueueItemId= */
2
);
castPlayer
.
addMediaItems
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
));
updateTimeLine
(
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
),
/* mediaQueueItemIds= */
new
int
[]
{
1
,
2
},
/* currentItemId= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
removeMediaItemsAndUpdateTimeline
(
castPlayer
.
removeMediaItem
(
/* index= */
0
);
/* existingMediaItems= */
ImmutableList
.
of
(
mediaItem1
,
mediaItem2
),
updateTimeLine
(
/* existingMediaQueueItemIds= */
new
int
[]
{
1
,
2
}
,
ImmutableList
.
of
(
mediaItem2
)
,
/*
fromIndex= */
1
,
/*
mediaQueueItemIds= */
new
int
[]
{
2
}
,
/*
toIndex
= */
2
);
/*
currentItemId
= */
2
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
}
...
@@ -648,16 +815,17 @@ public class CastPlayerTest {
...
@@ -648,16 +815,17 @@ public class CastPlayerTest {
public
void
setRepeatMode_all_notifiesAvailableCommandsChanged
()
{
public
void
setRepeatMode_all_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
queueSetRepeatMode
(
anyInt
(),
eq
(
null
)))
when
(
mockRemoteMediaClient
.
queueSetRepeatMode
(
anyInt
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
.
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
AndPrevious
=
new
Player
.
Commands
.
Builder
().
add
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
(
);
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
castPlayer
.
setRepeatMode
(
Player
.
REPEAT_MODE_ALL
);
castPlayer
.
setRepeatMode
(
Player
.
REPEAT_MODE_ALL
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
AndPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
}
...
@@ -668,7 +836,8 @@ public class CastPlayerTest {
...
@@ -668,7 +836,8 @@ public class CastPlayerTest {
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
List
<
MediaItem
>
mediaItems
=
createMediaItems
(
mediaQueueItemIds
);
addMediaItemsAndUpdateTimeline
(
mediaItems
,
mediaQueueItemIds
);
castPlayer
.
addMediaItems
(
mediaItems
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
castPlayer
.
setRepeatMode
(
Player
.
REPEAT_MODE_ONE
);
castPlayer
.
setRepeatMode
(
Player
.
REPEAT_MODE_ONE
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
}
}
...
@@ -698,66 +867,13 @@ public class CastPlayerTest {
...
@@ -698,66 +867,13 @@ public class CastPlayerTest {
}
}
private
void
addMediaItemsAndUpdateTimeline
(
List
<
MediaItem
>
mediaItems
,
int
[]
mediaQueueItemIds
)
{
private
void
addMediaItemsAndUpdateTimeline
(
List
<
MediaItem
>
mediaItems
,
int
[]
mediaQueueItemIds
)
{
addMediaItemsAndUpdateTimeline
(
Assertions
.
checkState
(
mediaItems
.
size
()
==
mediaQueueItemIds
.
length
);
/* existingMediaItems= */
ImmutableList
.
of
(),
castPlayer
.
addMediaItems
(
mediaItems
);
/* existingMediaQueueItemIds= */
new
int
[
0
],
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
,
/* currentItemId= */
1
);
/* mediaItemsToAdd= */
mediaItems
,
/* mediaQueueItemIdsToAdd= */
mediaQueueItemIds
);
}
private
void
addMediaItemsAndUpdateTimeline
(
List
<
MediaItem
>
existingMediaItems
,
int
[]
existingMediaQueueItemIds
,
List
<
MediaItem
>
mediaItemsToAdd
,
int
[]
mediaQueueItemIdsToAdd
)
{
Assertions
.
checkState
(
existingMediaItems
.
size
()
==
existingMediaQueueItemIds
.
length
);
Assertions
.
checkState
(
mediaItemsToAdd
.
size
()
==
mediaQueueItemIdsToAdd
.
length
);
List
<
MediaItem
>
mediaItems
=
new
ArrayList
<>();
mediaItems
.
addAll
(
existingMediaItems
);
mediaItems
.
addAll
(
mediaItemsToAdd
);
int
existingMediaItemCount
=
existingMediaQueueItemIds
.
length
;
int
mediaItemToAddCount
=
mediaQueueItemIdsToAdd
.
length
;
int
[]
mediaQueueItemIds
=
new
int
[
existingMediaItemCount
+
mediaItemToAddCount
];
System
.
arraycopy
(
existingMediaQueueItemIds
,
0
,
mediaQueueItemIds
,
0
,
existingMediaItemCount
);
System
.
arraycopy
(
mediaQueueItemIdsToAdd
,
0
,
mediaQueueItemIds
,
existingMediaItemCount
,
mediaItemToAddCount
);
castPlayer
.
addMediaItems
(
mediaItemsToAdd
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
);
}
private
void
removeMediaItemsAndUpdateTimeline
(
List
<
MediaItem
>
existingMediaItems
,
int
[]
existingMediaQueueItemIds
,
int
fromIndex
,
int
toIndex
)
{
Assertions
.
checkState
(
existingMediaItems
.
size
()
==
existingMediaQueueItemIds
.
length
);
Assertions
.
checkState
(
fromIndex
>=
0
);
Assertions
.
checkState
(
fromIndex
<
toIndex
);
int
existingMediaItemCount
=
existingMediaItems
.
size
();
Assertions
.
checkState
(
toIndex
<=
existingMediaItemCount
);
List
<
MediaItem
>
mediaItems
=
new
ArrayList
<>();
int
[]
mediaQueueItemIds
=
new
int
[
existingMediaItemCount
-
toIndex
+
fromIndex
];
for
(
int
i
=
0
;
i
<
existingMediaItemCount
;
i
++)
{
if
(
i
<
fromIndex
||
i
>=
toIndex
)
{
mediaItems
.
add
(
existingMediaItems
.
get
(
i
));
mediaQueueItemIds
[
mediaItems
.
size
()
-
1
]
=
existingMediaQueueItemIds
[
i
];
}
}
castPlayer
.
removeMediaItems
(
fromIndex
,
toIndex
);
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
);
}
private
void
clearMediaItemsAndUpdateTimeline
()
{
castPlayer
.
clearMediaItems
();
updateTimeLine
(
ImmutableList
.
of
(),
new
int
[
0
]);
}
}
private
void
updateTimeLine
(
List
<
MediaItem
>
mediaItems
,
int
[]
mediaQueueItemIds
)
{
private
void
updateTimeLine
(
List
<
MediaItem
>
mediaItems
,
int
[]
mediaQueueItemIds
,
int
currentItemId
)
{
List
<
MediaQueueItem
>
queueItems
=
new
ArrayList
<>();
List
<
MediaQueueItem
>
queueItems
=
new
ArrayList
<>();
DefaultMediaItemConverter
converter
=
new
DefaultMediaItemConverter
();
DefaultMediaItemConverter
converter
=
new
DefaultMediaItemConverter
();
for
(
MediaItem
mediaItem
:
mediaItems
)
{
for
(
MediaItem
mediaItem
:
mediaItems
)
{
...
@@ -766,7 +882,10 @@ public class CastPlayerTest {
...
@@ -766,7 +882,10 @@ public class CastPlayerTest {
// Set up mocks to allow the player to update the timeline.
// Set up mocks to allow the player to update the timeline.
when
(
mockMediaQueue
.
getItemIds
()).
thenReturn
(
mediaQueueItemIds
);
when
(
mockMediaQueue
.
getItemIds
()).
thenReturn
(
mediaQueueItemIds
);
when
(
mockMediaStatus
.
getCurrentItemId
()).
thenReturn
(
1
);
if
(
currentItemId
!=
C
.
INDEX_UNSET
)
{
when
(
mockMediaQueueItem
.
getItemId
()).
thenReturn
(
currentItemId
);
when
(
mockMediaStatus
.
getCurrentItemId
()).
thenReturn
(
currentItemId
);
}
when
(
mockMediaStatus
.
getMediaInfo
()).
thenReturn
(
mockMediaInfo
);
when
(
mockMediaStatus
.
getMediaInfo
()).
thenReturn
(
mockMediaInfo
);
when
(
mockMediaInfo
.
getStreamType
()).
thenReturn
(
MediaInfo
.
STREAM_TYPE_NONE
);
when
(
mockMediaInfo
.
getStreamType
()).
thenReturn
(
MediaInfo
.
STREAM_TYPE_NONE
);
when
(
mockMediaStatus
.
getQueueItems
()).
thenReturn
(
queueItems
);
when
(
mockMediaStatus
.
getQueueItems
()).
thenReturn
(
queueItems
);
...
@@ -774,4 +893,12 @@ public class CastPlayerTest {
...
@@ -774,4 +893,12 @@ public class CastPlayerTest {
// Call listener to update the timeline of the player.
// Call listener to update the timeline of the player.
remoteMediaClientCallback
.
onQueueStatusUpdated
();
remoteMediaClientCallback
.
onQueueStatusUpdated
();
}
}
private
static
Player
.
Commands
createCommands
(
@Player
.
Command
int
...
commands
)
{
Player
.
Commands
.
Builder
builder
=
new
Player
.
Commands
.
Builder
();
for
(
int
command
:
commands
)
{
builder
.
add
(
command
);
}
return
builder
.
build
();
}
}
}
extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java
View file @
851c915e
...
@@ -98,7 +98,10 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
...
@@ -98,7 +98,10 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
if
(!
timeline
.
isEmpty
()
&&
!
player
.
isPlayingAd
())
{
if
(!
timeline
.
isEmpty
()
&&
!
player
.
isPlayingAd
())
{
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
enableSkipTo
=
timeline
.
getWindowCount
()
>
1
;
enableSkipTo
=
timeline
.
getWindowCount
()
>
1
;
enablePrevious
=
window
.
isSeekable
||
!
window
.
isLive
()
||
player
.
hasPrevious
();
enablePrevious
=
window
.
isSeekable
||
!
window
.
isLive
()
||
player
.
isCommandAvailable
(
Player
.
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
enableNext
=
enableNext
=
(
window
.
isLive
()
&&
window
.
isDynamic
)
(
window
.
isLive
()
&&
window
.
isDynamic
)
||
player
.
isCommandAvailable
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
||
player
.
isCommandAvailable
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
...
...
library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java
View file @
851c915e
...
@@ -266,6 +266,9 @@ public abstract class BasePlayer implements Player {
...
@@ -266,6 +266,9 @@ public abstract class BasePlayer implements Player {
}
}
protected
Commands
getAvailableCommands
()
{
protected
Commands
getAvailableCommands
()
{
return
new
Commands
.
Builder
().
addIf
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
hasNext
()).
build
();
return
new
Commands
.
Builder
()
.
addIf
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
hasNext
())
.
addIf
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
,
hasPrevious
())
.
build
();
}
}
}
}
library/common/src/main/java/com/google/android/exoplayer2/Player.java
View file @
851c915e
...
@@ -1031,14 +1031,16 @@ public interface Player {
...
@@ -1031,14 +1031,16 @@ public interface Player {
/**
/**
* Commands that can be executed on a {@code Player}. One of {@link
* Commands that can be executed on a {@code Player}. One of {@link
* #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}.
* #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}
or {@link #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM}
.
*/
*/
@Documented
@Documented
@Retention
(
RetentionPolicy
.
SOURCE
)
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
})
@IntDef
({
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
})
@interface
Command
{}
@interface
Command
{}
/** Command to seek to the next {@link MediaItem} in the playlist. */
/** Command to seek to the next {@link MediaItem} in the playlist. */
int
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
=
0
;
int
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
=
0
;
/** Command to seek to the previous {@link MediaItem} in the playlist. */
int
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
=
1
;
/** Returns the component of this player for audio output, or null if audio is not supported. */
/** Returns the component of this player for audio output, or null if audio is not supported. */
@Nullable
@Nullable
...
...
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
View file @
851c915e
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
;
package
com
.
google
.
android
.
exoplayer2
;
import
static
com
.
google
.
android
.
exoplayer2
.
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
;
import
static
com
.
google
.
android
.
exoplayer2
.
Player
.
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
;
import
static
com
.
google
.
android
.
exoplayer2
.
robolectric
.
RobolectricUtil
.
runMainLooperUntil
;
import
static
com
.
google
.
android
.
exoplayer2
.
robolectric
.
RobolectricUtil
.
runMainLooperUntil
;
import
static
com
.
google
.
android
.
exoplayer2
.
robolectric
.
TestPlayerRunHelper
.
playUntilStartOfWindow
;
import
static
com
.
google
.
android
.
exoplayer2
.
robolectric
.
TestPlayerRunHelper
.
playUntilStartOfWindow
;
import
static
com
.
google
.
android
.
exoplayer2
.
robolectric
.
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
;
import
static
com
.
google
.
android
.
exoplayer2
.
robolectric
.
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
;
...
@@ -4593,7 +4595,7 @@ public final class ExoPlayerTest {
...
@@ -4593,7 +4595,7 @@ public final class ExoPlayerTest {
player
.
setHandleAudioBecomingNoisy
(
false
);
player
.
setHandleAudioBecomingNoisy
(
false
);
deliverBroadcast
(
new
Intent
(
AudioManager
.
ACTION_AUDIO_BECOMING_NOISY
));
deliverBroadcast
(
new
Intent
(
AudioManager
.
ACTION_AUDIO_BECOMING_NOISY
));
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
boolean
playWhenReadyAfterBroadcast
=
player
.
getPlayWhenReady
();
boolean
playWhenReadyAfterBroadcast
=
player
.
getPlayWhenReady
();
player
.
release
();
player
.
release
();
...
@@ -4607,7 +4609,7 @@ public final class ExoPlayerTest {
...
@@ -4607,7 +4609,7 @@ public final class ExoPlayerTest {
player
.
setHandleAudioBecomingNoisy
(
true
);
player
.
setHandleAudioBecomingNoisy
(
true
);
deliverBroadcast
(
new
Intent
(
AudioManager
.
ACTION_AUDIO_BECOMING_NOISY
));
deliverBroadcast
(
new
Intent
(
AudioManager
.
ACTION_AUDIO_BECOMING_NOISY
));
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
boolean
playWhenReadyAfterBroadcast
=
player
.
getPlayWhenReady
();
boolean
playWhenReadyAfterBroadcast
=
player
.
getPlayWhenReady
();
player
.
release
();
player
.
release
();
...
@@ -4734,7 +4736,7 @@ public final class ExoPlayerTest {
...
@@ -4734,7 +4736,7 @@ public final class ExoPlayerTest {
// Wait until the MediaSource is prepared, i.e. returned its timeline, and at least one
// Wait until the MediaSource is prepared, i.e. returned its timeline, and at least one
// iteration of doSomeWork after this was run.
// iteration of doSomeWork after this was run.
TestPlayerRunHelper
.
runUntilTimelineChanged
(
player
);
TestPlayerRunHelper
.
runUntilTimelineChanged
(
player
);
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
assertThat
(
player
.
getPlayerError
()).
isNull
();
assertThat
(
player
.
getPlayerError
()).
isNull
();
}
}
...
@@ -7593,7 +7595,7 @@ public final class ExoPlayerTest {
...
@@ -7593,7 +7595,7 @@ public final class ExoPlayerTest {
// Start playback and wait until player is idly waiting for an update of the first source.
// Start playback and wait until player is idly waiting for an update of the first source.
player
.
prepare
();
player
.
prepare
();
player
.
play
();
player
.
play
();
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
// Update media with a non-zero default start position and window offset.
// Update media with a non-zero default start position and window offset.
firstMediaSource
.
setNewSourceInfo
(
timelineWithOffsets
);
firstMediaSource
.
setNewSourceInfo
(
timelineWithOffsets
);
// Wait until player transitions to second source (which also has non-zero offsets).
// Wait until player transitions to second source (which also has non-zero offsets).
...
@@ -8069,57 +8071,118 @@ public final class ExoPlayerTest {
...
@@ -8069,57 +8071,118 @@ public final class ExoPlayerTest {
}
}
@Test
@Test
public
void
seekTo_otherWindow_notifiesAvailableCommandsChanged
()
{
public
void
seekTo_nextWindow_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasNextAndPrevious
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
player
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNextAndPrevious
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
3
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
seekTo_previousWindow_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasNextAndPrevious
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
seekTo
(
/* windowIndex= */
3
,
/* positionMs= */
0
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
player
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNextAndPrevious
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
player
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
player
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
}
}
@Test
@Test
public
void
seekTo_sameWindow_doesNotNotifyAvailableCommandsChanged
()
{
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
()));
player
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
200
);
player
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
100
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
automaticWindowTransition_notifiesAvailableCommandsChanged
()
throws
Exception
{
public
void
automaticWindowTransition_notifiesAvailableCommandsChanged
()
throws
Exception
{
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasNextAndPrevious
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
prepare
();
player
.
prepare
();
playUntilStartOfWindow
(
player
,
/* windowIndex= */
1
);
runUntilPendingCommandsAreFullyHandled
(
player
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNextAndPrevious
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
playUntilStartOfWindow
(
player
,
/* windowIndex= */
2
);
runUntilPendingCommandsAreFullyHandled
(
player
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
play
();
player
.
play
();
runUntilPlaybackState
(
player
,
Player
.
STATE_ENDED
);
runUntilPlaybackState
(
player
,
Player
.
STATE_ENDED
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
}
}
@Test
@Test
public
void
addMediaItems_whenLastPlaying_notifiesAvailableCommandsChanged
()
throws
Exception
{
public
void
addMediaSource_atTheEnd_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
...
@@ -8136,10 +8199,26 @@ public final class ExoPlayerTest {
...
@@ -8136,10 +8199,26 @@ public final class ExoPlayerTest {
}
}
@Test
@Test
public
void
removeMediaItems_followingCurrent_notifiesAvailableCommandsChanged
()
public
void
addMediaSource_atTheStart_notifiesAvailableCommandsChanged
()
{
throws
Exception
{
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
Commands
commandsWithHasNext
=
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSource
(
new
FakeMediaSource
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
player
.
addMediaSource
(
/* index= */
0
,
new
FakeMediaSource
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
addMediaSource
(
/* index= */
0
,
new
FakeMediaSource
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
...
@@ -8155,12 +8234,55 @@ public final class ExoPlayerTest {
...
@@ -8155,12 +8234,55 @@ public final class ExoPlayerTest {
player
.
removeMediaItem
(
/* index= */
1
);
player
.
removeMediaItem
(
/* index= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItem_atTheStart_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItem_current_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
}
@Test
@Test
public
void
setRepeatMode_all_notifiesAvailableCommandsChanged
()
throws
Exception
{
public
void
setRepeatMode_all_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
AndPrevious
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
(
);
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
...
@@ -8169,12 +8291,12 @@ public final class ExoPlayerTest {
...
@@ -8169,12 +8291,12 @@ public final class ExoPlayerTest {
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
player
.
setRepeatMode
(
Player
.
REPEAT_MODE_ALL
);
player
.
setRepeatMode
(
Player
.
REPEAT_MODE_ALL
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
AndPrevious
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
}
@Test
@Test
public
void
setRepeatMode_one_doesNotNotifyAvailableCommandsChanged
()
throws
Exception
{
public
void
setRepeatMode_one_doesNotNotifyAvailableCommandsChanged
()
{
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
...
@@ -8185,9 +8307,9 @@ public final class ExoPlayerTest {
...
@@ -8185,9 +8307,9 @@ public final class ExoPlayerTest {
}
}
@Test
@Test
public
void
setShuffleModeEnabled_notifiesAvailableCommandsChanged
()
throws
Exception
{
public
void
setShuffleModeEnabled_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
Player
.
Commands
commandsWithHasNext
=
createCommands
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
);
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
(
);
Player
.
Commands
commandsWithHasPrevious
=
createCommands
(
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addListener
(
mockListener
);
...
@@ -8202,7 +8324,7 @@ public final class ExoPlayerTest {
...
@@ -8202,7 +8324,7 @@ public final class ExoPlayerTest {
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
player
.
setShuffleModeEnabled
(
true
);
player
.
setShuffleModeEnabled
(
true
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasPrevious
);
}
}
@Test
@Test
...
@@ -9036,7 +9158,7 @@ public final class ExoPlayerTest {
...
@@ -9036,7 +9158,7 @@ public final class ExoPlayerTest {
player
.
setMediaSource
(
new
FakeMediaSource
(
new
FakeTimeline
(),
formatWithStaticMetadata
));
player
.
setMediaSource
(
new
FakeMediaSource
(
new
FakeTimeline
(),
formatWithStaticMetadata
));
player
.
seekTo
(
2_000
);
player
.
seekTo
(
2_000
);
player
.
setPlaybackParameters
(
new
PlaybackParameters
(
/* speed= */
2.0f
));
player
.
setPlaybackParameters
(
new
PlaybackParameters
(
/* speed= */
2.0f
));
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
verify
(
listener
).
onTimelineChanged
(
any
(),
anyInt
());
verify
(
listener
).
onTimelineChanged
(
any
(),
anyInt
());
verify
(
listener
).
onMediaItemTransition
(
any
(),
anyInt
());
verify
(
listener
).
onMediaItemTransition
(
any
(),
anyInt
());
...
@@ -9059,7 +9181,7 @@ public final class ExoPlayerTest {
...
@@ -9059,7 +9181,7 @@ public final class ExoPlayerTest {
}
}
});
});
player
.
setRepeatMode
(
Player
.
REPEAT_MODE_ONE
);
player
.
setRepeatMode
(
Player
.
REPEAT_MODE_ONE
);
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
verify
(
listener
).
onRepeatModeChanged
(
anyInt
());
verify
(
listener
).
onRepeatModeChanged
(
anyInt
());
verify
(
listener
).
onShuffleModeEnabledChanged
(
anyBoolean
());
verify
(
listener
).
onShuffleModeEnabledChanged
(
anyBoolean
());
...
@@ -9075,7 +9197,7 @@ public final class ExoPlayerTest {
...
@@ -9075,7 +9197,7 @@ public final class ExoPlayerTest {
player
.
play
();
player
.
play
();
player
.
setMediaItem
(
MediaItem
.
fromUri
(
"http://this-will-throw-an-exception.mp4"
));
player
.
setMediaItem
(
MediaItem
.
fromUri
(
"http://this-will-throw-an-exception.mp4"
));
TestPlayerRunHelper
.
runUntilPlaybackState
(
player
,
Player
.
STATE_IDLE
);
TestPlayerRunHelper
.
runUntilPlaybackState
(
player
,
Player
.
STATE_IDLE
);
TestPlayerRunHelper
.
runUntilPendingCommandsAreFullyHandled
(
player
);
runUntilPendingCommandsAreFullyHandled
(
player
);
player
.
release
();
player
.
release
();
// Verify that all callbacks have been called at least once.
// Verify that all callbacks have been called at least once.
...
@@ -9148,6 +9270,14 @@ public final class ExoPlayerTest {
...
@@ -9148,6 +9270,14 @@ public final class ExoPlayerTest {
return
false
;
return
false
;
}
}
private
static
Player
.
Commands
createCommands
(
@Player
.
Command
int
...
commands
)
{
Player
.
Commands
.
Builder
builder
=
new
Player
.
Commands
.
Builder
();
for
(
int
command
:
commands
)
{
builder
.
add
(
command
);
}
return
builder
.
build
();
}
// Internal classes.
// Internal classes.
/** {@link FakeRenderer} that can sleep and be woken-up. */
/** {@link FakeRenderer} that can sleep and be woken-up. */
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java
View file @
851c915e
...
@@ -913,7 +913,10 @@ public class PlayerControlView extends FrameLayout {
...
@@ -913,7 +913,10 @@ public class PlayerControlView extends FrameLayout {
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
boolean
isSeekable
=
window
.
isSeekable
;
boolean
isSeekable
=
window
.
isSeekable
;
enableSeeking
=
isSeekable
;
enableSeeking
=
isSeekable
;
enablePrevious
=
isSeekable
||
!
window
.
isLive
()
||
player
.
hasPrevious
();
enablePrevious
=
isSeekable
||
!
window
.
isLive
()
||
player
.
isCommandAvailable
(
Player
.
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
enableRewind
=
isSeekable
&&
controlDispatcher
.
isRewindEnabled
();
enableRewind
=
isSeekable
&&
controlDispatcher
.
isRewindEnabled
();
enableFastForward
=
isSeekable
&&
controlDispatcher
.
isFastForwardEnabled
();
enableFastForward
=
isSeekable
&&
controlDispatcher
.
isFastForwardEnabled
();
enableNext
=
enableNext
=
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java
View file @
851c915e
...
@@ -1460,7 +1460,10 @@ public class PlayerNotificationManager {
...
@@ -1460,7 +1460,10 @@ public class PlayerNotificationManager {
if
(!
timeline
.
isEmpty
()
&&
!
player
.
isPlayingAd
())
{
if
(!
timeline
.
isEmpty
()
&&
!
player
.
isPlayingAd
())
{
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
boolean
isSeekable
=
window
.
isSeekable
;
boolean
isSeekable
=
window
.
isSeekable
;
enablePrevious
=
isSeekable
||
!
window
.
isLive
()
||
player
.
hasPrevious
();
enablePrevious
=
isSeekable
||
!
window
.
isLive
()
||
player
.
isCommandAvailable
(
Player
.
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
enableRewind
=
isSeekable
&&
controlDispatcher
.
isRewindEnabled
();
enableRewind
=
isSeekable
&&
controlDispatcher
.
isRewindEnabled
();
enableFastForward
=
isSeekable
&&
controlDispatcher
.
isFastForwardEnabled
();
enableFastForward
=
isSeekable
&&
controlDispatcher
.
isFastForwardEnabled
();
enableNext
=
enableNext
=
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java
View file @
851c915e
...
@@ -1148,7 +1148,10 @@ public class StyledPlayerControlView extends FrameLayout {
...
@@ -1148,7 +1148,10 @@ public class StyledPlayerControlView extends FrameLayout {
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
timeline
.
getWindow
(
player
.
getCurrentWindowIndex
(),
window
);
boolean
isSeekable
=
window
.
isSeekable
;
boolean
isSeekable
=
window
.
isSeekable
;
enableSeeking
=
isSeekable
;
enableSeeking
=
isSeekable
;
enablePrevious
=
isSeekable
||
!
window
.
isLive
()
||
player
.
hasPrevious
();
enablePrevious
=
isSeekable
||
!
window
.
isLive
()
||
player
.
isCommandAvailable
(
Player
.
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
);
enableRewind
=
isSeekable
&&
controlDispatcher
.
isRewindEnabled
();
enableRewind
=
isSeekable
&&
controlDispatcher
.
isRewindEnabled
();
enableFastForward
=
isSeekable
&&
controlDispatcher
.
isFastForwardEnabled
();
enableFastForward
=
isSeekable
&&
controlDispatcher
.
isFastForwardEnabled
();
enableNext
=
enableNext
=
...
...
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