Use MediaUtils.intersect in MediaControllerImplBase

PiperOrigin-RevId: 550566322
This commit is contained in:
bachinger 2023-07-24 16:21:43 +01:00 committed by Rohit Singh
parent 2c19399d3e
commit a90ec96425
6 changed files with 77 additions and 13 deletions

View file

@ -149,7 +149,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerCommandsFromSession = Commands.EMPTY; playerCommandsFromSession = Commands.EMPTY;
playerCommandsFromPlayer = Commands.EMPTY; playerCommandsFromPlayer = Commands.EMPTY;
intersectedPlayerCommands = intersectedPlayerCommands =
createIntersectedCommands(playerCommandsFromSession, playerCommandsFromPlayer); createIntersectedCommandsEnsuringCommandReleaseAvailable(
playerCommandsFromSession, playerCommandsFromPlayer);
listeners = listeners =
new ListenerSet<>( new ListenerSet<>(
applicationLooper, applicationLooper,
@ -2479,7 +2480,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerCommandsFromSession = result.playerCommandsFromSession; playerCommandsFromSession = result.playerCommandsFromSession;
playerCommandsFromPlayer = result.playerCommandsFromPlayer; playerCommandsFromPlayer = result.playerCommandsFromPlayer;
intersectedPlayerCommands = intersectedPlayerCommands =
createIntersectedCommands(playerCommandsFromSession, playerCommandsFromPlayer); createIntersectedCommandsEnsuringCommandReleaseAvailable(
playerCommandsFromSession, playerCommandsFromPlayer);
customLayout = customLayout =
CommandButton.getEnabledCommandButtons( CommandButton.getEnabledCommandButtons(
result.customLayout, sessionCommands, intersectedPlayerCommands); result.customLayout, sessionCommands, intersectedPlayerCommands);
@ -2638,7 +2640,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerCommandsFromSession = playerCommands; playerCommandsFromSession = playerCommands;
Commands prevIntersectedPlayerCommands = intersectedPlayerCommands; Commands prevIntersectedPlayerCommands = intersectedPlayerCommands;
intersectedPlayerCommands = intersectedPlayerCommands =
createIntersectedCommands(playerCommandsFromSession, playerCommandsFromPlayer); createIntersectedCommandsEnsuringCommandReleaseAvailable(
playerCommandsFromSession, playerCommandsFromPlayer);
intersectedPlayerCommandsChanged = intersectedPlayerCommandsChanged =
!Util.areEqual(intersectedPlayerCommands, prevIntersectedPlayerCommands); !Util.areEqual(intersectedPlayerCommands, prevIntersectedPlayerCommands);
} }
@ -2679,7 +2682,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerCommandsFromPlayer = commandsFromPlayer; playerCommandsFromPlayer = commandsFromPlayer;
Commands prevIntersectedPlayerCommands = intersectedPlayerCommands; Commands prevIntersectedPlayerCommands = intersectedPlayerCommands;
intersectedPlayerCommands = intersectedPlayerCommands =
createIntersectedCommands(playerCommandsFromSession, playerCommandsFromPlayer); createIntersectedCommandsEnsuringCommandReleaseAvailable(
playerCommandsFromSession, playerCommandsFromPlayer);
boolean intersectedPlayerCommandsChanged = boolean intersectedPlayerCommandsChanged =
!Util.areEqual(intersectedPlayerCommands, prevIntersectedPlayerCommands); !Util.areEqual(intersectedPlayerCommands, prevIntersectedPlayerCommands);
if (intersectedPlayerCommandsChanged) { if (intersectedPlayerCommandsChanged) {
@ -3082,17 +3086,13 @@ import org.checkerframework.checker.nullness.qual.NonNull;
return newMediaItemIndex; return newMediaItemIndex;
} }
private static Commands createIntersectedCommands( private static Commands createIntersectedCommandsEnsuringCommandReleaseAvailable(
Commands commandFromSession, Commands commandsFromPlayer) { Commands commandFromSession, Commands commandsFromPlayer) {
Commands.Builder intersectCommandsBuilder = new Commands.Builder(); Commands intersectedCommands = MediaUtils.intersect(commandFromSession, commandsFromPlayer);
// Release is always available as it just releases the connection, not the underlying player. // Release is always available as it just releases the connection, not the underlying player.
intersectCommandsBuilder.add(Player.COMMAND_RELEASE); return intersectedCommands.contains(Player.COMMAND_RELEASE)
for (int i = 0; i < commandFromSession.size(); i++) { ? intersectedCommands
if (commandsFromPlayer.contains(commandFromSession.get(i))) { : intersectedCommands.buildUpon().add(Player.COMMAND_RELEASE).build();
intersectCommandsBuilder.add(commandFromSession.get(i));
}
}
return intersectCommandsBuilder.build();
} }
// This will be called on the main thread. // This will be called on the main thread.

