Filter available commands based on PlaybackStateCompat actions

This allows a MediaController to understand which methods calls
are available on a legacy session.

PiperOrigin-RevId: 504306806
(cherry picked from commit 067340cb0a03dede0f51425de00643fe3789baf2)
This commit is contained in:
tonihei 2023-01-24 18:06:24 +00:00 committed by christosts
parent 207d67b7af
commit c357e67dd1
4 changed files with 499 additions and 29 deletions

View File

@ -46,6 +46,7 @@ import android.view.SurfaceView;
import android.view.TextureView;
import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import androidx.media.VolumeProviderCompat;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.C;
import androidx.media3.common.DeviceInfo;
@ -1877,9 +1878,17 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
// Note: Sets the available player command here although it can be obtained before session is
// ready. It's to follow the decision on MediaController to disallow any commands before
// connection is made.
int volumeControlType =
newLegacyPlayerInfo.playbackInfoCompat != null
? newLegacyPlayerInfo.playbackInfoCompat.getVolumeControl()
: VolumeProviderCompat.VOLUME_CONTROL_FIXED;
availablePlayerCommands =
(oldControllerInfo.availablePlayerCommands == Commands.EMPTY)
? MediaUtils.convertToPlayerCommands(sessionFlags, isSessionReady)
? MediaUtils.convertToPlayerCommands(
newLegacyPlayerInfo.playbackStateCompat,
volumeControlType,
sessionFlags,
isSessionReady)
: oldControllerInfo.availablePlayerCommands;
PlaybackException playerError =

View File

