From ae875648a72b08f24c1e41cc5822fc24265dfd9b Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 12 Apr 2023 09:33:46 +0100 Subject: [PATCH] Update available commands when setting a new player in MediaSession #minor-release PiperOrigin-RevId: 523633865 --- RELEASENOTES.md | 2 ++ .../media3/session/MediaSessionImpl.java | 29 ++++++++++--------- .../test/session/common/CommonConstants.java | 1 + .../session/MediaControllerListenerTest.java | 13 ++++++++- .../session/MediaSessionProviderService.java | 5 ++++ .../media3/session/RemoteMediaSession.java | 7 +++++ 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8b50b47f2a..fbab31a0d0 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -37,6 +37,8 @@ * Add missing forwarding of `MediaSession.broadcastCustomCommand` to the legacy `MediaControllerCompat.Callback.onSessionEvent` ([#293](https://github.com/androidx/media/issues/293)). + * Fix bug where calling `MediaSession.setPlayer` doesn't update the + available commands. * Audio: * Fix bug where some playbacks fail when tunneling is enabled and `AudioProcessors` are active, e.g. for gapless trimming diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java index ba76484f43..a0b2a3cf15 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -15,7 +15,6 @@ */ package androidx.media3.session; -import static androidx.media3.common.Player.COMMAND_GET_TRACKS; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Util.castNonNull; @@ -279,8 +278,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; } playerInfo = newPlayerWrapper.createPlayerInfoForBundling(); - onPlayerInfoChangedHandler.sendPlayerInfoChangedMessage( - /* excludeTimeline= */ false, /* excludeTracks= */ false); + handleAvailablePlayerCommandsChanged(newPlayerWrapper.getAvailableCommands()); } public void release() { @@ -773,6 +771,20 @@ import org.checkerframework.checker.initialization.qual.Initialized; } } + private void handleAvailablePlayerCommandsChanged(Player.Commands availableCommands) { + // Update PlayerInfo and do not force exclude elements in case they need to be updated because + // an available command has been removed. + onPlayerInfoChangedHandler.sendPlayerInfoChangedMessage( + /* excludeTimeline= */ false, /* excludeTracks= */ false); + dispatchRemoteControllerTaskWithoutReturn( + (callback, seq) -> callback.onAvailableCommandsChangedFromPlayer(seq, availableCommands)); + + // Forcefully update playback info to update VolumeProviderCompat in case + // COMMAND_ADJUST_DEVICE_VOLUME or COMMAND_SET_DEVICE_VOLUME value has changed. + dispatchRemoteControllerTaskToLegacyStub( + (callback, seq) -> callback.onDeviceInfoChanged(seq, playerInfo.deviceInfo)); + } + /* @FunctionalInterface */ interface RemoteControllerTask { @@ -1183,16 +1195,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; if (player == null) { return; } - boolean excludeTracks = !availableCommands.contains(COMMAND_GET_TRACKS); - session.onPlayerInfoChangedHandler.sendPlayerInfoChangedMessage( - /* excludeTimeline= */ false, excludeTracks); - session.dispatchRemoteControllerTaskWithoutReturn( - (callback, seq) -> callback.onAvailableCommandsChangedFromPlayer(seq, availableCommands)); - - // Forcefully update playback info to update VolumeProviderCompat in case - // COMMAND_ADJUST_DEVICE_VOLUME or COMMAND_SET_DEVICE_VOLUME value has changed. - session.dispatchRemoteControllerTaskToLegacyStub( - (callback, seq) -> callback.onDeviceInfoChanged(seq, session.playerInfo.deviceInfo)); + session.handleAvailablePlayerCommandsChanged(availableCommands); } @Override diff --git a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java index b310ad34fc..f7642e9dd2 100644 --- a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java +++ b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java @@ -101,6 +101,7 @@ public class CommonConstants { public static final String KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS = "maxSeekToPreviousPositionMs"; public static final String KEY_TRACK_SELECTION_PARAMETERS = "trackSelectionParameters"; public static final String KEY_CURRENT_TRACKS = "currentTracks"; + public static final String KEY_AVAILABLE_COMMANDS = "availableCommands"; // SessionCompat arguments public static final String KEY_SESSION_COMPAT_TOKEN = "sessionCompatToken"; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java index 9b77490203..add2c263cc 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java @@ -326,6 +326,8 @@ public class MediaControllerListenerTest { @Player.RepeatMode int testRepeatMode = Player.REPEAT_MODE_ALL; int testCurrentAdGroupIndex = 33; int testCurrentAdIndexInAdGroup = 11; + Commands testCommands = + new Commands.Builder().addAllCommands().remove(Player.COMMAND_STOP).build(); AtomicInteger stateRef = new AtomicInteger(); AtomicReference timelineRef = new AtomicReference<>(); AtomicReference playlistMetadataRef = new AtomicReference<>(); @@ -335,7 +337,8 @@ public class MediaControllerListenerTest { AtomicInteger currentAdIndexInAdGroupRef = new AtomicInteger(); AtomicBoolean shuffleModeEnabledRef = new AtomicBoolean(); AtomicInteger repeatModeRef = new AtomicInteger(); - CountDownLatch latch = new CountDownLatch(7); + AtomicReference commandsRef = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(8); MediaController controller = controllerTestRule.createController(remoteSession.getToken()); threadTestRule .getHandler() @@ -343,6 +346,12 @@ public class MediaControllerListenerTest { () -> controller.addListener( new Player.Listener() { + @Override + public void onAvailableCommandsChanged(Commands availableCommands) { + commandsRef.set(availableCommands); + latch.countDown(); + } + @Override public void onAudioAttributesChanged(AudioAttributes attributes) { audioAttributesRef.set(attributes); @@ -402,6 +411,7 @@ public class MediaControllerListenerTest { .setIsPlayingAd(true) .setCurrentAdGroupIndex(testCurrentAdGroupIndex) .setCurrentAdIndexInAdGroup(testCurrentAdIndexInAdGroup) + .setAvailableCommands(testCommands) .build(); remoteSession.setPlayer(playerConfig); @@ -415,6 +425,7 @@ public class MediaControllerListenerTest { assertThat(currentAdIndexInAdGroupRef.get()).isEqualTo(testCurrentAdIndexInAdGroup); assertThat(shuffleModeEnabledRef.get()).isEqualTo(testShuffleModeEnabled); assertThat(repeatModeRef.get()).isEqualTo(testRepeatMode); + assertThat(commandsRef.get()).isEqualTo(testCommands); } @Test diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java index 053405b83f..4af259a69c 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java @@ -18,6 +18,7 @@ package androidx.media3.session; import static androidx.media3.common.Player.COMMAND_GET_TRACKS; import static androidx.media3.test.session.common.CommonConstants.ACTION_MEDIA3_SESSION; import static androidx.media3.test.session.common.CommonConstants.KEY_AUDIO_ATTRIBUTES; +import static androidx.media3.test.session.common.CommonConstants.KEY_AVAILABLE_COMMANDS; import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_PERCENTAGE; import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_POSITION; import static androidx.media3.test.session.common.CommonConstants.KEY_CONTENT_BUFFERED_POSITION; @@ -395,6 +396,10 @@ public class MediaSessionProviderService extends Service { player.trackSelectionParameters = TrackSelectionParameters.fromBundle(trackSelectionParametersBundle); } + @Nullable Bundle availableCommandsBundle = config.getBundle(KEY_AVAILABLE_COMMANDS); + if (availableCommandsBundle != null) { + player.commands = Player.Commands.CREATOR.fromBundle(availableCommandsBundle); + } return player; } diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java index 68937d0dd2..392a382129 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java @@ -17,6 +17,7 @@ package androidx.media3.session; import static androidx.media3.test.session.common.CommonConstants.ACTION_MEDIA3_SESSION; import static androidx.media3.test.session.common.CommonConstants.KEY_AUDIO_ATTRIBUTES; +import static androidx.media3.test.session.common.CommonConstants.KEY_AVAILABLE_COMMANDS; import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_PERCENTAGE; import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_POSITION; import static androidx.media3.test.session.common.CommonConstants.KEY_CONTENT_BUFFERED_POSITION; @@ -740,6 +741,12 @@ public class RemoteMediaSession { return this; } + @CanIgnoreReturnValue + public MockPlayerConfigBuilder setAvailableCommands(Player.Commands availableCommands) { + bundle.putBundle(KEY_AVAILABLE_COMMANDS, availableCommands.toBundle()); + return this; + } + public Bundle build() { return bundle; }