Propagate media3 session extras to media1 PlaybackStateCompat
PiperOrigin-RevId: 642299178
This commit is contained in:
parent
b145a96c79
commit
2456669398
@ -26,6 +26,9 @@
|
||||
and how to resolve the error if possible.
|
||||
* Publish the code for the media3 controller test app that can be used to
|
||||
test interactions with apps publishing a media session.
|
||||
* Propagate extras passed to media3's
|
||||
`MediaSession[Builder].setSessionExtras()` to a media1 controller's
|
||||
`PlaybackStateCompat.getExtras()`.
|
||||
* UI:
|
||||
* Add customisation of various icons in `PlayerControlView` through xml
|
||||
attributes to allow different drawables per `PlayerView` instance,
|
||||
|
@ -240,7 +240,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
playIfSuppressed,
|
||||
customLayout,
|
||||
connectionResult.availableSessionCommands,
|
||||
connectionResult.availablePlayerCommands);
|
||||
connectionResult.availablePlayerCommands,
|
||||
sessionExtras);
|
||||
this.playerWrapper = playerWrapper;
|
||||
postOrRun(
|
||||
applicationHandler,
|
||||
@ -265,7 +266,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
playIfSuppressed,
|
||||
playerWrapper.getCustomLayout(),
|
||||
playerWrapper.getAvailableSessionCommands(),
|
||||
playerWrapper.getAvailablePlayerCommands()));
|
||||
playerWrapper.getAvailablePlayerCommands(),
|
||||
playerWrapper.getLegacyExtras()));
|
||||
}
|
||||
|
||||
private void setPlayerInternal(
|
||||
|
@ -1113,6 +1113,8 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
||||
@Override
|
||||
public void onSessionExtrasChanged(int seq, Bundle sessionExtras) {
|
||||
sessionCompat.setExtras(sessionExtras);
|
||||
sessionImpl.getPlayerWrapper().setLegacyExtras(sessionExtras);
|
||||
sessionCompat.setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package androidx.media3.session;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.common.util.Util.msToUs;
|
||||
@ -70,6 +71,7 @@ import java.util.List;
|
||||
private int legacyStatusCode;
|
||||
@Nullable private String legacyErrorMessage;
|
||||
@Nullable private Bundle legacyErrorExtras;
|
||||
@Nullable private Bundle legacyExtras;
|
||||
private ImmutableList<CommandButton> customLayout;
|
||||
private SessionCommands availableSessionCommands;
|
||||
private Commands availablePlayerCommands;
|
||||
@ -79,12 +81,14 @@ import java.util.List;
|
||||
boolean playIfSuppressed,
|
||||
ImmutableList<CommandButton> customLayout,
|
||||
SessionCommands availableSessionCommands,
|
||||
Commands availablePlayerCommands) {
|
||||
Commands availablePlayerCommands,
|
||||
@Nullable Bundle legacyExtras) {
|
||||
super(player);
|
||||
this.playIfSuppressed = playIfSuppressed;
|
||||
this.customLayout = customLayout;
|
||||
this.availableSessionCommands = availableSessionCommands;
|
||||
this.availablePlayerCommands = availablePlayerCommands;
|
||||
this.legacyExtras = legacyExtras;
|
||||
legacyStatusCode = STATUS_CODE_SUCCESS_COMPAT;
|
||||
}
|
||||
|
||||
@ -110,6 +114,19 @@ import java.util.List;
|
||||
return customLayout;
|
||||
}
|
||||
|
||||
public void setLegacyExtras(@Nullable Bundle extras) {
|
||||
if (extras != null) {
|
||||
checkArgument(!extras.containsKey(EXTRAS_KEY_PLAYBACK_SPEED_COMPAT));
|
||||
checkArgument(!extras.containsKey(EXTRAS_KEY_MEDIA_ID_COMPAT));
|
||||
}
|
||||
this.legacyExtras = extras;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Bundle getLegacyExtras() {
|
||||
return legacyExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the legacy error code.
|
||||
*
|
||||
@ -1000,6 +1017,13 @@ import java.util.List;
|
||||
|
||||
public PlaybackStateCompat createPlaybackStateCompat() {
|
||||
if (legacyStatusCode != STATUS_CODE_SUCCESS_COMPAT) {
|
||||
Bundle extras;
|
||||
if (legacyExtras != null) {
|
||||
extras = new Bundle(checkNotNull(legacyErrorExtras));
|
||||
extras.putAll(legacyExtras);
|
||||
} else {
|
||||
extras = checkNotNull(legacyErrorExtras);
|
||||
}
|
||||
return new PlaybackStateCompat.Builder()
|
||||
.setState(
|
||||
PlaybackStateCompat.STATE_ERROR,
|
||||
@ -1009,7 +1033,7 @@ import java.util.List;
|
||||
.setActions(0)
|
||||
.setBufferedPosition(0)
|
||||
.setErrorMessage(legacyStatusCode, checkNotNull(legacyErrorMessage))
|
||||
.setExtras(checkNotNull(legacyErrorExtras))
|
||||
.setExtras(extras)
|
||||
.build();
|
||||
}
|
||||
@Nullable PlaybackException playerError = getPlayerError();
|
||||
@ -1027,7 +1051,7 @@ import java.util.List;
|
||||
: MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
||||
float playbackSpeed = getPlaybackParameters().speed;
|
||||
float sessionPlaybackSpeed = isPlaying() ? playbackSpeed : 0f;
|
||||
Bundle extras = new Bundle();
|
||||
Bundle extras = legacyExtras != null ? new Bundle(legacyExtras) : new Bundle();
|
||||
extras.putFloat(EXTRAS_KEY_PLAYBACK_SPEED_COMPAT, playbackSpeed);
|
||||
@Nullable MediaItem currentMediaItem = getCurrentMediaItemWithCommandCheck();
|
||||
if (currentMediaItem != null && !MediaItem.DEFAULT_MEDIA_ID.equals(currentMediaItem.mediaId)) {
|
||||
|
@ -49,7 +49,8 @@ public class PlayerWrapperTest {
|
||||
/* playIfSuppressed= */ true,
|
||||
ImmutableList.of(),
|
||||
SessionCommands.EMPTY,
|
||||
Player.Commands.EMPTY);
|
||||
Player.Commands.EMPTY,
|
||||
/* legacyExtras= */ null);
|
||||
when(player.isCommandAvailable(anyInt())).thenReturn(true);
|
||||
when(player.getApplicationLooper()).thenReturn(Looper.myLooper());
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import static androidx.media3.test.session.common.MediaSessionConstants.TEST_MED
|
||||
import static androidx.media3.test.session.common.MediaSessionConstants.TEST_SET_SHOW_PLAY_BUTTON_IF_SUPPRESSED_TO_FALSE;
|
||||
import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS;
|
||||
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
|
||||
import static androidx.test.ext.truth.os.BundleSubject.assertThat;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
@ -999,33 +1000,106 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSessionExtras_cnExtrasChangedCalled() throws Exception {
|
||||
public void setSessionExtras_toAllControllers_extrasAndStateCallbacks() throws Exception {
|
||||
Bundle sessionExtras = new Bundle();
|
||||
sessionExtras.putString("key-0", "value-0");
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
List<Bundle> receivedSessionExtras = new ArrayList<>();
|
||||
CountDownLatch onExtrasChangedCalled = new CountDownLatch(1);
|
||||
CountDownLatch onPlaybackStateChangedCalled = new CountDownLatch(1);
|
||||
AtomicReference<Bundle> sessionExtrasFromCallback = new AtomicReference<>();
|
||||
AtomicReference<Bundle> sessionExtrasFromController = new AtomicReference<>();
|
||||
AtomicReference<Bundle> playbackStateExtrasFromCallback = new AtomicReference<>();
|
||||
AtomicReference<Bundle> playbackStateExtrasFromController = new AtomicReference<>();
|
||||
MediaControllerCompat.Callback callback =
|
||||
new MediaControllerCompat.Callback() {
|
||||
@Override
|
||||
public void onExtrasChanged(Bundle extras) {
|
||||
receivedSessionExtras.add(extras);
|
||||
receivedSessionExtras.add(controllerCompat.getExtras());
|
||||
latch.countDown();
|
||||
sessionExtrasFromCallback.set(extras);
|
||||
sessionExtrasFromController.set(controllerCompat.getExtras());
|
||||
onExtrasChangedCalled.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
||||
playbackStateExtrasFromCallback.set(state.getExtras());
|
||||
playbackStateExtrasFromController.set(controllerCompat.getPlaybackState().getExtras());
|
||||
onPlaybackStateChangedCalled.countDown();
|
||||
}
|
||||
};
|
||||
controllerCompat.registerCallback(callback, handler);
|
||||
|
||||
session.setSessionExtras(sessionExtras);
|
||||
|
||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(TestUtils.equals(receivedSessionExtras.get(0), sessionExtras)).isTrue();
|
||||
assertThat(TestUtils.equals(receivedSessionExtras.get(1), sessionExtras)).isTrue();
|
||||
assertThat(onExtrasChangedCalled.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(onPlaybackStateChangedCalled.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(sessionExtrasFromCallback.get()).hasSize(1);
|
||||
assertThat(sessionExtrasFromCallback.get()).string("key-0").isEqualTo("value-0");
|
||||
assertThat(sessionExtrasFromController.get()).hasSize(1);
|
||||
assertThat(sessionExtrasFromController.get()).string("key-0").isEqualTo("value-0");
|
||||
assertThat(playbackStateExtrasFromCallback.get()).hasSize(2);
|
||||
assertThat(playbackStateExtrasFromCallback.get())
|
||||
.doubleFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT)
|
||||
.isEqualTo(0.0);
|
||||
assertThat(playbackStateExtrasFromCallback.get()).string("key-0").isEqualTo("value-0");
|
||||
assertThat(playbackStateExtrasFromController.get()).hasSize(2);
|
||||
assertThat(playbackStateExtrasFromController.get())
|
||||
.doubleFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT)
|
||||
.isEqualTo(0.0);
|
||||
assertThat(playbackStateExtrasFromController.get()).string("key-0").isEqualTo("value-0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSessionExtras_toMediaNotificationControllers_extrasAndStateCallbacks()
|
||||
throws Exception {
|
||||
Bundle sessionExtras = new Bundle();
|
||||
sessionExtras.putString("key-0", "value-0");
|
||||
CountDownLatch onExtrasChangedCalled = new CountDownLatch(1);
|
||||
CountDownLatch onPlaybackStateChangedCalled = new CountDownLatch(1);
|
||||
AtomicReference<Bundle> sessionExtrasFromCallback = new AtomicReference<>();
|
||||
AtomicReference<Bundle> sessionExtrasFromController = new AtomicReference<>();
|
||||
AtomicReference<Bundle> playbackStateExtrasFromCallback = new AtomicReference<>();
|
||||
AtomicReference<Bundle> playbackStateExtrasFromController = new AtomicReference<>();
|
||||
MediaControllerCompat.Callback callback =
|
||||
new MediaControllerCompat.Callback() {
|
||||
@Override
|
||||
public void onExtrasChanged(Bundle extras) {
|
||||
sessionExtrasFromCallback.set(extras);
|
||||
sessionExtrasFromController.set(controllerCompat.getExtras());
|
||||
onExtrasChangedCalled.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
||||
playbackStateExtrasFromCallback.set(state.getExtras());
|
||||
playbackStateExtrasFromController.set(controllerCompat.getPlaybackState().getExtras());
|
||||
onPlaybackStateChangedCalled.countDown();
|
||||
}
|
||||
};
|
||||
controllerCompat.registerCallback(callback, handler);
|
||||
|
||||
session.setSessionExtras(/* controllerKey= */ NOTIFICATION_CONTROLLER_KEY, sessionExtras);
|
||||
|
||||
assertThat(onExtrasChangedCalled.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(onPlaybackStateChangedCalled.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(sessionExtrasFromCallback.get()).hasSize(1);
|
||||
assertThat(sessionExtrasFromCallback.get()).string("key-0").isEqualTo("value-0");
|
||||
assertThat(sessionExtrasFromController.get()).hasSize(1);
|
||||
assertThat(sessionExtrasFromController.get()).string("key-0").isEqualTo("value-0");
|
||||
assertThat(playbackStateExtrasFromCallback.get()).hasSize(2);
|
||||
assertThat(playbackStateExtrasFromCallback.get())
|
||||
.doubleFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT)
|
||||
.isEqualTo(0.0);
|
||||
assertThat(playbackStateExtrasFromCallback.get()).string("key-0").isEqualTo("value-0");
|
||||
assertThat(playbackStateExtrasFromController.get()).hasSize(2);
|
||||
assertThat(playbackStateExtrasFromController.get())
|
||||
.doubleFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT)
|
||||
.isEqualTo(0.0);
|
||||
assertThat(playbackStateExtrasFromController.get()).string("key-0").isEqualTo("value-0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendError_toAllControllers_onPlaybackStateChangedToErrorStateAndWithCorrectErrorData()
|
||||
throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
CountDownLatch latch = new CountDownLatch(3);
|
||||
List<PlaybackStateCompat> playbackStates = new ArrayList<>();
|
||||
MediaControllerCompat.Callback callback =
|
||||
new MediaControllerCompat.Callback() {
|
||||
@ -1036,9 +1110,12 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
}
|
||||
};
|
||||
controllerCompat.registerCallback(callback, handler);
|
||||
Bundle sessionExtras = new Bundle();
|
||||
sessionExtras.putString("initialKey", "initialValue");
|
||||
session.setSessionExtras(sessionExtras);
|
||||
PlaybackStateCompat initialPlaybackStateCompat = controllerCompat.getPlaybackState();
|
||||
Bundle errorBundle = new Bundle();
|
||||
errorBundle.putInt("intKey", 99);
|
||||
errorBundle.putInt("errorKey", 99);
|
||||
|
||||
session.sendError(
|
||||
/* controllerKey= */ null,
|
||||
@ -1047,13 +1124,19 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
errorBundle);
|
||||
|
||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(playbackStates).hasSize(2);
|
||||
PlaybackStateCompat errorPlaybackStateCompat = playbackStates.get(0);
|
||||
assertThat(playbackStates).hasSize(3);
|
||||
|
||||
// Skip the playback state from the first setSessionExtras() call.
|
||||
PlaybackStateCompat errorPlaybackStateCompat = playbackStates.get(1);
|
||||
assertThat(errorPlaybackStateCompat.getState()).isEqualTo(PlaybackStateCompat.STATE_ERROR);
|
||||
assertThat(errorPlaybackStateCompat.getErrorCode()).isEqualTo(1);
|
||||
assertThat(errorPlaybackStateCompat.getErrorMessage().toString())
|
||||
.isEqualTo(context.getString(R.string.authentication_required));
|
||||
PlaybackStateCompat resolvedPlaybackStateCompat = playbackStates.get(1);
|
||||
assertThat(errorPlaybackStateCompat.getExtras()).hasSize(2);
|
||||
assertThat(errorPlaybackStateCompat.getExtras()).integer("errorKey").isEqualTo(99);
|
||||
assertThat(errorPlaybackStateCompat.getExtras()).string("initialKey").isEqualTo("initialValue");
|
||||
|
||||
PlaybackStateCompat resolvedPlaybackStateCompat = playbackStates.get(2);
|
||||
assertThat(resolvedPlaybackStateCompat.getState())
|
||||
.isEqualTo(initialPlaybackStateCompat.getState());
|
||||
assertThat(resolvedPlaybackStateCompat.getErrorCode())
|
||||
@ -1061,13 +1144,18 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
assertThat(resolvedPlaybackStateCompat.getErrorMessage()).isNull();
|
||||
assertThat(resolvedPlaybackStateCompat.getActions())
|
||||
.isEqualTo(initialPlaybackStateCompat.getActions());
|
||||
assertThat(resolvedPlaybackStateCompat.getExtras())
|
||||
.hasSize(initialPlaybackStateCompat.getExtras().size());
|
||||
assertThat(resolvedPlaybackStateCompat.getExtras())
|
||||
.string("initialKey")
|
||||
.isEqualTo(initialPlaybackStateCompat.getExtras().getString("initialKey"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
sendError_toMediaNotificationControllers_onPlaybackStateChangedToErrorStateAndWithCorrectErrorData()
|
||||
throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
CountDownLatch latch = new CountDownLatch(3);
|
||||
List<PlaybackStateCompat> playbackStates = new ArrayList<>();
|
||||
MediaControllerCompat.Callback callback =
|
||||
new MediaControllerCompat.Callback() {
|
||||
@ -1078,10 +1166,13 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
}
|
||||
};
|
||||
controllerCompat.registerCallback(callback, handler);
|
||||
Bundle sessionExtras = new Bundle();
|
||||
sessionExtras.putString("initialKey", "initialValue");
|
||||
session.setSessionExtras(/* controllerKey= */ NOTIFICATION_CONTROLLER_KEY, sessionExtras);
|
||||
PlaybackStateCompat initialPlaybackStateCompat = controllerCompat.getPlaybackState();
|
||||
Bundle errorBundle = new Bundle();
|
||||
errorBundle.putInt("intKey", 99);
|
||||
|
||||
Bundle errorBundle = new Bundle();
|
||||
errorBundle.putInt("errorKey", 99);
|
||||
session.sendError(
|
||||
/* controllerKey= */ NOTIFICATION_CONTROLLER_KEY,
|
||||
/* errorCode= */ 1,
|
||||
@ -1089,15 +1180,20 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
errorBundle);
|
||||
|
||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||
assertThat(playbackStates).hasSize(2);
|
||||
PlaybackStateCompat errorPlaybackStateCompat = playbackStates.get(0);
|
||||
assertThat(playbackStates).hasSize(3);
|
||||
|
||||
// Skip the playback state from the first setSessionExtras() call.
|
||||
PlaybackStateCompat errorPlaybackStateCompat = playbackStates.get(1);
|
||||
assertThat(errorPlaybackStateCompat.getState()).isEqualTo(PlaybackStateCompat.STATE_ERROR);
|
||||
assertThat(errorPlaybackStateCompat.getErrorCode()).isEqualTo(1);
|
||||
assertThat(errorPlaybackStateCompat.getErrorMessage().toString())
|
||||
.isEqualTo(context.getString(R.string.authentication_required));
|
||||
assertThat(errorPlaybackStateCompat.getActions()).isEqualTo(0);
|
||||
assertThat(TestUtils.equals(errorPlaybackStateCompat.getExtras(), errorBundle)).isTrue();
|
||||
PlaybackStateCompat resolvedPlaybackStateCompat = playbackStates.get(1);
|
||||
assertThat(errorPlaybackStateCompat.getExtras()).hasSize(2);
|
||||
assertThat(errorPlaybackStateCompat.getExtras()).string("initialKey").isEqualTo("initialValue");
|
||||
assertThat(errorPlaybackStateCompat.getExtras()).integer("errorKey").isEqualTo(99);
|
||||
|
||||
PlaybackStateCompat resolvedPlaybackStateCompat = playbackStates.get(2);
|
||||
assertThat(resolvedPlaybackStateCompat.getState())
|
||||
.isEqualTo(initialPlaybackStateCompat.getState());
|
||||
assertThat(resolvedPlaybackStateCompat.getErrorCode())
|
||||
@ -1105,6 +1201,11 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
assertThat(resolvedPlaybackStateCompat.getErrorMessage()).isNull();
|
||||
assertThat(resolvedPlaybackStateCompat.getActions())
|
||||
.isEqualTo(initialPlaybackStateCompat.getActions());
|
||||
assertThat(resolvedPlaybackStateCompat.getExtras())
|
||||
.hasSize(initialPlaybackStateCompat.getExtras().size());
|
||||
assertThat(resolvedPlaybackStateCompat.getExtras())
|
||||
.string("initialKey")
|
||||
.isEqualTo(initialPlaybackStateCompat.getExtras().getString("initialKey"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user