Add onSetMediaItems listener with access to start index and position
Added onSetMediaItems callback listener to allow the session to modify/set MediaItem list, starting index and position before call to Player.setMediaItem(s). Added conditional check in MediaSessionStub.setMediaItem methods to only call player.setMediaItem rather than setMediaItems if player does not support COMMAND_CHANGE_MEDIA_ITEMS PiperOrigin-RevId: 503427927
This commit is contained in:
parent
e690802e9e
commit
bb11e0286e
@ -52,6 +52,9 @@ Release notes
|
|||||||
* Add the media session as an argument of `getMediaButtons()` of the
|
* Add the media session as an argument of `getMediaButtons()` of the
|
||||||
`DefaultMediaNotificationProvider` and use immutable lists for clarity
|
`DefaultMediaNotificationProvider` and use immutable lists for clarity
|
||||||
([#216](https://github.com/androidx/media/issues/216)).
|
([#216](https://github.com/androidx/media/issues/216)).
|
||||||
|
* Add `onSetMediaItems` callback listener to provide means to modify/set
|
||||||
|
`MediaItem` list, starting index and position by session before setting
|
||||||
|
onto Player ([#156](https://github.com/androidx/media/issues/156)).
|
||||||
* Metadata:
|
* Metadata:
|
||||||
* Parse multiple null-separated values from ID3 frames, as permitted by
|
* Parse multiple null-separated values from ID3 frames, as permitted by
|
||||||
ID3 v2.4.
|
ID3 v2.4.
|
||||||
|
@ -59,6 +59,8 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.session.MediaLibraryService.LibraryParams;
|
import androidx.media3.session.MediaLibraryService.LibraryParams;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.primitives.Longs;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -1056,13 +1058,13 @@ public class MediaSession {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a controller requested to add new {@linkplain MediaItem media items} to the
|
* Called when a controller requested to add new {@linkplain MediaItem media items} to the
|
||||||
* playlist via one of the {@code Player.addMediaItem(s)} or {@code Player.setMediaItem(s)}
|
* playlist via one of the {@code Player.addMediaItem(s)} methods. Unless overriden, {@link
|
||||||
* methods.
|
* Callback#onSetMediaItems} will direct {@code Player.setMediaItem(s)} to this method as well.
|
||||||
*
|
*
|
||||||
* <p>This callback is also called when an app is using a legacy {@link
|
* <p>In addition, unless {@link Callback#onSetMediaItems} is overridden, this callback is also
|
||||||
* MediaControllerCompat.TransportControls} to prepare or play media (for instance when browsing
|
* called when an app is using a legacy {@link MediaControllerCompat.TransportControls} to
|
||||||
* the catalogue and then selecting an item for preparation from Android Auto that is using the
|
* prepare or play media (for instance when browsing the catalogue and then selecting an item
|
||||||
* legacy Media1 library).
|
* for preparation from Android Auto that is using the legacy Media1 library).
|
||||||
*
|
*
|
||||||
* <p>Note that the requested {@linkplain MediaItem media items} don't have a {@link
|
* <p>Note that the requested {@linkplain MediaItem media items} don't have a {@link
|
||||||
* MediaItem.LocalConfiguration} (for example, a URI) and need to be updated to make them
|
* MediaItem.LocalConfiguration} (for example, a URI) and need to be updated to make them
|
||||||
@ -1075,8 +1077,8 @@ public class MediaSession {
|
|||||||
* the {@link MediaItem media items} have been resolved, the session will call {@link
|
* the {@link MediaItem media items} have been resolved, the session will call {@link
|
||||||
* Player#setMediaItems} or {@link Player#addMediaItems} as requested.
|
* Player#setMediaItems} or {@link Player#addMediaItems} as requested.
|
||||||
*
|
*
|
||||||
* <p>Interoperability: This method will be called in response to the following {@link
|
* <p>Interoperability: This method will be called, unless {@link Callback#onSetMediaItems} is
|
||||||
* MediaControllerCompat} methods:
|
* overridden, in response to the following {@link MediaControllerCompat} methods:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link MediaControllerCompat.TransportControls#prepareFromUri prepareFromUri}
|
* <li>{@link MediaControllerCompat.TransportControls#prepareFromUri prepareFromUri}
|
||||||
@ -1104,6 +1106,156 @@ public class MediaSession {
|
|||||||
MediaSession mediaSession, ControllerInfo controller, List<MediaItem> mediaItems) {
|
MediaSession mediaSession, ControllerInfo controller, List<MediaItem> mediaItems) {
|
||||||
return Futures.immediateFailedFuture(new UnsupportedOperationException());
|
return Futures.immediateFailedFuture(new UnsupportedOperationException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a controller requested to set {@linkplain MediaItem media items} to the playlist
|
||||||
|
* via one of the {@code Player.setMediaItem(s)} methods. The default implementation calls
|
||||||
|
* {@link Callback#onAddMediaItems}. Override this method if you want to modify/set the starting
|
||||||
|
* index/position for the {@code Player.setMediaItem(s)} methods.
|
||||||
|
*
|
||||||
|
* <p>This callback is also called when an app is using a legacy {@link
|
||||||
|
* MediaControllerCompat.TransportControls} to prepare or play media (for instance when browsing
|
||||||
|
* the catalogue and then selecting an item for preparation from Android Auto that is using the
|
||||||
|
* legacy Media1 library).
|
||||||
|
*
|
||||||
|
* <p>Note that the requested {@linkplain MediaItem media items} in the
|
||||||
|
* MediaItemsWithStartPosition don't have a {@link MediaItem.LocalConfiguration} (for example, a
|
||||||
|
* URI) and need to be updated to make them playable by the underlying {@link Player}.
|
||||||
|
* Typically, this implementation should be able to identify the correct item by its {@link
|
||||||
|
* MediaItem#mediaId} and/or the {@link MediaItem#requestMetadata}.
|
||||||
|
*
|
||||||
|
* <p>Return a {@link ListenableFuture} with the resolved {@linkplain
|
||||||
|
* MediaItemsWithStartPosition media items and starting index and position}. You can also return
|
||||||
|
* the items directly by using Guava's {@link Futures#immediateFuture(Object)}. Once the {@link
|
||||||
|
* MediaItemsWithStartPosition} has been resolved, the session will call {@link
|
||||||
|
* Player#setMediaItems} as requested. If the resolved {@link
|
||||||
|
* MediaItemsWithStartPosition#startIndex startIndex} is {@link
|
||||||
|
* androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET} and {@link
|
||||||
|
* MediaItemsWithStartPosition#startPositionMs startPositionMs} is {@link
|
||||||
|
* androidx.media3.common.C#TIME_UNSET C.TIME_UNSET} then the session will call {@link
|
||||||
|
* Player#setMediaItem(MediaItem, boolean)} with {@code resetPosition} set to {@code true}.
|
||||||
|
*
|
||||||
|
* <p>Interoperability: This method will be called in response to the following {@link
|
||||||
|
* MediaControllerCompat} methods:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#prepareFromUri prepareFromUri}
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#playFromUri playFromUri}
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#prepareFromMediaId prepareFromMediaId}
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#playFromMediaId playFromMediaId}
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#prepareFromSearch prepareFromSearch}
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#playFromSearch playFromSearch}
|
||||||
|
* <li>{@link MediaControllerCompat.TransportControls#addQueueItem addQueueItem}
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* The values of {@link MediaItem#mediaId}, {@link MediaItem.RequestMetadata#mediaUri}, {@link
|
||||||
|
* MediaItem.RequestMetadata#searchQuery} and {@link MediaItem.RequestMetadata#extras} will be
|
||||||
|
* set to match the legacy method call. The session will call {@link Player#setMediaItems} or
|
||||||
|
* {@link Player#addMediaItems}, followed by {@link Player#prepare()} and {@link Player#play()}
|
||||||
|
* as appropriate once the {@link MediaItem} has been resolved.
|
||||||
|
*
|
||||||
|
* @param mediaSession The session for this event.
|
||||||
|
* @param controller The controller information.
|
||||||
|
* @param mediaItems The list of requested {@linkplain MediaItem media items}.
|
||||||
|
* @param startIndex The start index in the {@link MediaItem} list from which to start playing.
|
||||||
|
* If startIndex is {@link androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET} and
|
||||||
|
* startPositionMs is {@link androidx.media3.common.C#TIME_UNSET C.TIME_UNSET} then caller
|
||||||
|
* is requesting to set media items with default index and position.
|
||||||
|
* @param startPositionMs The starting position in the media item from where to start playing.
|
||||||
|
* If startIndex is {@link androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET} and
|
||||||
|
* startPositionMs is {@link androidx.media3.common.C#TIME_UNSET C.TIME_UNSET} then caller
|
||||||
|
* is requesting to set media items with default index and position.
|
||||||
|
* @return A {@link ListenableFuture} with a {@link MediaItemsWithStartPosition} containing a
|
||||||
|
* list of resolved {@linkplain MediaItem media items}, and a starting index and position
|
||||||
|
* that are playable by the underlying {@link Player}. If returned {@link
|
||||||
|
* MediaItemsWithStartPosition#startIndex} is {@link androidx.media3.common.C#INDEX_UNSET
|
||||||
|
* C.INDEX_UNSET} and {@link MediaItemsWithStartPosition#startPositionMs} is {@link
|
||||||
|
* androidx.media3.common.C#TIME_UNSET C.TIME_UNSET}, then {@linkplain
|
||||||
|
* Player#setMediaItems(List, boolean) Player#setMediaItems(List, true)} will be called to
|
||||||
|
* set media items with default index and position.
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
default ListenableFuture<MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
return Util.transformFutureAsync(
|
||||||
|
onAddMediaItems(mediaSession, controller, mediaItems),
|
||||||
|
(mediaItemList) ->
|
||||||
|
Futures.immediateFuture(
|
||||||
|
new MediaItemsWithStartPosition(mediaItemList, startIndex, startPositionMs)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Representation of list of media items and where to start playing */
|
||||||
|
@UnstableApi
|
||||||
|
public static final class MediaItemsWithStartPosition {
|
||||||
|
/** List of {@link MediaItem media items}. */
|
||||||
|
public final ImmutableList<MediaItem> mediaItems;
|
||||||
|
/**
|
||||||
|
* Index to start playing at in {@link MediaItem} list.
|
||||||
|
*
|
||||||
|
* <p>If startIndex is {@link androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET} and
|
||||||
|
* startPositionMs is {@link androidx.media3.common.C#TIME_UNSET C.TIME_UNSET} then the
|
||||||
|
* requested start is the default index and position. If only startIndex is {@link
|
||||||
|
* androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET}, then the requested start is the
|
||||||
|
* {@linkplain Player#getCurrentMediaItemIndex() current index} and {@linkplain
|
||||||
|
* Player#getContentPosition() position}.
|
||||||
|
*/
|
||||||
|
public final int startIndex;
|
||||||
|
/**
|
||||||
|
* Position to start playing from in starting media item.
|
||||||
|
*
|
||||||
|
* <p>If startIndex is {@link androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET} and
|
||||||
|
* startPositionMs is {@link androidx.media3.common.C#TIME_UNSET C.TIME_UNSET} then the
|
||||||
|
* requested start is the default start index that takes into account whether {@link
|
||||||
|
* Player#getShuffleModeEnabled() shuffling is enabled} and the {@linkplain
|
||||||
|
* Timeline.Window#defaultPositionUs} default position}. If only startIndex is {@link
|
||||||
|
* androidx.media3.common.C#INDEX_UNSET C.INDEX_UNSET}, then the requested start is the
|
||||||
|
* {@linkplain Player#getCurrentMediaItemIndex() current index} and {@linkplain
|
||||||
|
* Player#getContentPosition() position}.
|
||||||
|
*/
|
||||||
|
public final long startPositionMs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance.
|
||||||
|
*
|
||||||
|
* @param mediaItems List of {@link MediaItem media items}.
|
||||||
|
* @param startIndex Index to start playing at in {@link MediaItem} list.
|
||||||
|
* @param startPositionMs Position to start playing from in starting media item.
|
||||||
|
*/
|
||||||
|
public MediaItemsWithStartPosition(
|
||||||
|
List<MediaItem> mediaItems, int startIndex, long startPositionMs) {
|
||||||
|
this.mediaItems = ImmutableList.copyOf(mediaItems);
|
||||||
|
this.startIndex = startIndex;
|
||||||
|
this.startPositionMs = startPositionMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(obj instanceof MediaItemsWithStartPosition)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaItemsWithStartPosition other = (MediaItemsWithStartPosition) obj;
|
||||||
|
|
||||||
|
return mediaItems.equals(other.mediaItems)
|
||||||
|
&& Util.areEqual(startIndex, other.startIndex)
|
||||||
|
&& Util.areEqual(startPositionMs, other.startPositionMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = mediaItems.hashCode();
|
||||||
|
result = 31 * result + startIndex;
|
||||||
|
result = 31 * result + Longs.hashCode(startPositionMs);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +70,7 @@ import androidx.media3.common.util.Log;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.session.MediaSession.ControllerCb;
|
import androidx.media3.session.MediaSession.ControllerCb;
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo;
|
import androidx.media3.session.MediaSession.ControllerInfo;
|
||||||
|
import androidx.media3.session.MediaSession.MediaItemsWithStartPosition;
|
||||||
import androidx.media3.session.SequencedFutureManager.SequencedFuture;
|
import androidx.media3.session.SequencedFutureManager.SequencedFuture;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
@ -525,6 +526,13 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
|||||||
"onAddMediaItems must return a non-null future");
|
"onAddMediaItems must return a non-null future");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ListenableFuture<MediaItemsWithStartPosition> onSetMediaItemsOnHandler(
|
||||||
|
ControllerInfo controller, List<MediaItem> mediaItems, int startIndex, long startPositionMs) {
|
||||||
|
return checkNotNull(
|
||||||
|
callback.onSetMediaItems(instance, controller, mediaItems, startIndex, startPositionMs),
|
||||||
|
"onSetMediaItems must return a non-null future");
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isReleased() {
|
protected boolean isReleased() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
return closed;
|
return closed;
|
||||||
|
@ -85,6 +85,7 @@ import androidx.media3.common.util.Log;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.session.MediaSession.ControllerCb;
|
import androidx.media3.session.MediaSession.ControllerCb;
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo;
|
import androidx.media3.session.MediaSession.ControllerInfo;
|
||||||
|
import androidx.media3.session.MediaSession.MediaItemsWithStartPosition;
|
||||||
import androidx.media3.session.SessionCommand.CommandCode;
|
import androidx.media3.session.SessionCommand.CommandCode;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
@ -711,18 +712,26 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
dispatchSessionTaskWithPlayerCommand(
|
dispatchSessionTaskWithPlayerCommand(
|
||||||
COMMAND_SET_MEDIA_ITEM,
|
COMMAND_SET_MEDIA_ITEM,
|
||||||
controller -> {
|
controller -> {
|
||||||
ListenableFuture<List<MediaItem>> mediaItemsFuture =
|
ListenableFuture<MediaItemsWithStartPosition> mediaItemsFuture =
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, ImmutableList.of(mediaItem));
|
sessionImpl.onSetMediaItemsOnHandler(
|
||||||
|
controller, ImmutableList.of(mediaItem), C.INDEX_UNSET, C.TIME_UNSET);
|
||||||
Futures.addCallback(
|
Futures.addCallback(
|
||||||
mediaItemsFuture,
|
mediaItemsFuture,
|
||||||
new FutureCallback<List<MediaItem>>() {
|
new FutureCallback<MediaItemsWithStartPosition>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<MediaItem> mediaItems) {
|
public void onSuccess(MediaItemsWithStartPosition mediaItemsWithStartPosition) {
|
||||||
postOrRun(
|
postOrRun(
|
||||||
sessionImpl.getApplicationHandler(),
|
sessionImpl.getApplicationHandler(),
|
||||||
() -> {
|
() -> {
|
||||||
PlayerWrapper player = sessionImpl.getPlayerWrapper();
|
PlayerWrapper player = sessionImpl.getPlayerWrapper();
|
||||||
player.setMediaItems(mediaItems);
|
if (mediaItemsWithStartPosition.startIndex == C.INDEX_UNSET
|
||||||
|
&& mediaItemsWithStartPosition.startPositionMs == C.TIME_UNSET) {
|
||||||
|
MediaUtils.setMediaItemsWithDefaultStartIndexAndPosition(
|
||||||
|
player, mediaItemsWithStartPosition);
|
||||||
|
} else {
|
||||||
|
MediaUtils.setMediaItemsWithSpecifiedStartIndexAndPosition(
|
||||||
|
player, mediaItemsWithStartPosition);
|
||||||
|
}
|
||||||
@Player.State int playbackState = player.getPlaybackState();
|
@Player.State int playbackState = player.getPlaybackState();
|
||||||
if (playbackState == Player.STATE_IDLE) {
|
if (playbackState == Player.STATE_IDLE) {
|
||||||
player.prepareIfCommandAvailable();
|
player.prepareIfCommandAvailable();
|
||||||
|
@ -63,6 +63,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.core.util.ObjectsCompat;
|
import androidx.core.util.ObjectsCompat;
|
||||||
import androidx.media.MediaSessionManager;
|
import androidx.media.MediaSessionManager;
|
||||||
import androidx.media3.common.BundleListRetriever;
|
import androidx.media3.common.BundleListRetriever;
|
||||||
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MediaLibraryInfo;
|
import androidx.media3.common.MediaLibraryInfo;
|
||||||
import androidx.media3.common.MediaMetadata;
|
import androidx.media3.common.MediaMetadata;
|
||||||
@ -79,6 +80,7 @@ import androidx.media3.session.MediaLibraryService.LibraryParams;
|
|||||||
import androidx.media3.session.MediaLibraryService.MediaLibrarySession;
|
import androidx.media3.session.MediaLibraryService.MediaLibrarySession;
|
||||||
import androidx.media3.session.MediaSession.ControllerCb;
|
import androidx.media3.session.MediaSession.ControllerCb;
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo;
|
import androidx.media3.session.MediaSession.ControllerInfo;
|
||||||
|
import androidx.media3.session.MediaSession.MediaItemsWithStartPosition;
|
||||||
import androidx.media3.session.SessionCommand.CommandCode;
|
import androidx.media3.session.SessionCommand.CommandCode;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
@ -202,6 +204,30 @@ import java.util.concurrent.ExecutionException;
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <K extends MediaSessionImpl>
|
||||||
|
SessionTask<ListenableFuture<SessionResult>, K> handleMediaItemsWithStartPositionWhenReady(
|
||||||
|
SessionTask<ListenableFuture<MediaItemsWithStartPosition>, K> mediaItemsTask,
|
||||||
|
MediaItemsWithStartPositionPlayerTask mediaItemPlayerTask) {
|
||||||
|
return (sessionImpl, controller, sequenceNumber) -> {
|
||||||
|
if (sessionImpl.isReleased()) {
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new SessionResult(SessionResult.RESULT_ERROR_SESSION_DISCONNECTED));
|
||||||
|
}
|
||||||
|
return transformFutureAsync(
|
||||||
|
mediaItemsTask.run(sessionImpl, controller, sequenceNumber),
|
||||||
|
mediaItemsWithStartPosition ->
|
||||||
|
postOrRunWithCompletion(
|
||||||
|
sessionImpl.getApplicationHandler(),
|
||||||
|
() -> {
|
||||||
|
if (!sessionImpl.isReleased()) {
|
||||||
|
mediaItemPlayerTask.run(
|
||||||
|
sessionImpl.getPlayerWrapper(), controller, mediaItemsWithStartPosition);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new SessionResult(SessionResult.RESULT_SUCCESS)));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static void sendLibraryResult(
|
private static void sendLibraryResult(
|
||||||
ControllerInfo controller, int sequenceNumber, LibraryResult<?> result) {
|
ControllerInfo controller, int sequenceNumber, LibraryResult<?> result) {
|
||||||
try {
|
try {
|
||||||
@ -851,26 +877,8 @@ import java.util.concurrent.ExecutionException;
|
|||||||
@Override
|
@Override
|
||||||
public void setMediaItem(
|
public void setMediaItem(
|
||||||
@Nullable IMediaController caller, int sequenceNumber, @Nullable Bundle mediaItemBundle) {
|
@Nullable IMediaController caller, int sequenceNumber, @Nullable Bundle mediaItemBundle) {
|
||||||
if (caller == null || mediaItemBundle == null) {
|
setMediaItemWithResetPosition(
|
||||||
return;
|
caller, sequenceNumber, mediaItemBundle, /* resetPosition= */ true);
|
||||||
}
|
|
||||||
MediaItem mediaItem;
|
|
||||||
try {
|
|
||||||
mediaItem = MediaItem.CREATOR.fromBundle(mediaItemBundle);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
queueSessionTaskWithPlayerCommand(
|
|
||||||
caller,
|
|
||||||
sequenceNumber,
|
|
||||||
COMMAND_SET_MEDIA_ITEM,
|
|
||||||
sendSessionResultWhenReady(
|
|
||||||
handleMediaItemsWhenReady(
|
|
||||||
(sessionImpl, controller, sequenceNum) ->
|
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, ImmutableList.of(mediaItem)),
|
|
||||||
(playerWrapper, controller, mediaItems) ->
|
|
||||||
playerWrapper.setMediaItems(mediaItems))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -894,11 +902,35 @@ import java.util.concurrent.ExecutionException;
|
|||||||
sequenceNumber,
|
sequenceNumber,
|
||||||
COMMAND_SET_MEDIA_ITEM,
|
COMMAND_SET_MEDIA_ITEM,
|
||||||
sendSessionResultWhenReady(
|
sendSessionResultWhenReady(
|
||||||
handleMediaItemsWhenReady(
|
handleMediaItemsWithStartPositionWhenReady(
|
||||||
(sessionImpl, controller, sequenceNum) ->
|
(sessionImpl, controller, sequenceNum) ->
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, ImmutableList.of(mediaItem)),
|
sessionImpl.onSetMediaItemsOnHandler(
|
||||||
(player, controller, mediaItems) ->
|
controller,
|
||||||
player.setMediaItems(mediaItems, /* startIndex= */ 0, startPositionMs))));
|
ImmutableList.of(mediaItem),
|
||||||
|
/* startIndex= */ 0,
|
||||||
|
startPositionMs),
|
||||||
|
(player, controller, mediaItemsWithStartPosition) -> {
|
||||||
|
if (player.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)) {
|
||||||
|
if (mediaItemsWithStartPosition.startIndex == C.INDEX_UNSET
|
||||||
|
&& mediaItemsWithStartPosition.startPositionMs == C.TIME_UNSET) {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems, /* resetPosition= */ true);
|
||||||
|
} else {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems,
|
||||||
|
mediaItemsWithStartPosition.startIndex,
|
||||||
|
mediaItemsWithStartPosition.startPositionMs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mediaItemsWithStartPosition.mediaItems.isEmpty()) {
|
||||||
|
player.setMediaItem(
|
||||||
|
mediaItemsWithStartPosition.mediaItems.get(0),
|
||||||
|
mediaItemsWithStartPosition.startPositionMs);
|
||||||
|
} else {
|
||||||
|
player.clearMediaItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -922,11 +954,27 @@ import java.util.concurrent.ExecutionException;
|
|||||||
sequenceNumber,
|
sequenceNumber,
|
||||||
COMMAND_SET_MEDIA_ITEM,
|
COMMAND_SET_MEDIA_ITEM,
|
||||||
sendSessionResultWhenReady(
|
sendSessionResultWhenReady(
|
||||||
handleMediaItemsWhenReady(
|
handleMediaItemsWithStartPositionWhenReady(
|
||||||
(sessionImpl, controller, sequenceNum) ->
|
(sessionImpl, controller, sequenceNum) ->
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, ImmutableList.of(mediaItem)),
|
sessionImpl.onSetMediaItemsOnHandler(
|
||||||
(player, controller, mediaItems) ->
|
controller,
|
||||||
player.setMediaItems(mediaItems, resetPosition))));
|
ImmutableList.of(mediaItem),
|
||||||
|
resetPosition
|
||||||
|
? C.INDEX_UNSET
|
||||||
|
: sessionImpl.getPlayerWrapper().getCurrentMediaItemIndex(),
|
||||||
|
resetPosition
|
||||||
|
? C.TIME_UNSET
|
||||||
|
: sessionImpl.getPlayerWrapper().getCurrentPosition()),
|
||||||
|
(player, controller, mediaItemsWithStartPosition) -> {
|
||||||
|
if (mediaItemsWithStartPosition.startIndex == C.INDEX_UNSET
|
||||||
|
&& mediaItemsWithStartPosition.startPositionMs == C.TIME_UNSET) {
|
||||||
|
MediaUtils.setMediaItemsWithDefaultStartIndexAndPosition(
|
||||||
|
player, mediaItemsWithStartPosition);
|
||||||
|
} else {
|
||||||
|
MediaUtils.setMediaItemsWithSpecifiedStartIndexAndPosition(
|
||||||
|
player, mediaItemsWithStartPosition);
|
||||||
|
}
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -934,29 +982,8 @@ import java.util.concurrent.ExecutionException;
|
|||||||
@Nullable IMediaController caller,
|
@Nullable IMediaController caller,
|
||||||
int sequenceNumber,
|
int sequenceNumber,
|
||||||
@Nullable IBinder mediaItemsRetriever) {
|
@Nullable IBinder mediaItemsRetriever) {
|
||||||
if (caller == null || mediaItemsRetriever == null) {
|
setMediaItemsWithResetPosition(
|
||||||
return;
|
caller, sequenceNumber, mediaItemsRetriever, /* resetPosition= */ true);
|
||||||
}
|
|
||||||
List<MediaItem> mediaItemList;
|
|
||||||
try {
|
|
||||||
mediaItemList =
|
|
||||||
BundleableUtil.fromBundleList(
|
|
||||||
MediaItem.CREATOR, BundleListRetriever.getList(mediaItemsRetriever));
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queueSessionTaskWithPlayerCommand(
|
|
||||||
caller,
|
|
||||||
sequenceNumber,
|
|
||||||
COMMAND_CHANGE_MEDIA_ITEMS,
|
|
||||||
sendSessionResultWhenReady(
|
|
||||||
handleMediaItemsWhenReady(
|
|
||||||
(sessionImpl, controller, sequenceNum) ->
|
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, mediaItemList),
|
|
||||||
(playerWrapper, controller, mediaItems) ->
|
|
||||||
playerWrapper.setMediaItems(mediaItems))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -982,11 +1009,29 @@ import java.util.concurrent.ExecutionException;
|
|||||||
sequenceNumber,
|
sequenceNumber,
|
||||||
COMMAND_CHANGE_MEDIA_ITEMS,
|
COMMAND_CHANGE_MEDIA_ITEMS,
|
||||||
sendSessionResultWhenReady(
|
sendSessionResultWhenReady(
|
||||||
handleMediaItemsWhenReady(
|
handleMediaItemsWithStartPositionWhenReady(
|
||||||
(sessionImpl, controller, sequenceNum) ->
|
(sessionImpl, controller, sequenceNum) ->
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, mediaItemList),
|
sessionImpl.onSetMediaItemsOnHandler(
|
||||||
(player, controller, mediaItems) ->
|
controller,
|
||||||
player.setMediaItems(mediaItems, resetPosition))));
|
mediaItemList,
|
||||||
|
resetPosition
|
||||||
|
? C.INDEX_UNSET
|
||||||
|
: sessionImpl.getPlayerWrapper().getCurrentMediaItemIndex(),
|
||||||
|
resetPosition
|
||||||
|
? C.TIME_UNSET
|
||||||
|
: sessionImpl.getPlayerWrapper().getCurrentPosition()),
|
||||||
|
(player, controller, mediaItemsWithStartPosition) -> {
|
||||||
|
if (mediaItemsWithStartPosition.startIndex == C.INDEX_UNSET
|
||||||
|
&& mediaItemsWithStartPosition.startPositionMs == C.TIME_UNSET) {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems, /* resetPosition= */ true);
|
||||||
|
} else {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems,
|
||||||
|
mediaItemsWithStartPosition.startIndex,
|
||||||
|
mediaItemsWithStartPosition.startPositionMs);
|
||||||
|
}
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1013,11 +1058,29 @@ import java.util.concurrent.ExecutionException;
|
|||||||
sequenceNumber,
|
sequenceNumber,
|
||||||
COMMAND_CHANGE_MEDIA_ITEMS,
|
COMMAND_CHANGE_MEDIA_ITEMS,
|
||||||
sendSessionResultWhenReady(
|
sendSessionResultWhenReady(
|
||||||
handleMediaItemsWhenReady(
|
handleMediaItemsWithStartPositionWhenReady(
|
||||||
(sessionImpl, controller, sequenceNum) ->
|
(sessionImpl, controller, sequenceNum) ->
|
||||||
sessionImpl.onAddMediaItemsOnHandler(controller, mediaItemList),
|
sessionImpl.onSetMediaItemsOnHandler(
|
||||||
(player, controller, mediaItems) ->
|
controller,
|
||||||
player.setMediaItems(mediaItems, startIndex, startPositionMs))));
|
mediaItemList,
|
||||||
|
(startIndex == C.INDEX_UNSET)
|
||||||
|
? sessionImpl.getPlayerWrapper().getCurrentMediaItemIndex()
|
||||||
|
: startIndex,
|
||||||
|
(startIndex == C.INDEX_UNSET)
|
||||||
|
? sessionImpl.getPlayerWrapper().getCurrentPosition()
|
||||||
|
: startPositionMs),
|
||||||
|
(player, controller, mediaItemsWithStartPosition) -> {
|
||||||
|
if (mediaItemsWithStartPosition.startIndex == C.INDEX_UNSET
|
||||||
|
&& mediaItemsWithStartPosition.startPositionMs == C.TIME_UNSET) {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems, /* resetPosition= */ true);
|
||||||
|
} else {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems,
|
||||||
|
mediaItemsWithStartPosition.startIndex,
|
||||||
|
mediaItemsWithStartPosition.startPositionMs);
|
||||||
|
}
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1624,6 +1687,13 @@ import java.util.concurrent.ExecutionException;
|
|||||||
void run(PlayerWrapper player, ControllerInfo controller);
|
void run(PlayerWrapper player, ControllerInfo controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface MediaItemsWithStartPositionPlayerTask {
|
||||||
|
void run(
|
||||||
|
PlayerWrapper player,
|
||||||
|
ControllerInfo controller,
|
||||||
|
MediaItemsWithStartPosition mediaItemsWithStartPosition);
|
||||||
|
}
|
||||||
|
|
||||||
/* package */ static final class Controller2Cb implements ControllerCb {
|
/* package */ static final class Controller2Cb implements ControllerCb {
|
||||||
|
|
||||||
private final IMediaController iController;
|
private final IMediaController iController;
|
||||||
|
@ -1368,5 +1368,32 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
: Util.constrainValue((int) ((bufferedPositionMs * 100) / durationMs), 0, 100);
|
: Util.constrainValue((int) ((bufferedPositionMs * 100) / durationMs), 0, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setMediaItemsWithDefaultStartIndexAndPosition(
|
||||||
|
PlayerWrapper player, MediaSession.MediaItemsWithStartPosition mediaItemsWithStartPosition) {
|
||||||
|
if (player.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)) {
|
||||||
|
player.setMediaItems(mediaItemsWithStartPosition.mediaItems, /* resetPosition= */ true);
|
||||||
|
} else if (!mediaItemsWithStartPosition.mediaItems.isEmpty()) {
|
||||||
|
player.setMediaItem(mediaItemsWithStartPosition.mediaItems.get(0), /* resetPosition= */ true);
|
||||||
|
} else {
|
||||||
|
player.clearMediaItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMediaItemsWithSpecifiedStartIndexAndPosition(
|
||||||
|
PlayerWrapper player, MediaSession.MediaItemsWithStartPosition mediaItemsWithStartPosition) {
|
||||||
|
if (player.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)) {
|
||||||
|
player.setMediaItems(
|
||||||
|
mediaItemsWithStartPosition.mediaItems,
|
||||||
|
mediaItemsWithStartPosition.startIndex,
|
||||||
|
mediaItemsWithStartPosition.startPositionMs);
|
||||||
|
} else if (!mediaItemsWithStartPosition.mediaItems.isEmpty()) {
|
||||||
|
player.setMediaItem(
|
||||||
|
mediaItemsWithStartPosition.mediaItems.get(0),
|
||||||
|
mediaItemsWithStartPosition.startPositionMs);
|
||||||
|
} else {
|
||||||
|
player.clearMediaItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private MediaUtils() {}
|
private MediaUtils() {}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MediaLibraryInfo;
|
import androidx.media3.common.MediaLibraryInfo;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
@ -368,14 +369,14 @@ public class MediaSessionCallbackTest {
|
|||||||
controllerTestRule.createRemoteController(session.getToken());
|
controllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
controller.setMediaItem(mediaItem);
|
controller.setMediaItem(mediaItem);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(requestedMediaItems.get()).containsExactly(mediaItem);
|
assertThat(requestedMediaItems.get()).containsExactly(mediaItem);
|
||||||
assertThat(player.mediaItems).containsExactly(updateMediaItemWithLocalConfiguration(mediaItem));
|
assertThat(player.mediaItems).containsExactly(updateMediaItemWithLocalConfiguration(mediaItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onAddMediaItems_withSetMediaItemWithIndex() throws Exception {
|
public void onAddMediaItems_withSetMediaItemWithStartPosition() throws Exception {
|
||||||
MediaItem mediaItem = createMediaItem("mediaId");
|
MediaItem mediaItem = createMediaItem("mediaId");
|
||||||
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
MediaSession.Callback callback =
|
MediaSession.Callback callback =
|
||||||
@ -452,7 +453,7 @@ public class MediaSessionCallbackTest {
|
|||||||
controllerTestRule.createRemoteController(session.getToken());
|
controllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
controller.setMediaItems(mediaItems);
|
controller.setMediaItems(mediaItems);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(requestedMediaItems.get()).containsExactlyElementsIn(mediaItems).inOrder();
|
assertThat(requestedMediaItems.get()).containsExactlyElementsIn(mediaItems).inOrder();
|
||||||
assertThat(player.mediaItems)
|
assertThat(player.mediaItems)
|
||||||
@ -461,7 +462,7 @@ public class MediaSessionCallbackTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onAddMediaItems_withSetMediaItemsWithStartPosition() throws Exception {
|
public void onAddMediaItems_withSetMediaItemsWithStartIndex() throws Exception {
|
||||||
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
MediaSession.Callback callback =
|
MediaSession.Callback callback =
|
||||||
@ -645,6 +646,170 @@ public class MediaSessionCallbackTest {
|
|||||||
assertThat(player.index).isEqualTo(1);
|
assertThat(player.index).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSetMediaItems_withSetMediaItemWithStartPosition_callsPlayerWithStartIndex()
|
||||||
|
throws Exception {
|
||||||
|
MediaItem mediaItem = createMediaItem("mediaId");
|
||||||
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
requestedMediaItems.set(mediaItems);
|
||||||
|
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
updateMediaItemsWithLocalConfiguration(mediaItems),
|
||||||
|
startIndex,
|
||||||
|
/* startPosition = testStartPosition * 2 */ 200));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player).setCallback(callback).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
controllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
|
controller.setMediaItem(mediaItem, /* startPositionMs= */ 100);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(requestedMediaItems.get()).containsExactly(mediaItem);
|
||||||
|
assertThat(player.mediaItems).containsExactly(updateMediaItemWithLocalConfiguration(mediaItem));
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(0);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSetMediaItems_withSetMediaItemsWithStartIndex_callsPlayerWithStartIndex()
|
||||||
|
throws Exception {
|
||||||
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
requestedMediaItems.set(mediaItems);
|
||||||
|
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
updateMediaItemsWithLocalConfiguration(mediaItems),
|
||||||
|
startIndex,
|
||||||
|
/* startPosition= */ 200));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player).setCallback(callback).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
controllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
|
controller.setMediaItems(mediaItems, /* startWindowIndex= */ 1, /* startPositionMs= */ 100);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(requestedMediaItems.get()).containsExactlyElementsIn(mediaItems).inOrder();
|
||||||
|
assertThat(player.mediaItems)
|
||||||
|
.containsExactlyElementsIn(updateMediaItemsWithLocalConfiguration(mediaItems))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(1);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSetMediaItems_withIndexPositionUnset_callsPlayerWithResetPosition()
|
||||||
|
throws Exception {
|
||||||
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
requestedMediaItems.set(mediaItems);
|
||||||
|
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
updateMediaItemsWithLocalConfiguration(mediaItems),
|
||||||
|
C.INDEX_UNSET,
|
||||||
|
C.TIME_UNSET));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player).setCallback(callback).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
controllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
|
controller.setMediaItems(mediaItems, /* startWindowIndex= */ 1, /* startPositionMs= */ 100);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(requestedMediaItems.get()).containsExactlyElementsIn(mediaItems).inOrder();
|
||||||
|
assertThat(player.mediaItems)
|
||||||
|
.containsExactlyElementsIn(updateMediaItemsWithLocalConfiguration(mediaItems))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(player.resetPosition).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSetMediaItems_withStartIndexUnset_callsPlayerWithCurrentIndexAndPosition()
|
||||||
|
throws Exception {
|
||||||
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
requestedMediaItems.set(mediaItems);
|
||||||
|
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
updateMediaItemsWithLocalConfiguration(mediaItems),
|
||||||
|
startIndex,
|
||||||
|
startPositionMs));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player).setCallback(callback).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
controllerTestRule.createRemoteController(session.getToken());
|
||||||
|
controller.setMediaItems(mediaItems, true);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
|
|
||||||
|
// Model that player played to next item. Current media item index and position have changed
|
||||||
|
player.currentMediaItemIndex = 1;
|
||||||
|
player.currentPosition = 200;
|
||||||
|
|
||||||
|
// Re-set media items with start index and position as current index and position
|
||||||
|
controller.setMediaItems(mediaItems, C.INDEX_UNSET, /* startPosition= */ 0);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(requestedMediaItems.get()).containsExactlyElementsIn(mediaItems).inOrder();
|
||||||
|
assertThat(player.mediaItems)
|
||||||
|
.containsExactlyElementsIn(updateMediaItemsWithLocalConfiguration(mediaItems))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(1);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(200);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onConnect() throws Exception {
|
public void onConnect() throws Exception {
|
||||||
AtomicReference<Bundle> connectionHints = new AtomicReference<>();
|
AtomicReference<Bundle> connectionHints = new AtomicReference<>();
|
||||||
|
@ -961,7 +961,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void prepareFromMediaUri() throws Exception {
|
public void prepareFromMediaUri_withOnAddMediaItems() throws Exception {
|
||||||
Uri mediaUri = Uri.parse("foo://bar");
|
Uri mediaUri = Uri.parse("foo://bar");
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("key", "value");
|
bundle.putString("key", "value");
|
||||||
@ -988,7 +988,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().prepareFromUri(mediaUri, bundle);
|
controller.getTransportControls().prepareFromUri(mediaUri, bundle);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
assertThat(requestedMediaItems.get().get(0).requestMetadata.mediaUri).isEqualTo(mediaUri);
|
assertThat(requestedMediaItems.get().get(0).requestMetadata.mediaUri).isEqualTo(mediaUri);
|
||||||
@ -997,7 +997,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void playFromMediaUri() throws Exception {
|
public void playFromMediaUri_withOnAddMediaItems() throws Exception {
|
||||||
Uri request = Uri.parse("foo://bar");
|
Uri request = Uri.parse("foo://bar");
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("key", "value");
|
bundle.putString("key", "value");
|
||||||
@ -1024,7 +1024,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().playFromUri(request, bundle);
|
controller.getTransportControls().playFromUri(request, bundle);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
@ -1034,7 +1034,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void prepareFromMediaId() throws Exception {
|
public void prepareFromMediaId_withOnAddMediaItems() throws Exception {
|
||||||
String request = "media_id";
|
String request = "media_id";
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("key", "value");
|
bundle.putString("key", "value");
|
||||||
@ -1061,7 +1061,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().prepareFromMediaId(request, bundle);
|
controller.getTransportControls().prepareFromMediaId(request, bundle);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(request);
|
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(request);
|
||||||
@ -1070,7 +1070,53 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void playFromMediaId() throws Exception {
|
public void prepareFromMediaId_withOnSetMediaItems_callsPlayerWithStartIndex() throws Exception {
|
||||||
|
String request = "media_id";
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("key", "value");
|
||||||
|
AtomicReference<List<MediaItem>> requestedMediaItems = new AtomicReference<>();
|
||||||
|
MediaItem resolvedMediaItem = MediaItem.fromUri(TEST_URI);
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
requestedMediaItems.set(mediaItems);
|
||||||
|
return executorService.submit(
|
||||||
|
() ->
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
ImmutableList.of(resolvedMediaItem),
|
||||||
|
/* startIndex= */ 2,
|
||||||
|
/* startPositionMs= */ 100));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
session =
|
||||||
|
new MediaSession.Builder(context, player)
|
||||||
|
.setId("prepareFromMediaId")
|
||||||
|
.setCallback(callback)
|
||||||
|
.build();
|
||||||
|
controller =
|
||||||
|
new RemoteMediaControllerCompat(
|
||||||
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
|
controller.getTransportControls().prepareFromMediaId(request, bundle);
|
||||||
|
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, TIMEOUT_MS);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
|
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(request);
|
||||||
|
TestUtils.equals(requestedMediaItems.get().get(0).requestMetadata.extras, bundle);
|
||||||
|
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(2);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playFromMediaId_withOnAddMediaItems() throws Exception {
|
||||||
String mediaId = "media_id";
|
String mediaId = "media_id";
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("key", "value");
|
bundle.putString("key", "value");
|
||||||
@ -1097,7 +1143,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().playFromMediaId(mediaId, bundle);
|
controller.getTransportControls().playFromMediaId(mediaId, bundle);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
@ -1107,7 +1153,49 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void prepareFromSearch() throws Exception {
|
public void playFromMediaId_withOnSetMediaItems_callsPlayerWithStartIndex() throws Exception {
|
||||||
|
String mediaId = "media_id";
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("key", "value");
|
||||||
|
MediaItem resolvedMediaItem = MediaItem.fromUri(TEST_URI);
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onSetMediaItems(
|
||||||
|
MediaSession mediaSession,
|
||||||
|
ControllerInfo controller,
|
||||||
|
List<MediaItem> mediaItems,
|
||||||
|
int startIndex,
|
||||||
|
long startPositionMs) {
|
||||||
|
return executorService.submit(
|
||||||
|
() ->
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
ImmutableList.of(resolvedMediaItem),
|
||||||
|
/* startIndex= */ 2,
|
||||||
|
/* startPositionMs= */ 100));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
session =
|
||||||
|
new MediaSession.Builder(context, player)
|
||||||
|
.setId("playFromMediaId")
|
||||||
|
.setCallback(callback)
|
||||||
|
.build();
|
||||||
|
controller =
|
||||||
|
new RemoteMediaControllerCompat(
|
||||||
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
|
controller.getTransportControls().playFromMediaId(mediaId, bundle);
|
||||||
|
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, TIMEOUT_MS);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(2);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void prepareFromSearch_withOnAddMediaItems() throws Exception {
|
||||||
String query = "test_query";
|
String query = "test_query";
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("key", "value");
|
bundle.putString("key", "value");
|
||||||
@ -1134,7 +1222,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().prepareFromSearch(query, bundle);
|
controller.getTransportControls().prepareFromSearch(query, bundle);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
assertThat(requestedMediaItems.get().get(0).requestMetadata.searchQuery).isEqualTo(query);
|
assertThat(requestedMediaItems.get().get(0).requestMetadata.searchQuery).isEqualTo(query);
|
||||||
@ -1143,7 +1231,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void playFromSearch() throws Exception {
|
public void playFromSearch_withOnAddMediaItems() throws Exception {
|
||||||
String query = "test_query";
|
String query = "test_query";
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("key", "value");
|
bundle.putString("key", "value");
|
||||||
@ -1170,7 +1258,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().playFromSearch(query, bundle);
|
controller.getTransportControls().playFromSearch(query, bundle);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
@ -1204,7 +1292,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().prepareFromUri(Uri.parse("foo://bar"), Bundle.EMPTY);
|
controller.getTransportControls().prepareFromUri(Uri.parse("foo://bar"), Bundle.EMPTY);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
||||||
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
||||||
}
|
}
|
||||||
@ -1234,7 +1322,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().playFromUri(Uri.parse("foo://bar"), Bundle.EMPTY);
|
controller.getTransportControls().playFromUri(Uri.parse("foo://bar"), Bundle.EMPTY);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
||||||
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
||||||
@ -1268,7 +1356,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
controller.getTransportControls().playFromUri(Uri.parse("foo://bar"), Bundle.EMPTY);
|
controller.getTransportControls().playFromUri(Uri.parse("foo://bar"), Bundle.EMPTY);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isFalse();
|
||||||
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
assertThat(player.mediaItems).containsExactly(resolvedMediaItem);
|
||||||
|
@ -300,7 +300,7 @@ public class MediaSessionPlayerTest {
|
|||||||
|
|
||||||
controller.setMediaItem(item);
|
controller.setMediaItem(item);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.mediaItems).containsExactly(item);
|
assertThat(player.mediaItems).containsExactly(item);
|
||||||
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
|
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
|
||||||
assertThat(player.resetPosition).isEqualTo(resetPosition);
|
assertThat(player.resetPosition).isEqualTo(resetPosition);
|
||||||
@ -316,7 +316,7 @@ public class MediaSessionPlayerTest {
|
|||||||
|
|
||||||
controller.setMediaItem(item);
|
controller.setMediaItem(item);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.mediaItems).containsExactly(item);
|
assertThat(player.mediaItems).containsExactly(item);
|
||||||
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
|
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
|
||||||
assertThat(player.resetPosition).isEqualTo(resetPosition);
|
assertThat(player.resetPosition).isEqualTo(resetPosition);
|
||||||
@ -332,7 +332,7 @@ public class MediaSessionPlayerTest {
|
|||||||
|
|
||||||
controller.setMediaItem(item);
|
controller.setMediaItem(item);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.mediaItems).containsExactly(item);
|
assertThat(player.mediaItems).containsExactly(item);
|
||||||
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
|
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
|
||||||
assertThat(player.resetPosition).isEqualTo(resetPosition);
|
assertThat(player.resetPosition).isEqualTo(resetPosition);
|
||||||
@ -344,9 +344,9 @@ public class MediaSessionPlayerTest {
|
|||||||
|
|
||||||
controller.setMediaItems(items);
|
controller.setMediaItems(items);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.mediaItems).isEqualTo(items);
|
assertThat(player.mediaItems).isEqualTo(items);
|
||||||
assertThat(player.resetPosition).isFalse();
|
assertThat(player.resetPosition).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -382,7 +382,7 @@ public class MediaSessionPlayerTest {
|
|||||||
|
|
||||||
controller.setMediaItems(list);
|
controller.setMediaItems(list);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.mediaItems.size()).isEqualTo(listSize);
|
assertThat(player.mediaItems.size()).isEqualTo(listSize);
|
||||||
for (int i = 0; i < listSize; i++) {
|
for (int i = 0; i < listSize; i++) {
|
||||||
assertThat(player.mediaItems.get(i).mediaId).isEqualTo(list.get(i).mediaId);
|
assertThat(player.mediaItems.get(i).mediaId).isEqualTo(list.get(i).mediaId);
|
||||||
@ -395,7 +395,7 @@ public class MediaSessionPlayerTest {
|
|||||||
// Make client app to generate a long list, and call setMediaItems() with it.
|
// Make client app to generate a long list, and call setMediaItems() with it.
|
||||||
controller.createAndSetFakeMediaItems(listSize);
|
controller.createAndSetFakeMediaItems(listSize);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
|
||||||
assertThat(player.mediaItems).isNotNull();
|
assertThat(player.mediaItems).isNotNull();
|
||||||
assertThat(player.mediaItems.size()).isEqualTo(listSize);
|
assertThat(player.mediaItems.size()).isEqualTo(listSize);
|
||||||
for (int i = 0; i < listSize; i++) {
|
for (int i = 0; i < listSize; i++) {
|
||||||
@ -824,7 +824,7 @@ public class MediaSessionPlayerTest {
|
|||||||
controller.setMediaItemsPreparePlayAddItemsSeek(initialItems, addedItems, /* seekIndex= */ 3);
|
controller.setMediaItemsPreparePlayAddItemsSeek(initialItems, addedItems, /* seekIndex= */ 3);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
boolean setMediaItemsCalledBeforePrepare =
|
boolean setMediaItemsCalledBeforePrepare =
|
||||||
player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS);
|
player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
|
||||||
boolean addMediaItemsCalledBeforeSeek =
|
boolean addMediaItemsCalledBeforeSeek =
|
||||||
player.hasMethodBeenCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS);
|
player.hasMethodBeenCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user