diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b2b0eb80ad..0c4db2e4d1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -32,6 +32,9 @@ * Fix bug where multiple identical queue items published by a legacy `MediaSessionCompat` result in an exception in `MediaController` ([#290](https://github.com/androidx/media/issues/290)). + * Add missing forwarding of `MediaSession.broadcastCustomCommand` to the + legacy `MediaControllerCompat.Callback.onSessionEvent` + ([#293](https://github.com/androidx/media/issues/293)). * 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/MediaSession.java b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java index b59a672f12..46bbd976e5 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -704,6 +704,9 @@ public class MediaSession { * * * + *

Interoperability: This call has no effect when called for a {@linkplain + * ControllerInfo#LEGACY_CONTROLLER_VERSION legacy controller}. + * * @param controller The controller to specify layout. * @param layout The ordered list of {@link CommandButton}. */ @@ -796,6 +799,9 @@ public class MediaSession { * *

This is a synchronous call and doesn't wait for results from the controller. * + *

Interoperability: This call has no effect when called for a {@linkplain + * ControllerInfo#LEGACY_CONTROLLER_VERSION legacy controller}. + * * @param controller The controller to send the extras to. * @param sessionExtras The session extras. */ @@ -819,6 +825,9 @@ public class MediaSession { * *

A command is not accepted if it is not a custom command. * + *

Interoperability: This call has no effect when called for a {@linkplain + * ControllerInfo#LEGACY_CONTROLLER_VERSION legacy controller}. + * * @param controller The controller to send the custom command to. * @param command A custom command. * @param args A {@link Bundle} for additional arguments. May be empty. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java index 3f174dc28f..69e93234a7 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java @@ -988,6 +988,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; sessionImpl.getSessionCompat().setExtras(sessionExtras); } + @Override + public void sendCustomCommand(int seq, SessionCommand command, Bundle args) { + sessionImpl.getSessionCompat().sendSessionEvent(command.customAction, args); + } + @Override public void onPlayWhenReadyChanged( int seq, boolean playWhenReady, @Player.PlaybackSuppressionReason int reason) diff --git a/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java b/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java index c514af10c8..de204146e6 100644 --- a/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java +++ b/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java @@ -123,6 +123,10 @@ public final class SessionCommand implements Bundleable { /** * The extra bundle of a custom command. It will be {@link Bundle#EMPTY} for a predefined command. + * + *

Interoperability: This value is not used when the command is sent to a legacy {@link + * android.support.v4.media.session.MediaSessionCompat} or {@link + * android.support.v4.media.session.MediaControllerCompat}. */ public final Bundle customExtras; @@ -143,7 +147,9 @@ public final class SessionCommand implements Bundleable { * Creates a custom command. * * @param action The action of this custom command. - * @param extras An extra bundle for this custom command. + * @param extras An extra bundle for this custom command. This value is not used when the command + * is sent to a legacy {@link android.support.v4.media.session.MediaSessionCompat} or {@link + * android.support.v4.media.session.MediaControllerCompat}. */ public SessionCommand(String action, Bundle extras) { commandCode = COMMAND_CODE_CUSTOM; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java index 71543ae0fe..bd85cf9338 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java @@ -980,6 +980,35 @@ public class MediaControllerCompatCallbackWithMediaSessionTest { assertThat(TestUtils.equals(receivedSessionExtras.get(1), sessionExtras)).isTrue(); } + @Test + public void broadcastCustomCommand_cnSessionEventCalled() throws Exception { + Bundle commandCallExtras = new Bundle(); + commandCallExtras.putString("key-0", "value-0"); + // Specify session command extras to see that they are NOT used. + Bundle sessionCommandExtras = new Bundle(); + sessionCommandExtras.putString("key-0", "value-1"); + SessionCommand sessionCommand = new SessionCommand("custom_action", sessionCommandExtras); + CountDownLatch latch = new CountDownLatch(1); + AtomicReference receivedCommand = new AtomicReference<>(); + AtomicReference receivedCommandExtras = new AtomicReference<>(); + MediaControllerCompat.Callback callback = + new MediaControllerCompat.Callback() { + @Override + public void onSessionEvent(String event, Bundle extras) { + receivedCommand.set(event); + receivedCommandExtras.set(extras); + latch.countDown(); + } + }; + controllerCompat.registerCallback(callback, handler); + + session.broadcastCustomCommand(sessionCommand, commandCallExtras); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(receivedCommand.get()).isEqualTo("custom_action"); + assertThat(TestUtils.equals(receivedCommandExtras.get(), commandCallExtras)).isTrue(); + } + @Test public void onMediaItemTransition_updatesLegacyMetadataAndPlaybackState_correctModelConversion() throws Exception {