Update available commands when setting a new player in MediaSession
#minor-release PiperOrigin-RevId: 523633865
This commit is contained in:
parent
7ee53219ff
commit
ae875648a7
@ -37,6 +37,8 @@
|
|||||||
* Add missing forwarding of `MediaSession.broadcastCustomCommand` to the
|
* Add missing forwarding of `MediaSession.broadcastCustomCommand` to the
|
||||||
legacy `MediaControllerCompat.Callback.onSessionEvent`
|
legacy `MediaControllerCompat.Callback.onSessionEvent`
|
||||||
([#293](https://github.com/androidx/media/issues/293)).
|
([#293](https://github.com/androidx/media/issues/293)).
|
||||||
|
* Fix bug where calling `MediaSession.setPlayer` doesn't update the
|
||||||
|
available commands.
|
||||||
* Audio:
|
* Audio:
|
||||||
* Fix bug where some playbacks fail when tunneling is enabled and
|
* Fix bug where some playbacks fail when tunneling is enabled and
|
||||||
`AudioProcessors` are active, e.g. for gapless trimming
|
`AudioProcessors` are active, e.g. for gapless trimming
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.session;
|
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.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.common.util.Util.castNonNull;
|
import static androidx.media3.common.util.Util.castNonNull;
|
||||||
@ -279,8 +278,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
|||||||
}
|
}
|
||||||
|
|
||||||
playerInfo = newPlayerWrapper.createPlayerInfoForBundling();
|
playerInfo = newPlayerWrapper.createPlayerInfoForBundling();
|
||||||
onPlayerInfoChangedHandler.sendPlayerInfoChangedMessage(
|
handleAvailablePlayerCommandsChanged(newPlayerWrapper.getAvailableCommands());
|
||||||
/* excludeTimeline= */ false, /* excludeTracks= */ false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
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 */
|
/* @FunctionalInterface */
|
||||||
interface RemoteControllerTask {
|
interface RemoteControllerTask {
|
||||||
|
|
||||||
@ -1183,16 +1195,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
|||||||
if (player == null) {
|
if (player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean excludeTracks = !availableCommands.contains(COMMAND_GET_TRACKS);
|
session.handleAvailablePlayerCommandsChanged(availableCommands);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -101,6 +101,7 @@ public class CommonConstants {
|
|||||||
public static final String KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS = "maxSeekToPreviousPositionMs";
|
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_TRACK_SELECTION_PARAMETERS = "trackSelectionParameters";
|
||||||
public static final String KEY_CURRENT_TRACKS = "currentTracks";
|
public static final String KEY_CURRENT_TRACKS = "currentTracks";
|
||||||
|
public static final String KEY_AVAILABLE_COMMANDS = "availableCommands";
|
||||||
|
|
||||||
// SessionCompat arguments
|
// SessionCompat arguments
|
||||||
public static final String KEY_SESSION_COMPAT_TOKEN = "sessionCompatToken";
|
public static final String KEY_SESSION_COMPAT_TOKEN = "sessionCompatToken";
|
||||||
|
@ -326,6 +326,8 @@ public class MediaControllerListenerTest {
|
|||||||
@Player.RepeatMode int testRepeatMode = Player.REPEAT_MODE_ALL;
|
@Player.RepeatMode int testRepeatMode = Player.REPEAT_MODE_ALL;
|
||||||
int testCurrentAdGroupIndex = 33;
|
int testCurrentAdGroupIndex = 33;
|
||||||
int testCurrentAdIndexInAdGroup = 11;
|
int testCurrentAdIndexInAdGroup = 11;
|
||||||
|
Commands testCommands =
|
||||||
|
new Commands.Builder().addAllCommands().remove(Player.COMMAND_STOP).build();
|
||||||
AtomicInteger stateRef = new AtomicInteger();
|
AtomicInteger stateRef = new AtomicInteger();
|
||||||
AtomicReference<Timeline> timelineRef = new AtomicReference<>();
|
AtomicReference<Timeline> timelineRef = new AtomicReference<>();
|
||||||
AtomicReference<MediaMetadata> playlistMetadataRef = new AtomicReference<>();
|
AtomicReference<MediaMetadata> playlistMetadataRef = new AtomicReference<>();
|
||||||
@ -335,7 +337,8 @@ public class MediaControllerListenerTest {
|
|||||||
AtomicInteger currentAdIndexInAdGroupRef = new AtomicInteger();
|
AtomicInteger currentAdIndexInAdGroupRef = new AtomicInteger();
|
||||||
AtomicBoolean shuffleModeEnabledRef = new AtomicBoolean();
|
AtomicBoolean shuffleModeEnabledRef = new AtomicBoolean();
|
||||||
AtomicInteger repeatModeRef = new AtomicInteger();
|
AtomicInteger repeatModeRef = new AtomicInteger();
|
||||||
CountDownLatch latch = new CountDownLatch(7);
|
AtomicReference<Commands> commandsRef = new AtomicReference<>();
|
||||||
|
CountDownLatch latch = new CountDownLatch(8);
|
||||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||||
threadTestRule
|
threadTestRule
|
||||||
.getHandler()
|
.getHandler()
|
||||||
@ -343,6 +346,12 @@ public class MediaControllerListenerTest {
|
|||||||
() ->
|
() ->
|
||||||
controller.addListener(
|
controller.addListener(
|
||||||
new Player.Listener() {
|
new Player.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onAvailableCommandsChanged(Commands availableCommands) {
|
||||||
|
commandsRef.set(availableCommands);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAudioAttributesChanged(AudioAttributes attributes) {
|
public void onAudioAttributesChanged(AudioAttributes attributes) {
|
||||||
audioAttributesRef.set(attributes);
|
audioAttributesRef.set(attributes);
|
||||||
@ -402,6 +411,7 @@ public class MediaControllerListenerTest {
|
|||||||
.setIsPlayingAd(true)
|
.setIsPlayingAd(true)
|
||||||
.setCurrentAdGroupIndex(testCurrentAdGroupIndex)
|
.setCurrentAdGroupIndex(testCurrentAdGroupIndex)
|
||||||
.setCurrentAdIndexInAdGroup(testCurrentAdIndexInAdGroup)
|
.setCurrentAdIndexInAdGroup(testCurrentAdIndexInAdGroup)
|
||||||
|
.setAvailableCommands(testCommands)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
remoteSession.setPlayer(playerConfig);
|
remoteSession.setPlayer(playerConfig);
|
||||||
@ -415,6 +425,7 @@ public class MediaControllerListenerTest {
|
|||||||
assertThat(currentAdIndexInAdGroupRef.get()).isEqualTo(testCurrentAdIndexInAdGroup);
|
assertThat(currentAdIndexInAdGroupRef.get()).isEqualTo(testCurrentAdIndexInAdGroup);
|
||||||
assertThat(shuffleModeEnabledRef.get()).isEqualTo(testShuffleModeEnabled);
|
assertThat(shuffleModeEnabledRef.get()).isEqualTo(testShuffleModeEnabled);
|
||||||
assertThat(repeatModeRef.get()).isEqualTo(testRepeatMode);
|
assertThat(repeatModeRef.get()).isEqualTo(testRepeatMode);
|
||||||
|
assertThat(commandsRef.get()).isEqualTo(testCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.session;
|
|||||||
import static androidx.media3.common.Player.COMMAND_GET_TRACKS;
|
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.ACTION_MEDIA3_SESSION;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.KEY_AUDIO_ATTRIBUTES;
|
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_PERCENTAGE;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_POSITION;
|
import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_POSITION;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.KEY_CONTENT_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 =
|
player.trackSelectionParameters =
|
||||||
TrackSelectionParameters.fromBundle(trackSelectionParametersBundle);
|
TrackSelectionParameters.fromBundle(trackSelectionParametersBundle);
|
||||||
}
|
}
|
||||||
|
@Nullable Bundle availableCommandsBundle = config.getBundle(KEY_AVAILABLE_COMMANDS);
|
||||||
|
if (availableCommandsBundle != null) {
|
||||||
|
player.commands = Player.Commands.CREATOR.fromBundle(availableCommandsBundle);
|
||||||
|
}
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.ACTION_MEDIA3_SESSION;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.KEY_AUDIO_ATTRIBUTES;
|
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_PERCENTAGE;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_POSITION;
|
import static androidx.media3.test.session.common.CommonConstants.KEY_BUFFERED_POSITION;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.KEY_CONTENT_BUFFERED_POSITION;
|
import static androidx.media3.test.session.common.CommonConstants.KEY_CONTENT_BUFFERED_POSITION;
|
||||||
@ -740,6 +741,12 @@ public class RemoteMediaSession {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public MockPlayerConfigBuilder setAvailableCommands(Player.Commands availableCommands) {
|
||||||
|
bundle.putBundle(KEY_AVAILABLE_COMMANDS, availableCommands.toBundle());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Bundle build() {
|
public Bundle build() {
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user