View file

@ -100,6 +100,7 @@ interface IRemoteMediaController {
int pageSize, int pageSize,
in Bundle libraryParams); in Bundle libraryParams);
Bundle getCustomLayout(String controllerId); Bundle getCustomLayout(String controllerId);
Bundle getAvailableCommands(String controllerId);
Bundle getItem(String controllerId, String mediaId); Bundle getItem(String controllerId, String mediaId);
Bundle search(String controllerId, String query, in Bundle libraryParams); Bundle search(String controllerId, String query, in Bundle libraryParams);
Bundle getSearchResult( Bundle getSearchResult(

View file

@ -422,6 +422,32 @@ public class MediaControllerTest {
session.cleanUp(); session.cleanUp();
} }
@Test
public void getAvailableCommands_emptyPlayerCommands_commandReleaseStillAvailable()
throws Exception {
CountDownLatch latch = new CountDownLatch(1);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
List<Player.Commands> capturedCommands = new ArrayList<>();
controller.addListener(
new Player.Listener() {
@Override
public void onAvailableCommandsChanged(Player.Commands availableCommands) {
capturedCommands.add(availableCommands);
capturedCommands.add(controller.getAvailableCommands());
latch.countDown();
}
});
remoteSession.setAvailableCommands(SessionCommands.EMPTY, Player.Commands.EMPTY);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(capturedCommands).hasSize(2);
assertThat(capturedCommands.get(0).size()).isEqualTo(1);
assertThat(capturedCommands.get(0).contains(Player.COMMAND_RELEASE)).isTrue();
assertThat(capturedCommands.get(1).size()).isEqualTo(1);
assertThat(capturedCommands.get(1).contains(Player.COMMAND_RELEASE)).isTrue();
}
@Test @Test
public void getPackageName() throws Exception { public void getPackageName() throws Exception {
MediaController controller = controllerTestRule.createController(remoteSession.getToken()); MediaController controller = controllerTestRule.createController(remoteSession.getToken());

View file

@ -193,6 +193,31 @@ public class MediaSessionCallbackTest {
.isEqualTo(RESULT_SUCCESS); .isEqualTo(RESULT_SUCCESS);
} }
@Test
public void onConnect_emptyPlayerCommands_commandReleaseAlwaysIncluded() throws Exception {
MediaSession.Callback callback =
new MediaSession.Callback() {
@Override
public MediaSession.ConnectionResult onConnect(
MediaSession session, ControllerInfo controller) {
return new AcceptedResultBuilder(session)
.setAvailablePlayerCommands(Player.Commands.EMPTY)
.build();
}
};
MediaSession session =
sessionTestRule.ensureReleaseAfterTest(
new MediaSession.Builder(context, player)
.setCallback(callback)
.setId("onConnect_emptyPlayerCommands_commandReleaseAlwaysIncluded")
.build());
RemoteMediaController remoteController =
controllerTestRule.createRemoteController(session.getToken());
assertThat(remoteController.getAvailableCommands().size()).isEqualTo(1);
assertThat(remoteController.getAvailableCommands().contains(Player.COMMAND_RELEASE)).isTrue();
}
@Test @Test
public void onPostConnect_afterConnected() throws Exception { public void onPostConnect_afterConnected() throws Exception {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);

View file

@ -823,6 +823,12 @@ public class MediaControllerProviderService extends Service {
return bundle; return bundle;
} }
@Override
public Bundle getAvailableCommands(String controllerId) throws RemoteException {
MediaController controller = mediaControllerMap.get(controllerId);
return runOnHandler(controller::getAvailableCommands).toBundle();
}
@Override @Override
public Bundle getItem(String controllerId, String mediaId) throws RemoteException { public Bundle getItem(String controllerId, String mediaId) throws RemoteException {
MediaBrowser browser = (MediaBrowser) mediaControllerMap.get(controllerId); MediaBrowser browser = (MediaBrowser) mediaControllerMap.get(controllerId);

View file

@ -34,6 +34,7 @@ import androidx.media3.common.C;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaMetadata; import androidx.media3.common.MediaMetadata;
import androidx.media3.common.PlaybackParameters; import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.Player.RepeatMode; import androidx.media3.common.Player.RepeatMode;
import androidx.media3.common.Rating; import androidx.media3.common.Rating;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
@ -362,6 +363,11 @@ public class RemoteMediaController {
return customLayout.build(); return customLayout.build();
} }
public Player.Commands getAvailableCommands() throws RemoteException {
Bundle commandsBundle = binder.getAvailableCommands(controllerId);
return Player.Commands.CREATOR.fromBundle(commandsBundle);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Non-public methods // Non-public methods
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////