Don't advertise commands that are not available
When calling `MediaController.getCommandButtonForMediaItem(MediaItem)` command buttons with custom commands that are not available shouldn't be advertised to the controller when connected to a Media3 session. In contrast, when connected to a legacy session, available commands are not enforced when advertising commands. Similarly, when sending a custom commands that is referenced by a command button for media items, sending is permitted without the command being available. This is required because available commands match to custom actions in `PlaybackStateCompat` of the legacy session. Adding commands for media items to custom action of the `PlaybackStateCompat` would interfere with other use cases. Issue: androidx/media#1474 #cherrypick PiperOrigin-RevId: 683717723
This commit is contained in:
parent
546d7da2f2
commit
c4ff07e229
@ -43,6 +43,7 @@ import com.google.common.util.concurrent.SettableFuture;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
|
||||
/** Implementation of MediaBrowser with the {@link MediaBrowserCompat} for legacy support. */
|
||||
@ -93,8 +94,21 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<String, CommandButton> getCommandButtonsForMediaItemsMap() {
|
||||
return commandButtonsForMediaItems;
|
||||
public ImmutableList<CommandButton> getCommandButtonsForMediaItem(MediaItem mediaItem) {
|
||||
// Do not filter by available commands. When connected to a legacy session, the available
|
||||
// session commands are read from the custom actions in PlaybackStateCompat (see
|
||||
// LegacyConversion.convertToSessionCommands). Filtering by these commands would force a
|
||||
// legacy session to put all commands for media items into the playback state as custom commands
|
||||
// which would interfere with the custom commands set for media controls.
|
||||
ImmutableList<String> supportedActions = mediaItem.mediaMetadata.supportedCommands;
|
||||
ImmutableList.Builder<CommandButton> commandButtonsForMediaItem = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < supportedActions.size(); i++) {
|
||||
CommandButton commandButton = commandButtonsForMediaItems.get(supportedActions.get(i));
|
||||
if (commandButton != null && commandButton.sessionCommand != null) {
|
||||
commandButtonsForMediaItem.add(commandButton);
|
||||
}
|
||||
}
|
||||
return commandButtonsForMediaItem.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -307,7 +321,9 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
@Override
|
||||
public ListenableFuture<SessionResult> sendCustomCommand(SessionCommand command, Bundle args) {
|
||||
MediaBrowserCompat browserCompat = getBrowserCompat();
|
||||
if (browserCompat != null && instance.isSessionCommandAvailable(command)) {
|
||||
if (browserCompat != null
|
||||
&& (instance.isSessionCommandAvailable(command)
|
||||
|| isContainedInCommandButtonsForMediaItems(command))) {
|
||||
SettableFuture<SessionResult> settable = SettableFuture.create();
|
||||
browserCompat.sendCustomAction(
|
||||
command.customAction,
|
||||
@ -330,7 +346,20 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
});
|
||||
return settable;
|
||||
}
|
||||
return super.sendCustomCommand(command, args);
|
||||
return Futures.immediateFuture(new SessionResult(SessionResult.RESULT_ERROR_PERMISSION_DENIED));
|
||||
}
|
||||
|
||||
// Using this method as a proxy whether an browser is allowed to send a custom action can be
|
||||
// justified because a MediaBrowserCompat can declare the custom browse actions in onGetRoot()
|
||||
// specifically for each browser that connects. This is different to Media3 where the command
|
||||
// buttons for media items are declared on the session level, and are constraint by the available
|
||||
// session commands granted individually to a controller/browser in onConnect.
|
||||
private boolean isContainedInCommandButtonsForMediaItems(SessionCommand command) {
|
||||
if (command.commandCode != SessionCommand.COMMAND_CODE_CUSTOM) {
|
||||
return false;
|
||||
}
|
||||
CommandButton commandButton = commandButtonsForMediaItems.get(command.customAction);
|
||||
return commandButton != null && Objects.equals(commandButton.sessionCommand, command);
|
||||
}
|
||||
|
||||
private MediaBrowserCompat getBrowserCompat(LibraryParams extras) {
|
||||
|
@ -62,7 +62,6 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSourceBitmapLoader;
|
||||
import androidx.media3.session.legacy.MediaBrowserCompat;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
@ -674,16 +673,7 @@ public class MediaController implements Player {
|
||||
*/
|
||||
@UnstableApi
|
||||
public final ImmutableList<CommandButton> getCommandButtonsForMediaItem(MediaItem mediaItem) {
|
||||
ImmutableMap<String, CommandButton> buttonMap = impl.getCommandButtonsForMediaItemsMap();
|
||||
ImmutableList<String> supportedActions = mediaItem.mediaMetadata.supportedCommands;
|
||||
ImmutableList.Builder<CommandButton> commandButtonsForMediaItem = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < supportedActions.size(); i++) {
|
||||
CommandButton commandButton = buttonMap.get(supportedActions.get(i));
|
||||
if (commandButton != null) {
|
||||
commandButtonsForMediaItem.add(commandButton);
|
||||
}
|
||||
}
|
||||
return commandButtonsForMediaItem.build();
|
||||
return impl.getCommandButtonsForMediaItem(mediaItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2174,7 +2164,7 @@ public class MediaController implements Player {
|
||||
|
||||
ImmutableList<CommandButton> getCustomLayout();
|
||||
|
||||
ImmutableMap<String, CommandButton> getCommandButtonsForMediaItemsMap();
|
||||
ImmutableList<CommandButton> getCommandButtonsForMediaItem(MediaItem mediaItem);
|
||||
|
||||
Bundle getSessionExtras();
|
||||
|
||||
|
@ -745,8 +745,19 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<String, CommandButton> getCommandButtonsForMediaItemsMap() {
|
||||
return commandButtonsForMediaItemsMap;
|
||||
public ImmutableList<CommandButton> getCommandButtonsForMediaItem(MediaItem mediaItem) {
|
||||
ImmutableList<String> supportedActions = mediaItem.mediaMetadata.supportedCommands;
|
||||
SessionCommands availableSessionCommands = getAvailableSessionCommands();
|
||||
ImmutableList.Builder<CommandButton> commandButtonsForMediaItem = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < supportedActions.size(); i++) {
|
||||
CommandButton commandButton = commandButtonsForMediaItemsMap.get(supportedActions.get(i));
|
||||
if (commandButton != null
|
||||
&& commandButton.sessionCommand != null
|
||||
&& availableSessionCommands.contains(commandButton.sessionCommand)) {
|
||||
commandButtonsForMediaItem.add(commandButton);
|
||||
}
|
||||
}
|
||||
return commandButtonsForMediaItem.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,7 +76,6 @@ import androidx.media3.session.legacy.PlaybackStateCompat;
|
||||
import androidx.media3.session.legacy.RatingCompat;
|
||||
import androidx.media3.session.legacy.VolumeProviderCompat;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
@ -102,6 +101,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
private final ListenerSet<Listener> listeners;
|
||||
private final ControllerCompatCallback controllerCompatCallback;
|
||||
private final BitmapLoader bitmapLoader;
|
||||
private final ImmutableList<CommandButton> commandButtonsForMediaItems;
|
||||
|
||||
@Nullable private MediaControllerCompat controllerCompat;
|
||||
@Nullable private MediaBrowserCompat browserCompat;
|
||||
@ -137,6 +137,8 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
this.bitmapLoader = bitmapLoader;
|
||||
currentPositionMs = C.TIME_UNSET;
|
||||
lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET;
|
||||
// Always empty. Only supported for a MediaBrowser connected to a MediaBrowserServiceCompat.
|
||||
commandButtonsForMediaItems = ImmutableList.of();
|
||||
}
|
||||
|
||||
/* package */ MediaController getInstance() {
|
||||
@ -410,6 +412,11 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
controllerCompat.getTransportControls().fastForward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<CommandButton> getCommandButtonsForMediaItem(MediaItem mediaItem) {
|
||||
return commandButtonsForMediaItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PendingIntent getSessionActivity() {
|
||||
@ -421,11 +428,6 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
|
||||
return controllerInfo.customLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableMap<String, CommandButton> getCommandButtonsForMediaItemsMap() {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getSessionExtras() {
|
||||
return controllerInfo.sessionExtras;
|
||||
|
@ -23,6 +23,8 @@ public class MediaSessionConstants {
|
||||
public static final String TEST_GET_CUSTOM_LAYOUT = "testGetCustomLayout";
|
||||
public static final String TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS =
|
||||
"testGetCommandButtonsForMediaItems";
|
||||
public static final String TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE =
|
||||
"testGetCommandButtonsForMediaItemsCommandsNotAvailable";
|
||||
public static final String TEST_WITH_CUSTOM_COMMANDS = "testWithCustomCommands";
|
||||
public static final String TEST_CONTROLLER_LISTENER_SESSION_REJECTS = "connection_sessionRejects";
|
||||
public static final String TEST_IS_SESSION_COMMAND_AVAILABLE = "testIsSessionCommandAvailable";
|
||||
|
@ -220,8 +220,20 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest {
|
||||
@Test
|
||||
public void sendCustomCommandWithMediaItem_mediaItemIdConvertedCorrectly() throws Exception {
|
||||
remoteService.setProxyForTest(TEST_MEDIA_ITEMS_WITH_BROWSE_ACTIONS);
|
||||
MediaBrowser mediaBrowser = createBrowser(/* listener= */ null);
|
||||
MediaBrowser mediaBrowser =
|
||||
createBrowser(
|
||||
/* connectionHints= */ Bundle.EMPTY,
|
||||
/* maxCommandsForMediaItems= */ 2,
|
||||
/* listener= */ null);
|
||||
MediaItem mediaItem = new MediaItem.Builder().setMediaId("mediaIdFromCommand").build();
|
||||
// When connected to a legacy browser service, the library root needs to be requested
|
||||
// before media item commands are available.
|
||||
LibraryResult<MediaItem> libraryRootResult =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> mediaBrowser.getLibraryRoot(new LibraryParams.Builder().build()))
|
||||
.get(TIMEOUT_MS, MILLISECONDS);
|
||||
assertThat(libraryRootResult.resultCode).isEqualTo(RESULT_SUCCESS);
|
||||
|
||||
SessionResult sessionResult =
|
||||
threadTestRule
|
||||
@ -232,12 +244,45 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest {
|
||||
new SessionCommand(MediaBrowserConstants.COMMAND_RADIO, Bundle.EMPTY),
|
||||
mediaItem,
|
||||
/* args= */ Bundle.EMPTY))
|
||||
.get();
|
||||
.get(TIMEOUT_MS, MILLISECONDS);
|
||||
|
||||
assertThat(sessionResult.extras.getString(MediaConstants.EXTRA_KEY_MEDIA_ID))
|
||||
.isEqualTo("mediaIdFromCommand");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendCustomCommandWithMediaItem_commandButtonNotAvailable_permissionDenied()
|
||||
throws Exception {
|
||||
remoteService.setProxyForTest(TEST_MEDIA_ITEMS_WITH_BROWSE_ACTIONS);
|
||||
MediaBrowser mediaBrowser =
|
||||
createBrowser(
|
||||
/* connectionHints= */ Bundle.EMPTY,
|
||||
/* maxCommandsForMediaItems= */ 0,
|
||||
/* listener= */ null);
|
||||
MediaItem mediaItem = new MediaItem.Builder().setMediaId("mediaIdFromCommand").build();
|
||||
// When connected to a legacy browser service, the library root needs to be requested
|
||||
// before media item commands are available.
|
||||
LibraryResult<MediaItem> libraryRootResult =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> mediaBrowser.getLibraryRoot(new LibraryParams.Builder().build()))
|
||||
.get(TIMEOUT_MS, MILLISECONDS);
|
||||
assertThat(libraryRootResult.resultCode).isEqualTo(RESULT_SUCCESS);
|
||||
|
||||
SessionResult sessionResult =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(
|
||||
() ->
|
||||
mediaBrowser.sendCustomCommand(
|
||||
new SessionCommand(MediaBrowserConstants.COMMAND_RADIO, Bundle.EMPTY),
|
||||
mediaItem,
|
||||
/* args= */ Bundle.EMPTY))
|
||||
.get(TIMEOUT_MS, MILLISECONDS);
|
||||
|
||||
assertThat(sessionResult.resultCode).isEqualTo(SessionResult.RESULT_ERROR_PERMISSION_DENIED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onChildrenChanged_subscribeAndUnsubscribe() throws Exception {
|
||||
String testParentId = "testOnChildrenChanged";
|
||||
|
@ -22,6 +22,7 @@ import static androidx.media3.test.session.common.CommonConstants.DEFAULT_TEST_N
|
||||
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.KEY_AVAILABLE_SESSION_COMMANDS;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_CUSTOM_LAYOUT;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_SESSION_ACTIVITY;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_IS_SESSION_COMMAND_AVAILABLE;
|
||||
@ -68,10 +69,8 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -554,7 +553,8 @@ public class MediaControllerTest {
|
||||
@Test
|
||||
public void getCommandButtonsForMediaItem() throws Exception {
|
||||
RemoteMediaSession session =
|
||||
createRemoteMediaSession(TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS, /* tokenExtras= */ null);
|
||||
createRemoteMediaSession(
|
||||
TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS, /* tokenExtras= */ Bundle.EMPTY);
|
||||
CommandButton playlistAddButton =
|
||||
new CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD)
|
||||
.setSessionCommand(
|
||||
@ -588,10 +588,41 @@ public class MediaControllerTest {
|
||||
session.cleanUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCommandButtonsForMediaItem_availableCommandsNotGranted_commandButtonsEmpty()
|
||||
throws Exception {
|
||||
RemoteMediaSession session =
|
||||
createRemoteMediaSession(
|
||||
TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE,
|
||||
/* tokenExtras= */ Bundle.EMPTY);
|
||||
MediaItem mediaItem =
|
||||
new MediaItem.Builder()
|
||||
.setMediaId("mediaId")
|
||||
.setMediaMetadata(
|
||||
new MediaMetadata.Builder()
|
||||
.setSupportedCommands(
|
||||
ImmutableList.of(
|
||||
MediaBrowserConstants.COMMAND_PLAYLIST_ADD,
|
||||
MediaBrowserConstants.COMMAND_RADIO,
|
||||
"invalid"))
|
||||
.build())
|
||||
.build();
|
||||
MediaController controller = controllerTestRule.createController(session.getToken());
|
||||
|
||||
ImmutableList<CommandButton> commandButtons =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.getCommandButtonsForMediaItem(mediaItem));
|
||||
|
||||
assertThat(commandButtons).isEmpty();
|
||||
session.cleanUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendCustomCommandForMediaItem() throws Exception {
|
||||
RemoteMediaSession session =
|
||||
createRemoteMediaSession(TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS, /* tokenExtras= */ null);
|
||||
createRemoteMediaSession(
|
||||
TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS, /* tokenExtras= */ Bundle.EMPTY);
|
||||
MediaItem mediaItem =
|
||||
new MediaItem.Builder()
|
||||
.setMediaId("mediaId-1")
|
||||
@ -601,11 +632,9 @@ public class MediaControllerTest {
|
||||
ImmutableList.of(MediaBrowserConstants.COMMAND_PLAYLIST_ADD))
|
||||
.build())
|
||||
.build();
|
||||
CountDownLatch latch = new CountDownLatch(/* count= */ 1);
|
||||
AtomicReference<SessionResult> sessionResultRef = new AtomicReference<>();
|
||||
MediaController controller = controllerTestRule.createController(session.getToken());
|
||||
|
||||
Futures.addCallback(
|
||||
SessionResult sessionResult =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(
|
||||
@ -614,29 +643,48 @@ public class MediaControllerTest {
|
||||
controller.getCommandButtonsForMediaItem(mediaItem).get(0);
|
||||
return controller.sendCustomCommand(
|
||||
commandButton.sessionCommand, mediaItem, Bundle.EMPTY);
|
||||
}),
|
||||
new FutureCallback<SessionResult>() {
|
||||
@Override
|
||||
public void onSuccess(SessionResult result) {
|
||||
sessionResultRef.set(result);
|
||||
latch.countDown();
|
||||
}
|
||||
})
|
||||
.get(TIMEOUT_MS, MILLISECONDS);
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
latch.countDown();
|
||||
}
|
||||
},
|
||||
MoreExecutors.directExecutor());
|
||||
|
||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(sessionResultRef.get()).isNotNull();
|
||||
assertThat(sessionResultRef.get().resultCode).isEqualTo(SessionResult.RESULT_SUCCESS);
|
||||
assertThat(sessionResultRef.get().extras.getString(MediaConstants.EXTRA_KEY_MEDIA_ID))
|
||||
assertThat(sessionResult.resultCode).isEqualTo(SessionResult.RESULT_SUCCESS);
|
||||
assertThat(sessionResult.extras.getString(MediaConstants.EXTRA_KEY_MEDIA_ID))
|
||||
.isEqualTo("mediaId-1");
|
||||
session.cleanUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendCustomCommandForMediaItem_availableCommandsNotGranted_permissionDenied()
|
||||
throws Exception {
|
||||
RemoteMediaSession session =
|
||||
createRemoteMediaSession(
|
||||
TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE,
|
||||
/* tokenExtras= */ Bundle.EMPTY);
|
||||
SessionCommand playlistAddSessionCommand =
|
||||
new SessionCommand(MediaBrowserConstants.COMMAND_PLAYLIST_ADD, /* extras= */ Bundle.EMPTY);
|
||||
MediaItem mediaItem =
|
||||
new MediaItem.Builder()
|
||||
.setMediaId("mediaId-1")
|
||||
.setMediaMetadata(
|
||||
new MediaMetadata.Builder()
|
||||
.setSupportedCommands(
|
||||
ImmutableList.of(MediaBrowserConstants.COMMAND_PLAYLIST_ADD))
|
||||
.build())
|
||||
.build();
|
||||
MediaController controller = controllerTestRule.createController(session.getToken());
|
||||
|
||||
SessionResult sessionResult =
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(
|
||||
() ->
|
||||
controller.sendCustomCommand(
|
||||
playlistAddSessionCommand, mediaItem, Bundle.EMPTY))
|
||||
.get(TIMEOUT_MS, MILLISECONDS);
|
||||
|
||||
assertThat(sessionResult.resultCode).isEqualTo(SessionResult.RESULT_ERROR_PERMISSION_DENIED);
|
||||
session.cleanUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionExtras_includedInConnectionStateWhenConnecting() throws Exception {
|
||||
RemoteMediaSession session =
|
||||
|
@ -64,6 +64,7 @@ import static androidx.media3.test.session.common.MediaSessionConstants.NOTIFICA
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_COMMAND_GET_TRACKS;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_CONTROLLER_LISTENER_SESSION_REJECTS;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_CUSTOM_LAYOUT;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_SESSION_ACTIVITY;
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_IS_SESSION_COMMAND_AVAILABLE;
|
||||
@ -237,6 +238,7 @@ public class MediaSessionProviderService extends Service {
|
||||
break;
|
||||
}
|
||||
case TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS:
|
||||
case TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE:
|
||||
{
|
||||
CommandButton playlistAddButton =
|
||||
new CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD)
|
||||
@ -256,6 +258,10 @@ public class MediaSessionProviderService extends Service {
|
||||
@Override
|
||||
public MediaSession.ConnectionResult onConnect(
|
||||
MediaSession session, ControllerInfo controller) {
|
||||
if (sessionId.equals(
|
||||
TEST_GET_COMMAND_BUTTONS_FOR_MEDIA_ITEMS_COMMANDS_NOT_AVAILABLE)) {
|
||||
return MediaSession.Callback.super.onConnect(session, controller);
|
||||
}
|
||||
return new MediaSession.ConnectionResult.AcceptedResultBuilder(session)
|
||||
.setAvailableSessionCommands(
|
||||
new SessionCommands.Builder()
|
||||
|
@ -46,7 +46,6 @@ import android.support.v4.media.MediaBrowserCompat;
|
||||
import android.support.v4.media.MediaBrowserCompat.MediaItem;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat.Callback;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -89,7 +88,7 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
||||
instance = this;
|
||||
}
|
||||
sessionCompat = new MediaSessionCompat(this, TAG);
|
||||
sessionCompat.setCallback(new Callback() {});
|
||||
sessionCompat.setCallback(new MediaSessionCompat.Callback() {});
|
||||
sessionCompat.setActive(true);
|
||||
setSessionToken(sessionCompat.getSessionToken());
|
||||
|
||||
@ -401,27 +400,6 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
||||
}
|
||||
extras.putParcelableArrayList(
|
||||
BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST, browseActionList);
|
||||
|
||||
session.setPlaybackState(
|
||||
new PlaybackStateCompat.Builder()
|
||||
.setState(
|
||||
PlaybackStateCompat.STATE_PLAYING,
|
||||
/* position= */ 123L,
|
||||
/* playbackSpeed= */ 1.0f)
|
||||
.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
MediaBrowserConstants.COMMAND_PLAYLIST_ADD,
|
||||
"Add to playlist",
|
||||
CommandButton.ICON_PLAYLIST_ADD)
|
||||
.build())
|
||||
.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
MediaBrowserConstants.COMMAND_RADIO,
|
||||
"Radio station",
|
||||
CommandButton.ICON_RADIO)
|
||||
.build())
|
||||
.build());
|
||||
|
||||
return new BrowserRoot(ROOT_ID, extras);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user