Add missing command checks to playback resumption flow
Player methods shouldn't be called if they are not available and the entry point to the playback resumption flow only checks COMMAND_PLAY_PAUSE. #minor-release PiperOrigin-RevId: 574834148
This commit is contained in:
parent
5f80a47081
commit
bfd1a2724c
@ -1423,11 +1423,19 @@ public class MediaSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the last recent playlist of the player with which the player should be prepared when
|
* Returns the playlist with which the player should be prepared when a controller requests to
|
||||||
* playback resumption from a media button receiver or the System UI notification is requested.
|
* play without a current {@link MediaItem}.
|
||||||
|
*
|
||||||
|
* <p>This happens, for example, if <a
|
||||||
|
* href="https://developer.android.com/guide/topics/media/session/mediasession#resumption">playback
|
||||||
|
* resumption</a> is requested from a media button receiver or the System UI notification.
|
||||||
|
*
|
||||||
|
* <p>The method will only be called if the {@link Player} has {@link
|
||||||
|
* Player#COMMAND_GET_CURRENT_MEDIA_ITEM} and either {@link Player#COMMAND_SET_MEDIA_ITEM} or
|
||||||
|
* {@link Player#COMMAND_CHANGE_MEDIA_ITEMS} available.
|
||||||
*
|
*
|
||||||
* @param mediaSession The media session for which playback resumption is requested.
|
* @param mediaSession The media session for which playback resumption is requested.
|
||||||
* @param controller The controller that requests the playback resumption. This is a short
|
* @param controller The controller that requests the playback resumption. This may be a short
|
||||||
* living controller created only for issuing a play command for resuming playback.
|
* living controller created only for issuing a play command for resuming playback.
|
||||||
* @return The {@linkplain MediaItemsWithStartPosition playlist} to resume playback with.
|
* @return The {@linkplain MediaItemsWithStartPosition playlist} to resume playback with.
|
||||||
*/
|
*/
|
||||||
|
@ -25,6 +25,8 @@ import static android.view.KeyEvent.KEYCODE_MEDIA_REWIND;
|
|||||||
import static android.view.KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD;
|
import static android.view.KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD;
|
||||||
import static android.view.KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD;
|
import static android.view.KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD;
|
||||||
import static android.view.KeyEvent.KEYCODE_MEDIA_STOP;
|
import static android.view.KeyEvent.KEYCODE_MEDIA_STOP;
|
||||||
|
import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS;
|
||||||
|
import static androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM;
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.common.util.Util.SDK_INT;
|
import static androidx.media3.common.util.Util.SDK_INT;
|
||||||
@ -33,7 +35,6 @@ import static androidx.media3.session.MediaSessionStub.UNKNOWN_SEQUENCE_NUMBER;
|
|||||||
import static androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_DISCONNECTED;
|
import static androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_DISCONNECTED;
|
||||||
import static androidx.media3.session.SessionResult.RESULT_ERROR_UNKNOWN;
|
import static androidx.media3.session.SessionResult.RESULT_ERROR_UNKNOWN;
|
||||||
import static androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED;
|
import static androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED;
|
||||||
import static java.lang.Math.min;
|
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@ -55,10 +56,8 @@ import androidx.annotation.CheckResult;
|
|||||||
import androidx.annotation.FloatRange;
|
import androidx.annotation.FloatRange;
|
||||||
import androidx.annotation.GuardedBy;
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.os.ExecutorCompat;
|
|
||||||
import androidx.media.MediaBrowserServiceCompat;
|
import androidx.media.MediaBrowserServiceCompat;
|
||||||
import androidx.media3.common.AudioAttributes;
|
import androidx.media3.common.AudioAttributes;
|
||||||
import androidx.media3.common.C;
|
|
||||||
import androidx.media3.common.DeviceInfo;
|
import androidx.media3.common.DeviceInfo;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MediaLibraryInfo;
|
import androidx.media3.common.MediaLibraryInfo;
|
||||||
@ -87,14 +86,12 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
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 com.google.common.util.concurrent.MoreExecutors;
|
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import org.checkerframework.checker.initialization.qual.Initialized;
|
import org.checkerframework.checker.initialization.qual.Initialized;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
@ -815,67 +812,72 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to prepare and play for playback resumption.
|
* Handles a play request from a media controller.
|
||||||
*
|
*
|
||||||
* <p>If playlist data for playback resumption can be successfully obtained, the media items are
|
* <p>Attempts to prepare and play for playback resumption if the playlist is empty. {@link
|
||||||
* set and the player is prepared. {@link Player#play()} is called regardless of success or
|
* Player#play()} is called regardless of success or failure of playback resumption.
|
||||||
* failure of playback resumption.
|
|
||||||
*
|
*
|
||||||
* @param controller The controller requesting playback resumption.
|
* @param controller The controller requesting to play.
|
||||||
* @param player The player to setup for playback resumption.
|
|
||||||
*/
|
*/
|
||||||
/* package */ void prepareAndPlayForPlaybackResumption(ControllerInfo controller, Player player) {
|
/* package */ void handleMediaControllerPlayRequest(ControllerInfo controller) {
|
||||||
verifyApplicationThread();
|
if (!onPlayRequested()) {
|
||||||
@Nullable
|
// Request denied, e.g. due to missing foreground service abilities.
|
||||||
ListenableFuture<MediaItemsWithStartPosition> future =
|
return;
|
||||||
checkNotNull(
|
}
|
||||||
callback.onPlaybackResumption(instance, resolveControllerInfoForCallback(controller)),
|
boolean hasCurrentMediaItem =
|
||||||
"Callback.onPlaybackResumption must return a non-null future");
|
playerWrapper.isCommandAvailable(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)
|
||||||
// Use a direct executor when an immediate future is returned to execute the player setup in the
|
&& playerWrapper.getCurrentMediaItem() != null;
|
||||||
// caller's looper event on the application thread.
|
boolean canAddMediaItems =
|
||||||
Executor executor =
|
playerWrapper.isCommandAvailable(COMMAND_SET_MEDIA_ITEM)
|
||||||
future.isDone()
|
|| playerWrapper.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS);
|
||||||
? MoreExecutors.directExecutor()
|
if (hasCurrentMediaItem || !canAddMediaItems) {
|
||||||
: ExecutorCompat.create(getApplicationHandler());
|
// No playback resumption needed or possible.
|
||||||
Futures.addCallback(
|
if (!hasCurrentMediaItem) {
|
||||||
future,
|
Log.w(
|
||||||
new FutureCallback<MediaItemsWithStartPosition>() {
|
TAG,
|
||||||
@Override
|
"Play requested without current MediaItem, but playback resumption prevented by"
|
||||||
public void onSuccess(MediaItemsWithStartPosition mediaItemsWithStartPosition) {
|
+ " missing available commands");
|
||||||
ImmutableList<MediaItem> mediaItems = mediaItemsWithStartPosition.mediaItems;
|
}
|
||||||
player.setMediaItems(
|
Util.handlePlayButtonAction(playerWrapper);
|
||||||
mediaItems,
|
} else {
|
||||||
mediaItemsWithStartPosition.startIndex != C.INDEX_UNSET
|
@Nullable
|
||||||
? min(mediaItems.size() - 1, mediaItemsWithStartPosition.startIndex)
|
ListenableFuture<MediaItemsWithStartPosition> future =
|
||||||
: 0,
|
checkNotNull(
|
||||||
mediaItemsWithStartPosition.startPositionMs);
|
callback.onPlaybackResumption(instance, resolveControllerInfoForCallback(controller)),
|
||||||
if (player.getPlaybackState() == Player.STATE_IDLE) {
|
"Callback.onPlaybackResumption must return a non-null future");
|
||||||
player.prepare();
|
Futures.addCallback(
|
||||||
|
future,
|
||||||
|
new FutureCallback<MediaItemsWithStartPosition>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(MediaItemsWithStartPosition mediaItemsWithStartPosition) {
|
||||||
|
MediaUtils.setMediaItemsWithStartIndexAndPosition(
|
||||||
|
playerWrapper, mediaItemsWithStartPosition);
|
||||||
|
Util.handlePlayButtonAction(playerWrapper);
|
||||||
}
|
}
|
||||||
player.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void onFailure(Throwable t) {
|
||||||
if (t instanceof UnsupportedOperationException) {
|
if (t instanceof UnsupportedOperationException) {
|
||||||
Log.w(
|
Log.w(
|
||||||
TAG,
|
TAG,
|
||||||
"UnsupportedOperationException: Make sure to implement"
|
"UnsupportedOperationException: Make sure to implement"
|
||||||
+ " MediaSession.Callback.onPlaybackResumption() if you add a"
|
+ " MediaSession.Callback.onPlaybackResumption() if you add a"
|
||||||
+ " media button receiver to your manifest or if you implement the recent"
|
+ " media button receiver to your manifest or if you implement the recent"
|
||||||
+ " media item contract with your MediaLibraryService.",
|
+ " media item contract with your MediaLibraryService.",
|
||||||
t);
|
t);
|
||||||
} else {
|
} else {
|
||||||
Log.e(
|
Log.e(
|
||||||
TAG,
|
TAG,
|
||||||
"Failure calling MediaSession.Callback.onPlaybackResumption(): " + t.getMessage(),
|
"Failure calling MediaSession.Callback.onPlaybackResumption(): "
|
||||||
t);
|
+ t.getMessage(),
|
||||||
|
t);
|
||||||
|
}
|
||||||
|
// Play as requested even if playback resumption fails.
|
||||||
|
Util.handlePlayButtonAction(playerWrapper);
|
||||||
}
|
}
|
||||||
// Play as requested either way.
|
},
|
||||||
Util.handlePlayButtonAction(player);
|
this::postOrRunOnApplicationHandler);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
executor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAvailableFrameworkControllerCommands(
|
private void setAvailableFrameworkControllerCommands(
|
||||||
@ -1147,6 +1149,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void postOrRunOnApplicationHandler(Runnable runnable) {
|
||||||
|
Util.postOrRun(getApplicationHandler(), runnable);
|
||||||
|
}
|
||||||
|
|
||||||
/* @FunctionalInterface */
|
/* @FunctionalInterface */
|
||||||
interface RemoteControllerTask {
|
interface RemoteControllerTask {
|
||||||
|
|
||||||
|
@ -411,18 +411,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
|||||||
public void onPlay() {
|
public void onPlay() {
|
||||||
dispatchSessionTaskWithPlayerCommand(
|
dispatchSessionTaskWithPlayerCommand(
|
||||||
COMMAND_PLAY_PAUSE,
|
COMMAND_PLAY_PAUSE,
|
||||||
controller -> {
|
sessionImpl::handleMediaControllerPlayRequest,
|
||||||
if (sessionImpl.onPlayRequested()) {
|
|
||||||
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
|
|
||||||
if (playerWrapper.getMediaItemCount() == 0) {
|
|
||||||
// The player is in IDLE or ENDED state and has no media items in the playlist yet.
|
|
||||||
// Handle the play command as a playback resumption command to try resume playback.
|
|
||||||
sessionImpl.prepareAndPlayForPlaybackResumption(controller, playerWrapper);
|
|
||||||
} else {
|
|
||||||
Util.handlePlayButtonAction(playerWrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sessionCompat.getCurrentControllerInfo());
|
sessionCompat.getCurrentControllerInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,16 +719,7 @@ import java.util.concurrent.ExecutionException;
|
|||||||
if (impl == null || impl.isReleased()) {
|
if (impl == null || impl.isReleased()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (impl.onPlayRequested()) {
|
impl.handleMediaControllerPlayRequest(controller);
|
||||||
if (player.getMediaItemCount() == 0) {
|
|
||||||
// The player is in IDLE or ENDED state and has no media items in the playlist
|
|
||||||
// yet. Handle the play command as a playback resumption command to try resume
|
|
||||||
// playback.
|
|
||||||
impl.prepareAndPlayForPlaybackResumption(controller, player);
|
|
||||||
} else {
|
|
||||||
Util.handlePlayButtonAction(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1073,8 +1073,7 @@ public class MediaSessionCallbackTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onPlay_withEmptyTimelinePlaybackResumptionOn_callsOnGetPlaybackResumptionPlaylist()
|
public void onPlay_withEmptyTimeline_callsOnGetPlaybackResumptionPlaylist() throws Exception {
|
||||||
throws Exception {
|
|
||||||
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
MediaSession.Callback callback =
|
MediaSession.Callback callback =
|
||||||
new MediaSession.Callback() {
|
new MediaSession.Callback() {
|
||||||
@ -1093,8 +1092,8 @@ public class MediaSessionCallbackTest {
|
|||||||
remoteControllerTestRule.createRemoteController(session.getToken());
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
controller.play();
|
controller.play();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
@ -1104,18 +1103,110 @@ public class MediaSessionCallbackTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onPlay_withEmptyTimelineCallbackFailure_callsHandlePlayButtonAction()
|
public void
|
||||||
throws Exception {
|
onPlay_withEmptyTimelineWithoutCommandGetCurrentMediaItem_doesNotTriggerPlaybackResumption()
|
||||||
player.startMediaItemIndex = 7;
|
throws Exception {
|
||||||
player.startPositionMs = 321L;
|
player.commands =
|
||||||
|
new Player.Commands.Builder()
|
||||||
|
.addAllCommands()
|
||||||
|
.remove(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)
|
||||||
|
.build();
|
||||||
MediaSession session =
|
MediaSession session =
|
||||||
sessionTestRule.ensureReleaseAfterTest(new MediaSession.Builder(context, player).build());
|
sessionTestRule.ensureReleaseAfterTest(new MediaSession.Builder(context, player).build());
|
||||||
RemoteMediaController controller =
|
RemoteMediaController controller =
|
||||||
remoteControllerTestRule.createRemoteController(session.getToken());
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
controller.play();
|
controller.play();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
|
.isFalse();
|
||||||
|
assertThat(player.mediaItems).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
onPlay_withEmptyTimelineWithoutCommandSetOrChangeMediaItems_doesNotTriggerPlaybackResumption()
|
||||||
|
throws Exception {
|
||||||
|
player.commands =
|
||||||
|
new Player.Commands.Builder()
|
||||||
|
.addAllCommands()
|
||||||
|
.removeAll(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_CHANGE_MEDIA_ITEMS)
|
||||||
|
.build();
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(new MediaSession.Builder(context, player).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
|
controller.play();
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
|
.isFalse();
|
||||||
|
assertThat(player.mediaItems).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPlay_withEmptyTimelineWithoutCommandChangeMediaItems_setsSingleItem()
|
||||||
|
throws Exception {
|
||||||
|
player.commands =
|
||||||
|
new Player.Commands.Builder()
|
||||||
|
.addAllCommands()
|
||||||
|
.remove(Player.COMMAND_CHANGE_MEDIA_ITEMS)
|
||||||
|
.build();
|
||||||
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onPlaybackResumption(
|
||||||
|
MediaSession mediaSession, ControllerInfo controller) {
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
mediaItems, /* startIndex= */ 1, /* startPositionMs= */ 123L));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player).setCallback(callback).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
|
controller.play();
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEM_WITH_START_POSITION))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(0);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(123L);
|
||||||
|
assertThat(player.mediaItems).containsExactly(mediaItems.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
onPlay_withEmptyTimelinePlaybackResumptionCallbackFailure_callsHandlePlayButtonAction()
|
||||||
|
throws Exception {
|
||||||
|
player.startMediaItemIndex = 7;
|
||||||
|
player.startPositionMs = 321L;
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onPlaybackResumption(
|
||||||
|
MediaSession mediaSession, ControllerInfo controller) {
|
||||||
|
return Futures.immediateFailedFuture(new UnsupportedOperationException());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSession session =
|
||||||
|
sessionTestRule.ensureReleaseAfterTest(
|
||||||
|
new MediaSession.Builder(context, player).setCallback(callback).build());
|
||||||
|
RemoteMediaController controller =
|
||||||
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
|
controller.play();
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
@ -1150,8 +1241,8 @@ public class MediaSessionCallbackTest {
|
|||||||
remoteControllerTestRule.createRemoteController(session.getToken());
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
controller.play();
|
controller.play();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
@ -1188,6 +1279,7 @@ public class MediaSessionCallbackTest {
|
|||||||
|
|
||||||
remoteControllerTestRule.createRemoteController(
|
remoteControllerTestRule.createRemoteController(
|
||||||
session.getToken(), /* waitForConnection= */ false, testConnectionHints);
|
session.getToken(), /* waitForConnection= */ false, testConnectionHints);
|
||||||
|
|
||||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
assertThat(TestUtils.equals(testConnectionHints, connectionHints.get())).isTrue();
|
assertThat(TestUtils.equals(testConnectionHints, connectionHints.get())).isTrue();
|
||||||
}
|
}
|
||||||
@ -1213,7 +1305,9 @@ public class MediaSessionCallbackTest {
|
|||||||
.build());
|
.build());
|
||||||
RemoteMediaController controller =
|
RemoteMediaController controller =
|
||||||
remoteControllerTestRule.createRemoteController(session.getToken());
|
remoteControllerTestRule.createRemoteController(session.getToken());
|
||||||
|
|
||||||
controller.release();
|
controller.release();
|
||||||
|
|
||||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +155,13 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
.build();
|
.build();
|
||||||
// Make onDisconnected() to be called immediately after the connection.
|
// Make onDisconnected() to be called immediately after the connection.
|
||||||
session.setLegacyControllerConnectionTimeoutMs(0);
|
session.setLegacyControllerConnectionTimeoutMs(0);
|
||||||
|
|
||||||
controller =
|
controller =
|
||||||
new RemoteMediaControllerCompat(
|
new RemoteMediaControllerCompat(
|
||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
// Invoke any command for session to recognize the controller compat.
|
// Invoke any command for session to recognize the controller compat.
|
||||||
controller.getTransportControls().seekTo(111);
|
controller.getTransportControls().seekTo(111);
|
||||||
|
|
||||||
assertThat(disconnectedLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(disconnectedLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,8 +223,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().play();
|
controller.getTransportControls().play();
|
||||||
|
|
||||||
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.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
||||||
}
|
}
|
||||||
@ -240,9 +242,9 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().play();
|
controller.getTransportControls().play();
|
||||||
|
|
||||||
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(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,8 +263,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().play();
|
controller.getTransportControls().play();
|
||||||
|
|
||||||
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.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
||||||
}
|
}
|
||||||
@ -280,9 +282,9 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().play();
|
controller.getTransportControls().play();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,8 +307,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().play();
|
controller.getTransportControls().play();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION)).isFalse();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
|
||||||
}
|
}
|
||||||
@ -323,7 +325,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().pause();
|
controller.getTransportControls().pause();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +340,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().stop();
|
controller.getTransportControls().stop();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_STOP, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_STOP, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,7 +355,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().prepare();
|
controller.getTransportControls().prepare();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,11 +368,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
controller =
|
controller =
|
||||||
new RemoteMediaControllerCompat(
|
new RemoteMediaControllerCompat(
|
||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
long seekPosition = 12125L;
|
long seekPosition = 12125L;
|
||||||
controller.getTransportControls().seekTo(seekPosition);
|
|
||||||
|
|
||||||
|
controller.getTransportControls().seekTo(seekPosition);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.seekPositionMs).isEqualTo(seekPosition);
|
assertThat(player.seekPositionMs).isEqualTo(seekPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,11 +386,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
controller =
|
controller =
|
||||||
new RemoteMediaControllerCompat(
|
new RemoteMediaControllerCompat(
|
||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
float testSpeed = 2.0f;
|
float testSpeed = 2.0f;
|
||||||
controller.getTransportControls().setPlaybackSpeed(testSpeed);
|
|
||||||
|
|
||||||
|
controller.getTransportControls().setPlaybackSpeed(testSpeed);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAYBACK_SPEED, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAYBACK_SPEED, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.playbackParameters.speed).isEqualTo(testSpeed);
|
assertThat(player.playbackParameters.speed).isEqualTo(testSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,15 +424,15 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
player.timeline = MediaTestUtils.createTimeline(mediaItems);
|
player.timeline = MediaTestUtils.createTimeline(mediaItems);
|
||||||
player.notifyTimelineChanged(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
|
player.notifyTimelineChanged(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prepare an item to add.
|
// Prepare an item to add.
|
||||||
String mediaId = "newMediaItemId";
|
String mediaId = "newMediaItemId";
|
||||||
Uri mediaUri = Uri.parse("https://test.test");
|
Uri mediaUri = Uri.parse("https://test.test");
|
||||||
MediaDescriptionCompat desc =
|
MediaDescriptionCompat desc =
|
||||||
new MediaDescriptionCompat.Builder().setMediaId(mediaId).setMediaUri(mediaUri).build();
|
new MediaDescriptionCompat.Builder().setMediaId(mediaId).setMediaUri(mediaUri).build();
|
||||||
controller.addQueueItem(desc);
|
|
||||||
|
|
||||||
|
controller.addQueueItem(desc);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(mediaId);
|
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(mediaId);
|
||||||
assertThat(requestedMediaItems.get().get(0).requestMetadata.mediaUri).isEqualTo(mediaUri);
|
assertThat(requestedMediaItems.get().get(0).requestMetadata.mediaUri).isEqualTo(mediaUri);
|
||||||
@ -471,16 +470,16 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
player.timeline = MediaTestUtils.createTimeline(mediaItems);
|
player.timeline = MediaTestUtils.createTimeline(mediaItems);
|
||||||
player.notifyTimelineChanged(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
|
player.notifyTimelineChanged(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prepare an item to add.
|
// Prepare an item to add.
|
||||||
int testIndex = 1;
|
int testIndex = 1;
|
||||||
String mediaId = "media_id";
|
String mediaId = "media_id";
|
||||||
Uri mediaUri = Uri.parse("https://test.test");
|
Uri mediaUri = Uri.parse("https://test.test");
|
||||||
MediaDescriptionCompat desc =
|
MediaDescriptionCompat desc =
|
||||||
new MediaDescriptionCompat.Builder().setMediaId(mediaId).setMediaUri(mediaUri).build();
|
new MediaDescriptionCompat.Builder().setMediaId(mediaId).setMediaUri(mediaUri).build();
|
||||||
controller.addQueueItem(desc, testIndex);
|
|
||||||
|
|
||||||
|
controller.addQueueItem(desc, testIndex);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS_WITH_INDEX, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS_WITH_INDEX, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(requestedMediaItems.get()).hasSize(1);
|
assertThat(requestedMediaItems.get()).hasSize(1);
|
||||||
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(mediaId);
|
assertThat(requestedMediaItems.get().get(0).mediaId).isEqualTo(mediaId);
|
||||||
assertThat(requestedMediaItems.get().get(0).requestMetadata.mediaUri).isEqualTo(mediaUri);
|
assertThat(requestedMediaItems.get().get(0).requestMetadata.mediaUri).isEqualTo(mediaUri);
|
||||||
@ -507,15 +506,15 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
player.timeline = new PlaylistTimeline(mediaItems);
|
player.timeline = new PlaylistTimeline(mediaItems);
|
||||||
player.notifyTimelineChanged(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
|
player.notifyTimelineChanged(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Select an item to remove.
|
// Select an item to remove.
|
||||||
int targetIndex = 3;
|
int targetIndex = 3;
|
||||||
MediaItem targetItem = mediaItems.get(targetIndex);
|
MediaItem targetItem = mediaItems.get(targetIndex);
|
||||||
MediaDescriptionCompat desc =
|
MediaDescriptionCompat desc =
|
||||||
new MediaDescriptionCompat.Builder().setMediaId(targetItem.mediaId).build();
|
new MediaDescriptionCompat.Builder().setMediaId(targetItem.mediaId).build();
|
||||||
controller.removeQueueItem(desc);
|
|
||||||
|
|
||||||
|
controller.removeQueueItem(desc);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEM, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEM, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.index).isEqualTo(targetIndex);
|
assertThat(player.index).isEqualTo(targetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,7 +530,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().skipToPrevious();
|
controller.getTransportControls().skipToPrevious();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,7 +551,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().skipToPrevious();
|
controller.getTransportControls().skipToPrevious();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +566,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().skipToNext();
|
controller.getTransportControls().skipToNext();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +584,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
controller.getTransportControls().skipToNext();
|
controller.getTransportControls().skipToNext();
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT_MEDIA_ITEM, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT_MEDIA_ITEM, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,9 +608,9 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
List<QueueItem> queue = session.getSessionCompat().getController().getQueue();
|
List<QueueItem> queue = session.getSessionCompat().getController().getQueue();
|
||||||
int targetIndex = 3;
|
int targetIndex = 3;
|
||||||
controller.getTransportControls().skipToQueueItem(queue.get(targetIndex).getQueueId());
|
controller.getTransportControls().skipToQueueItem(queue.get(targetIndex).getQueueId());
|
||||||
|
|
||||||
player.awaitMethodCalled(
|
player.awaitMethodCalled(
|
||||||
MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
|
MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.seekMediaItemIndex).isEqualTo(targetIndex);
|
assertThat(player.seekMediaItemIndex).isEqualTo(targetIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,8 +638,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
||||||
|
|
||||||
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
@ -655,20 +650,121 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
dispatchMediaButtonEvent_playWithEmptyTimelineCallbackFailure_callsHandlePlayButtonAction()
|
dispatchMediaButtonEvent_playWithEmptyTimelineWithoutCommandGetCurrentMediaItem_doesNotTriggerPlaybackResumption()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
player.mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
player.commands =
|
||||||
player.startMediaItemIndex = 1;
|
new Player.Commands.Builder()
|
||||||
player.startPositionMs = 321L;
|
.addAllCommands()
|
||||||
session = new MediaSession.Builder(context, player).setId("sendMediaButtonEvent").build();
|
.remove(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)
|
||||||
|
.build();
|
||||||
|
session = new MediaSession.Builder(context, player).setId("dispatchMediaButtonEvent").build();
|
||||||
controller =
|
controller =
|
||||||
new RemoteMediaControllerCompat(
|
new RemoteMediaControllerCompat(
|
||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
||||||
|
|
||||||
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
|
.isFalse();
|
||||||
|
assertThat(player.mediaItems).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
dispatchMediaButtonEvent_playWithEmptyTimelineWithoutCommandSetOrChangeMediaItems_doesNotTriggerPlaybackResumption()
|
||||||
|
throws Exception {
|
||||||
|
player.commands =
|
||||||
|
new Player.Commands.Builder()
|
||||||
|
.addAllCommands()
|
||||||
|
.removeAll(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_CHANGE_MEDIA_ITEMS)
|
||||||
|
.build();
|
||||||
|
session = new MediaSession.Builder(context, player).setId("dispatchMediaButtonEvent").build();
|
||||||
|
controller =
|
||||||
|
new RemoteMediaControllerCompat(
|
||||||
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
||||||
|
|
||||||
|
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
|
.isFalse();
|
||||||
|
assertThat(player.mediaItems).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
dispatchMediaButtonEvent_playWithEmptyTimelineWithoutCommandChangeMediaItems_setsSingleItem()
|
||||||
|
throws Exception {
|
||||||
|
player.commands =
|
||||||
|
new Player.Commands.Builder()
|
||||||
|
.addAllCommands()
|
||||||
|
.remove(Player.COMMAND_CHANGE_MEDIA_ITEMS)
|
||||||
|
.build();
|
||||||
|
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onPlaybackResumption(
|
||||||
|
MediaSession mediaSession, ControllerInfo controller) {
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
new MediaSession.MediaItemsWithStartPosition(
|
||||||
|
mediaItems, /* startIndex= */ 1, /* startPositionMs= */ 123L));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
session =
|
||||||
|
new MediaSession.Builder(context, player)
|
||||||
|
.setCallback(callback)
|
||||||
|
.setId("dispatchMediaButtonEvent")
|
||||||
|
.build();
|
||||||
|
controller =
|
||||||
|
new RemoteMediaControllerCompat(
|
||||||
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
||||||
|
|
||||||
|
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEM_WITH_START_POSITION))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(player.startMediaItemIndex).isEqualTo(0);
|
||||||
|
assertThat(player.startPositionMs).isEqualTo(123L);
|
||||||
|
assertThat(player.mediaItems).containsExactly(mediaItems.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
dispatchMediaButtonEvent_playWithEmptyTimelineCallbackFailure_callsHandlePlayButtonAction()
|
||||||
|
throws Exception {
|
||||||
|
player.mediaItems = MediaTestUtils.createMediaItems(/* size= */ 3);
|
||||||
|
player.startMediaItemIndex = 1;
|
||||||
|
player.startPositionMs = 321L;
|
||||||
|
MediaSession.Callback callback =
|
||||||
|
new MediaSession.Callback() {
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<MediaSession.MediaItemsWithStartPosition> onPlaybackResumption(
|
||||||
|
MediaSession mediaSession, ControllerInfo controller) {
|
||||||
|
return Futures.immediateFailedFuture(new UnsupportedOperationException());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
session =
|
||||||
|
new MediaSession.Builder(context, player)
|
||||||
|
.setCallback(callback)
|
||||||
|
.setId("sendMediaButtonEvent")
|
||||||
|
.build();
|
||||||
|
controller =
|
||||||
|
new RemoteMediaControllerCompat(
|
||||||
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY);
|
||||||
|
|
||||||
|
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
||||||
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
@ -707,8 +803,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
|
||||||
|
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
|
||||||
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
@ -727,11 +823,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
controller =
|
controller =
|
||||||
new RemoteMediaControllerCompat(
|
new RemoteMediaControllerCompat(
|
||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
@PlaybackStateCompat.ShuffleMode int testShuffleMode = PlaybackStateCompat.SHUFFLE_MODE_GROUP;
|
@PlaybackStateCompat.ShuffleMode int testShuffleMode = PlaybackStateCompat.SHUFFLE_MODE_GROUP;
|
||||||
controller.getTransportControls().setShuffleMode(testShuffleMode);
|
|
||||||
|
|
||||||
|
controller.getTransportControls().setShuffleMode(testShuffleMode);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_SHUFFLE_MODE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_SHUFFLE_MODE, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.shuffleModeEnabled).isTrue();
|
assertThat(player.shuffleModeEnabled).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,11 +841,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
controller =
|
controller =
|
||||||
new RemoteMediaControllerCompat(
|
new RemoteMediaControllerCompat(
|
||||||
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
|
||||||
|
|
||||||
int testRepeatMode = Player.REPEAT_MODE_ALL;
|
int testRepeatMode = Player.REPEAT_MODE_ALL;
|
||||||
controller.getTransportControls().setRepeatMode(testRepeatMode);
|
|
||||||
|
|
||||||
|
controller.getTransportControls().setRepeatMode(testRepeatMode);
|
||||||
player.awaitMethodCalled(MockPlayer.METHOD_SET_REPEAT_MODE, TIMEOUT_MS);
|
player.awaitMethodCalled(MockPlayer.METHOD_SET_REPEAT_MODE, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(player.repeatMode).isEqualTo(testRepeatMode);
|
assertThat(player.repeatMode).isEqualTo(testRepeatMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,11 +873,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
remotePlayer.deviceVolume = 23;
|
remotePlayer.deviceVolume = 23;
|
||||||
session.setPlayer(remotePlayer);
|
session.setPlayer(remotePlayer);
|
||||||
});
|
});
|
||||||
|
|
||||||
int targetVolume = 50;
|
int targetVolume = 50;
|
||||||
controller.setVolumeTo(targetVolume, /* flags= */ 0);
|
|
||||||
|
|
||||||
|
controller.setVolumeTo(targetVolume, /* flags= */ 0);
|
||||||
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME, TIMEOUT_MS);
|
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
|
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,11 +901,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
remotePlayer.deviceVolume = 23;
|
remotePlayer.deviceVolume = 23;
|
||||||
session.setPlayer(remotePlayer);
|
session.setPlayer(remotePlayer);
|
||||||
});
|
});
|
||||||
|
|
||||||
int targetVolume = 50;
|
int targetVolume = 50;
|
||||||
controller.setVolumeTo(targetVolume, /* flags= */ 0);
|
|
||||||
|
|
||||||
|
controller.setVolumeTo(targetVolume, /* flags= */ 0);
|
||||||
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
|
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
|
||||||
|
|
||||||
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
|
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -839,7 +935,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
|
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
|
||||||
|
|
||||||
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME, TIMEOUT_MS);
|
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,7 +959,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
|
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
|
||||||
|
|
||||||
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
|
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,7 +988,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
controller.adjustVolume(AudioManager.ADJUST_LOWER, /* flags= */ 0);
|
controller.adjustVolume(AudioManager.ADJUST_LOWER, /* flags= */ 0);
|
||||||
|
|
||||||
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME, TIMEOUT_MS);
|
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +1013,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
controller.adjustVolume(AudioManager.ADJUST_LOWER, /* flags= */ 0);
|
controller.adjustVolume(AudioManager.ADJUST_LOWER, /* flags= */ 0);
|
||||||
|
|
||||||
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
|
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user