@ -19,13 +19,17 @@ import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_Q
import static androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS;
import static androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES;
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_GET_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA;
import static androidx.media3.common.Player.COMMAND_GET_TIMELINE;
import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE;
import static androidx.media3.common.Player.COMMAND_PREPARE;
import static androidx.media3.common.Player.COMMAND_SEEK_BACK;
import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD;
import static androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
@ -65,6 +69,7 @@ import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.media.AudioAttributesCompat;
import androidx.media.MediaBrowserServiceCompat.BrowserRoot;
import androidx.media.VolumeProviderCompat;
import androidx.media3.common.AdPlaybackState;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.C;
@ -1070,42 +1075,103 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
/**
* Converts {@link MediaControllerCompat#getFlags() session flags} and {@link
* MediaControllerCompat#isSessionReady whether session is ready} to {@link Player.Commands}.
* Converts {@link PlaybackStateCompat}, {@link
* MediaControllerCompat.PlaybackInfo#getVolumeControl() volume control type}, {@link
* MediaControllerCompat#getFlags() session flags} and {@link MediaControllerCompat#isSessionReady
* whether the session is ready} to {@link Player.Commands}.
*
* @param sessionFlags The session flag.
* @param playbackStateCompat The {@link PlaybackStateCompat}.
* @param volumeControlType The {@link MediaControllerCompat.PlaybackInfo#getVolumeControl()
* volume control type}.
* @param sessionFlags The session flags.
* @param isSessionReady Whether the session compat is ready.
* @return The converted player commands.
*/
public static Player.Commands convertToPlayerCommands(long sessionFlags, boolean isSessionReady) {
public static Player.Commands convertToPlayerCommands(
@Nullable PlaybackStateCompat playbackStateCompat,
int volumeControlType,
long sessionFlags,
boolean isSessionReady) {
Commands.Builder playerCommandsBuilder = new Commands.Builder();
long actions = playbackStateCompat == null ? 0 : playbackStateCompat.getActions();
if ((hasAction(actions, PlaybackStateCompat.ACTION_PLAY)
&& hasAction(actions, PlaybackStateCompat.ACTION_PAUSE))
|| hasAction(actions, PlaybackStateCompat.ACTION_PLAY_PAUSE)) {
playerCommandsBuilder.add(COMMAND_PLAY_PAUSE);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_PREPARE)) {
playerCommandsBuilder.add(COMMAND_PREPARE);
}
if ((hasAction(actions, PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID)
&& hasAction(actions, PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID))
|| (hasAction(actions, PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH)
&& hasAction(actions, PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH))
|| (hasAction(actions, PlaybackStateCompat.ACTION_PREPARE_FROM_URI)
&& hasAction(actions, PlaybackStateCompat.ACTION_PLAY_FROM_URI))) {
// Require both PREPARE and PLAY actions as we have no logic to handle having just one action.
playerCommandsBuilder.addAll(COMMAND_SET_MEDIA_ITEM, COMMAND_PREPARE);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_REWIND)) {
playerCommandsBuilder.add(COMMAND_SEEK_BACK);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_FAST_FORWARD)) {
playerCommandsBuilder.add(COMMAND_SEEK_FORWARD);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_SEEK_TO)) {
playerCommandsBuilder.addAll(
COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_DEFAULT_POSITION);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_SKIP_TO_NEXT)) {
playerCommandsBuilder.addAll(COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)) {
playerCommandsBuilder.addAll(COMMAND_SEEK_TO_PREVIOUS, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED)) {
playerCommandsBuilder.add(COMMAND_SET_SPEED_AND_PITCH);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_STOP)) {
playerCommandsBuilder.add(COMMAND_STOP);
}
if (volumeControlType == VolumeProviderCompat.VOLUME_CONTROL_RELATIVE) {
playerCommandsBuilder.add(COMMAND_ADJUST_DEVICE_VOLUME);
} else if (volumeControlType == VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE) {
playerCommandsBuilder.addAll(COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_SET_DEVICE_VOLUME);
}
playerCommandsBuilder.addAll(
COMMAND_PLAY_PAUSE,
COMMAND_PREPARE,
COMMAND_STOP,
COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM,
COMMAND_SET_SPEED_AND_PITCH,
COMMAND_GET_DEVICE_VOLUME,
COMMAND_SET_DEVICE_VOLUME,
COMMAND_ADJUST_DEVICE_VOLUME,
COMMAND_GET_TIMELINE,
COMMAND_SEEK_TO_PREVIOUS,
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM,
COMMAND_SEEK_TO_NEXT,
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM,
COMMAND_GET_MEDIA_ITEMS_METADATA,
COMMAND_GET_CURRENT_MEDIA_ITEM,
COMMAND_SET_MEDIA_ITEM);
boolean includePlaylistCommands = (sessionFlags & FLAG_HANDLES_QUEUE_COMMANDS) != 0;
if (includePlaylistCommands) {
COMMAND_GET_AUDIO_ATTRIBUTES);
if ((sessionFlags & FLAG_HANDLES_QUEUE_COMMANDS) != 0) {
playerCommandsBuilder.add(COMMAND_CHANGE_MEDIA_ITEMS);
if (hasAction(actions, PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM)) {
playerCommandsBuilder.add(Player.COMMAND_SEEK_TO_MEDIA_ITEM);
}
}
if (isSessionReady) {
playerCommandsBuilder.addAll(COMMAND_SET_SHUFFLE_MODE, COMMAND_SET_REPEAT_MODE);
if (hasAction(actions, PlaybackStateCompat.ACTION_SET_REPEAT_MODE)) {
playerCommandsBuilder.add(COMMAND_SET_REPEAT_MODE);
}
if (hasAction(actions, PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE)) {
playerCommandsBuilder.add(COMMAND_SET_SHUFFLE_MODE);
}
}
return playerCommandsBuilder.build();
}
/**
* Checks if the set of actions contains the specified action.
*
* @param actions A bit set of actions.
* @param action The action to check.
* @return Whether the action is contained in the set.
*/
private static boolean hasAction(long actions, @PlaybackStateCompat.Actions long action) {
return (actions & action) != 0;
}
/**
* Converts {@link PlaybackStateCompat} to {@link SessionCommands}.
*

View File

@ -153,6 +153,20 @@ public class TestUtils {
return list.build();
}
/**
* Returns an {@link ImmutableList} with the {@linkplain Player.Command Commands} contained in
* {@code commands}. The contents of the list are in matching order with the {@linkplain
* Player.Command Commands} returned by {@link Player.Commands#get(int)}.
*/
// TODO(b/254265256): Move this method off test-session-common.
public static ImmutableList<@Player.Command Integer> getCommandsAsList(Player.Commands commands) {
ImmutableList.Builder<@Player.Command Integer> list = new ImmutableList.Builder<>();
for (int i = 0; i < commands.size(); i++) {
list.add(commands.get(i));
}
return list.build();
}
/** Returns the bytes of a scaled asset file. */
public static byte[] getByteArrayForScaledBitmap(Context context, String fileName)
throws IOException {

View File

@ -18,12 +18,12 @@ package androidx.media3.session;
import static android.support.v4.media.MediaBrowserCompat.MediaItem.FLAG_BROWSABLE;
import static android.support.v4.media.MediaBrowserCompat.MediaItem.FLAG_PLAYABLE;
import static android.support.v4.media.MediaMetadataCompat.METADATA_KEY_DURATION;
import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
import static androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS;
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
import static androidx.media3.common.MimeTypes.VIDEO_H264;
import static androidx.media3.common.MimeTypes.VIDEO_H265;
import static androidx.media3.session.MediaConstants.EXTRA_KEY_ROOT_CHILDREN_BROWSABLE_ONLY;
import static androidx.media3.test.session.common.TestUtils.getCommandsAsList;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;
@ -43,6 +43,7 @@ import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.media.AudioAttributesCompat;
import androidx.media.VolumeProviderCompat;
import androidx.media.utils.MediaConstants;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.C;
@ -479,19 +480,399 @@ public final class MediaUtilsTest {
}
@Test
public void convertToPlayerCommands() {
long sessionFlags = FLAG_HANDLES_QUEUE_COMMANDS;
public void convertToPlayerCommands_withNoActions_onlyDefaultCommandsAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(/* capabilities= */ 0).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(sessionFlags, /* isSessionReady= */ true);
assertThat(playerCommands.contains(Player.COMMAND_GET_TIMELINE)).isTrue();
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsExactly(
Player.COMMAND_GET_TIMELINE,
Player.COMMAND_GET_CURRENT_MEDIA_ITEM,
Player.COMMAND_GET_DEVICE_VOLUME,
Player.COMMAND_GET_MEDIA_ITEMS_METADATA,
Player.COMMAND_GET_AUDIO_ATTRIBUTES);
}
@Test
public void convertToPlayerCommands_whenSessionIsNotReady_disallowsShuffle() {
long sessionFlags = FLAG_HANDLES_QUEUE_COMMANDS;
public void convertToPlayerCommands_withJustPlayAction_playPauseCommandNotAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_PLAY).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(sessionFlags, /* isSessionReady= */ false);
assertThat(playerCommands.contains(Player.COMMAND_SET_SHUFFLE_MODE)).isFalse();
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).doesNotContain(Player.COMMAND_PLAY_PAUSE);
}
@Test
public void convertToPlayerCommands_withJustPauseAction_playPauseCommandNotAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_PAUSE).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).doesNotContain(Player.COMMAND_PLAY_PAUSE);
}
@Test
public void convertToPlayerCommands_withPlayAndPauseAction_playPauseCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_PLAY_PAUSE);
}
@Test
public void convertToPlayerCommands_withPlayPauseAction_playPauseCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_PLAY_PAUSE);
}
@Test
public void convertToPlayerCommands_withPrepareAction_prepareCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_PREPARE).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_PREPARE);
}
@Test
public void convertToPlayerCommands_withRewindAction_seekBackCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_REWIND).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_SEEK_BACK);
}
@Test
public void convertToPlayerCommands_withFastForwardAction_seekForwardCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_FAST_FORWARD)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_SEEK_FORWARD);
}
@Test
public void convertToPlayerCommands_withSeekToAction_seekInCurrentMediaItemCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_SEEK_TO).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.contains(Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM);
}
@Test
public void convertToPlayerCommands_withSkipToNextAction_seekToNextCommandsAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SKIP_TO_NEXT)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(Player.COMMAND_SEEK_TO_NEXT, Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM);
}
@Test
public void convertToPlayerCommands_withSkipToPreviousAction_seekToPreviousCommandsAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(
Player.COMMAND_SEEK_TO_PREVIOUS, Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM);
}
@Test
public void
convertToPlayerCommands_withPlayFromActionsWithoutPrepareFromAction_setMediaItemCommandNotAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID
| PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
| PlaybackStateCompat.ACTION_PLAY_FROM_URI)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsNoneOf(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_PREPARE);
}
@Test
public void
convertToPlayerCommands_withPrepareFromActionsWithoutPlayFromAction_setMediaItemCommandNotAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID
| PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH
| PlaybackStateCompat.ACTION_PREPARE_FROM_URI)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsNoneOf(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_PREPARE);
}
@Test
public void
convertToPlayerCommands_withPlayFromAndPrepareFromMediaId_setMediaItemPrepareAndPlayAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID
| PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_PREPARE);
}
@Test
public void
convertToPlayerCommands_withPlayFromAndPrepareFromSearch_setMediaItemPrepareAndPlayAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
| PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_PREPARE);
}
@Test
public void
convertToPlayerCommands_withPlayFromAndPrepareFromUri_setMediaItemPrepareAndPlayAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY_FROM_URI
| PlaybackStateCompat.ACTION_PREPARE_FROM_URI)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(Player.COMMAND_SET_MEDIA_ITEM, Player.COMMAND_PREPARE);
}
@Test
public void convertToPlayerCommands_withSetPlaybackSpeedAction_setSpeedCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_SET_SPEED_AND_PITCH);
}
@Test
public void convertToPlayerCommands_withStopAction_stopCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_STOP).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_STOP);
}
@Test
public void convertToPlayerCommands_withRelativeVolumeControl_adjustVolumeCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(/* capabilities= */ 0).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_RELATIVE,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands)).contains(Player.COMMAND_ADJUST_DEVICE_VOLUME);
assertThat(getCommandsAsList(playerCommands)).doesNotContain(Player.COMMAND_SET_DEVICE_VOLUME);
}
@Test
public void convertToPlayerCommands_withAbsoluteVolumeControl_adjustVolumeCommandAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder().setActions(/* capabilities= */ 0).build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(Player.COMMAND_ADJUST_DEVICE_VOLUME, Player.COMMAND_SET_DEVICE_VOLUME);
}
@Test
public void
convertToPlayerCommands_withShuffleRepeatActionsAndSessionReady_shuffleAndRepeatCommandsAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_SET_REPEAT_MODE
| PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ true);
assertThat(getCommandsAsList(playerCommands))
.containsAtLeast(Player.COMMAND_SET_REPEAT_MODE, Player.COMMAND_SET_SHUFFLE_MODE);
}
@Test
public void
convertToPlayerCommands_withShuffleRepeatActionsAndSessionNotReady_shuffleAndRepeatCommandsNotAvailable() {
PlaybackStateCompat playbackStateCompat =
new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_SET_REPEAT_MODE
| PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE)
.build();
Player.Commands playerCommands =
MediaUtils.convertToPlayerCommands(
playbackStateCompat,
/* volumeControlType= */ VolumeProviderCompat.VOLUME_CONTROL_FIXED,
/* sessionFlags= */ 0,
/* isSessionReady= */ false);
assertThat(getCommandsAsList(playerCommands))
.containsNoneOf(Player.COMMAND_SET_REPEAT_MODE, Player.COMMAND_SET_SHUFFLE_MODE);
}
@Test