diff --git a/libraries/session/src/main/aidl/androidx/media3/session/IMediaController.aidl b/libraries/session/src/main/aidl/androidx/media3/session/IMediaController.aidl index 2bebc6beeb..e3b1995540 100644 --- a/libraries/session/src/main/aidl/androidx/media3/session/IMediaController.aidl +++ b/libraries/session/src/main/aidl/androidx/media3/session/IMediaController.aidl @@ -42,7 +42,8 @@ oneway interface IMediaController { void onAvailableCommandsChangedFromSession( int seq, in Bundle sessionCommandsBundle, in Bundle playerCommandsBundle) = 3009; void onRenderedFirstFrame(int seq) = 3010; - // Next Id for MediaController: 3011 + void onExtrasChanged(int seq, in Bundle extras) = 3011; + // Next Id for MediaController: 3012 void onChildrenChanged( int seq, String parentId, int itemCount, in @nullable Bundle libraryParams) = 4000; diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java b/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java index 3b7935c79a..e97f6d7690 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java @@ -151,8 +151,6 @@ public final class MediaConstants { */ public static final int ERROR_CODE_AUTHENTICATION_EXPIRED_COMPAT = 3; - /* package */ static final String SESSION_COMMAND_ON_EXTRAS_CHANGED = - "androidx.media3.session.SESSION_COMMAND_ON_EXTRAS_CHANGED"; /* package */ static final String SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED = "androidx.media3.session.SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED"; /* package */ static final String SESSION_COMMAND_REQUEST_SESSION3_TOKEN = diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaController.java b/libraries/session/src/main/java/androidx/media3/session/MediaController.java index 09a418fb24..8f5a0424b7 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaController.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaController.java @@ -322,6 +322,14 @@ public class MediaController implements Player { MediaController controller, SessionCommand command, Bundle args) { return Futures.immediateFuture(new SessionResult(SessionResult.RESULT_ERROR_NOT_SUPPORTED)); } + + /** + * Called when the session extras have changed. + * + * @param controller The controller. + * @param extras The session extras that have changed. + */ + default void onExtrasChanged(MediaController controller, Bundle extras) {} } /* package */ interface ConnectionCallback { diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java index e9d9b5a420..9fe1017622 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java @@ -2598,6 +2598,13 @@ import org.checkerframework.checker.nullness.qual.NonNull; }); } + public void onExtrasChanged(Bundle extras) { + if (!isConnected()) { + return; + } + instance.notifyControllerListener(listener -> listener.onExtrasChanged(instance, extras)); + } + public void onRenderedFirstFrame() { listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onRenderedFirstFrame); } diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java index ae8d72d10a..3855969830 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -38,7 +38,6 @@ import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_QUERY; import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_URI; import static androidx.media3.session.MediaConstants.MEDIA_URI_SET_MEDIA_URI_PREFIX; import static androidx.media3.session.MediaConstants.SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED; -import static androidx.media3.session.MediaConstants.SESSION_COMMAND_ON_EXTRAS_CHANGED; import static androidx.media3.session.MediaUtils.POSITION_DIFF_TOLERANCE_MS; import static androidx.media3.session.MediaUtils.calculateBufferedPercentage; import static androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED; @@ -1606,14 +1605,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @Override public void onExtrasChanged(Bundle extras) { - instance.notifyControllerListener( - listener -> - ignoreFuture( - listener.onCustomCommand( - instance, - new SessionCommand( - SESSION_COMMAND_ON_EXTRAS_CHANGED, /* extras= */ Bundle.EMPTY), - extras))); + instance.notifyControllerListener(listener -> listener.onExtrasChanged(instance, extras)); } @Override diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java index 1cb2a5e62b..9d86ac05be 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerStub.java @@ -183,6 +183,11 @@ import java.util.List; isTimelineExcluded)); } + @Override + public void onExtrasChanged(int seq, Bundle extras) { + dispatchControllerTaskOnHandler(controller -> controller.onExtrasChanged(extras)); + } + @Override public void onRenderedFirstFrame(int seq) { dispatchControllerTaskOnHandler(MediaControllerImplBase::onRenderedFirstFrame); 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 3a27833c68..23db7affef 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -702,6 +702,32 @@ public class MediaSession { impl.broadcastCustomCommand(command, args); } + /** + * Sends the session extras to connected controllers. + * + *

This is a synchronous call and doesn't wait for results from the controllers. + * + * @param sessionExtras The session extras. + */ + public void setSessionExtras(Bundle sessionExtras) { + checkNotNull(sessionExtras); + impl.setSessionExtras(sessionExtras); + } + + /** + * Sends the session extras to the connected controller. + * + *

This is a synchronous call and doesn't wait for results from the controller. + * + * @param controller The controller to send the extras to. + * @param sessionExtras The session extras. + */ + public void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) { + checkNotNull(controller, "controller must not be null"); + checkNotNull(sessionExtras); + impl.setSessionExtras(controller, sessionExtras); + } + /** * Sends a custom command to a specific controller. * @@ -1119,6 +1145,8 @@ public class MediaSession { default void setCustomLayout(int seq, List layout) throws RemoteException {} + default void onSessionExtrasChanged(int seq, Bundle sessionExtras) throws RemoteException {} + default void sendCustomCommand(int seq, SessionCommand command, Bundle args) throws RemoteException {} 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 d82e1d54d1..57d1533c9a 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -342,6 +342,18 @@ import org.checkerframework.checker.initialization.qual.Initialized; (controller, seq) -> controller.setCustomLayout(seq, layout)); } + public void setSessionExtras(Bundle sessionExtras) { + dispatchRemoteControllerTaskWithoutReturn( + (controller, seq) -> controller.onSessionExtrasChanged(seq, sessionExtras)); + } + + public void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) { + if (sessionStub.getConnectedControllersManager().isConnected(controller)) { + dispatchRemoteControllerTaskWithoutReturn( + controller, (callback, seq) -> callback.onSessionExtrasChanged(seq, sessionExtras)); + } + } + public void setAvailableCommands( ControllerInfo controller, SessionCommands sessionCommands, Player.Commands playerCommands) { if (sessionStub.getConnectedControllersManager().isConnected(controller)) { 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 87361873a9..088aed877b 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java @@ -886,6 +886,11 @@ import org.checkerframework.checker.initialization.qual.Initialized; .setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat()); } + @Override + public void onSessionExtrasChanged(int seq, Bundle sessionExtras) { + sessionImpl.getSessionCompat().setExtras(sessionExtras); + } + @Override public void onPlayWhenReadyChanged( int seq, boolean playWhenReady, @Player.PlaybackSuppressionReason int reason) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java index 743af2c08e..672edf3a30 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java @@ -1801,6 +1801,11 @@ import java.util.concurrent.ExecutionException; iController.onRenderedFirstFrame(seq); } + @Override + public void onSessionExtrasChanged(int seq, Bundle sessionExtras) throws RemoteException { + iController.onExtrasChanged(seq, sessionExtras); + } + @Override public int hashCode() { return ObjectsCompat.hash(getCallbackBinder()); diff --git a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl index 30972501fa..4711fa62b1 100644 --- a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl +++ b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl @@ -32,6 +32,8 @@ interface IRemoteMediaSession { void release(String sessionId); void setAvailableCommands(String sessionId, in Bundle sessionCommands, in Bundle playerCommands); void setCustomLayout(String sessionId, in List layout); + void setSessionExtras(String sessionId, in Bundle extras); + void setSessionExtrasForController(String sessionId, in String controllerKey, in Bundle extras); // Player Methods void setPlayWhenReady(String sessionId, boolean playWhenReady, int reason); diff --git a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSessionCompat.aidl b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSessionCompat.aidl index f49dce56fa..3fe24ac8b9 100644 --- a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSessionCompat.aidl +++ b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSessionCompat.aidl @@ -41,4 +41,5 @@ interface IRemoteMediaSessionCompat { void setRatingType(String sessionTag, int type); void sendSessionEvent(String sessionTag, String event, in Bundle extras); void setCaptioningEnabled(String sessionTag, boolean enabled); + void setSessionExtras(String sessionTag, in Bundle extras); } diff --git a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaSessionConstants.java b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaSessionConstants.java index 4791aad8fc..bd08f997ca 100644 --- a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaSessionConstants.java +++ b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/MediaSessionConstants.java @@ -29,6 +29,7 @@ public class MediaSessionConstants { // Bundle keys public static final String KEY_AVAILABLE_SESSION_COMMANDS = "availableSessionCommands"; + public static final String KEY_CONTROLLER = "controllerKey"; private MediaSessionConstants() {} } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionCompatTest.java index 29e36e682d..551d03b109 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionCompatTest.java @@ -27,6 +27,7 @@ import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import androidx.media3.test.session.common.HandlerThreadTestRule; import androidx.media3.test.session.common.MainLooperTestRule; +import androidx.media3.test.session.common.TestUtils; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; @@ -137,4 +138,42 @@ public class MediaControllerCompatCallbackWithMediaSessionCompatTest { assertThat(receivedIconResIds).containsExactly(1, 2).inOrder(); assertThat(receivedBundleValues).containsExactly("value-1", "value-2").inOrder(); } + + /** + * Setting the session extras is used for instance by + * Wear OS and System UI (starting with T) to receive extras for UI customization. An app + * needs a way to set the session extras that are stored in the legacy session and broadcast to + * the connected controllers. + */ + @Test + public void setExtras_onExtrasChangedCalled() throws Exception { + Bundle sessionExtras = new Bundle(); + sessionExtras.putString("key-1", "value-1"); + CountDownLatch countDownLatch = new CountDownLatch(1); + MediaSessionCompat.Token sessionToken = session.getSessionToken(); + List receivedSessionExtras = new ArrayList<>(); + threadTestRule + .getHandler() + .postAndSync( + () -> { + MediaControllerCompat mediaControllerCompat = + new MediaControllerCompat(context, sessionToken); + mediaControllerCompat.registerCallback( + new MediaControllerCompat.Callback() { + @Override + public void onExtrasChanged(Bundle extras) { + receivedSessionExtras.add(extras); + receivedSessionExtras.add(mediaControllerCompat.getExtras()); + countDownLatch.countDown(); + } + }); + }); + + session.setExtras(sessionExtras); + + assertThat(countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(TestUtils.equals(receivedSessionExtras.get(0), sessionExtras)).isTrue(); + assertThat(TestUtils.equals(receivedSessionExtras.get(1), sessionExtras)).isTrue(); + } } 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 d025108b07..ac53cdf47f 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 @@ -819,6 +819,30 @@ public class MediaControllerCompatCallbackWithMediaSessionTest { assertThat(receivedBundleValues).containsExactly("value-1", "value-2").inOrder(); } + @Test + public void setSessionExtras_cnExtrasChangedCalled() throws Exception { + Bundle sessionExtras = new Bundle(); + sessionExtras.putString("key-0", "value-0"); + CountDownLatch latch = new CountDownLatch(1); + List receivedSessionExtras = new ArrayList<>(); + MediaControllerCompat.Callback callback = + new MediaControllerCompat.Callback() { + @Override + public void onExtrasChanged(Bundle extras) { + receivedSessionExtras.add(extras); + receivedSessionExtras.add(controllerCompat.getExtras()); + latch.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(); + } + @Test public void currentMediaItemChange() throws Exception { int testItemIndex = 3; 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 378506b08e..d4a597f410 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 @@ -28,6 +28,7 @@ import static androidx.media3.session.SessionResult.RESULT_SUCCESS; import static androidx.media3.test.session.common.CommonConstants.DEFAULT_TEST_NAME; import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA3_LIBRARY_SERVICE; import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA3_SESSION_SERVICE; +import static androidx.media3.test.session.common.MediaSessionConstants.KEY_CONTROLLER; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_CONTROLLER_LISTENER_SESSION_REJECTS; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_WITH_CUSTOM_COMMANDS; import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS; @@ -1800,6 +1801,55 @@ public class MediaControllerListenerTest { assertThat(receivedBundleValues).containsExactly("value-1", "value-2").inOrder(); } + @Test + public void setSessionExtras_onExtrasChangedCalled() throws Exception { + Bundle sessionExtras = TestUtils.createTestBundle(); + sessionExtras.putString("key-0", "value-0"); + CountDownLatch latch = new CountDownLatch(1); + List receivedSessionExtras = new ArrayList<>(); + MediaController.Listener listener = + new MediaController.Listener() { + @Override + public void onExtrasChanged(MediaController controller, Bundle extras) { + receivedSessionExtras.add(extras); + latch.countDown(); + } + }; + controllerTestRule.createController( + remoteSession.getToken(), /* connectionHints= */ null, listener); + + remoteSession.setSessionExtras(sessionExtras); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(receivedSessionExtras).hasSize(1); + assertThat(TestUtils.equals(receivedSessionExtras.get(0), sessionExtras)).isTrue(); + } + + @Test + public void setSessionExtras_specificMedia3Controller_onExtrasChangedCalled() throws Exception { + Bundle sessionExtras = TestUtils.createTestBundle(); + sessionExtras.putString("key-0", "value-0"); + CountDownLatch latch = new CountDownLatch(1); + List receivedSessionExtras = new ArrayList<>(); + MediaController.Listener listener = + new MediaController.Listener() { + @Override + public void onExtrasChanged(MediaController controller, Bundle extras) { + receivedSessionExtras.add(extras); + latch.countDown(); + } + }; + Bundle connectionHints = new Bundle(); + connectionHints.putString(KEY_CONTROLLER, "controller_key_1"); + controllerTestRule.createController(remoteSession.getToken(), connectionHints, listener); + + remoteSession.setSessionExtras("controller_key_1", sessionExtras); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(receivedSessionExtras).hasSize(1); + assertThat(TestUtils.equals(receivedSessionExtras.get(0), sessionExtras)).isTrue(); + } + @Test public void onVideoSizeChanged() throws Exception { VideoSize testVideoSize = diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java index 67a02b3b44..3e20c1cdaf 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java @@ -32,6 +32,7 @@ import androidx.media3.common.FlagSet; import androidx.media3.common.Player; import androidx.media3.test.session.common.HandlerThreadTestRule; import androidx.media3.test.session.common.MainLooperTestRule; +import androidx.media3.test.session.common.TestUtils; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; @@ -168,4 +169,26 @@ public class MediaControllerListenerWithMediaSessionCompatTest { assertThat(receivedIconResIds).containsExactly(1, 2).inOrder(); assertThat(receivedBundleValues).containsExactly("value-1", "value-2").inOrder(); } + + @Test + public void setSessionExtras_onExtrasChangedCalled() throws Exception { + Bundle sessionExtras = new Bundle(); + sessionExtras.putString("key-1", "value-1"); + CountDownLatch countDownLatch = new CountDownLatch(1); + List receivedSessionExtras = new ArrayList<>(); + controllerTestRule.createController( + session.getSessionToken(), + new MediaController.Listener() { + @Override + public void onExtrasChanged(MediaController controller, Bundle extras) { + receivedSessionExtras.add(extras); + countDownLatch.countDown(); + } + }); + + session.setExtras(sessionExtras); + + assertThat(countDownLatch.await(1_000, MILLISECONDS)).isTrue(); + assertThat(TestUtils.equals(receivedSessionExtras.get(0), sessionExtras)).isTrue(); + } } diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionCompatProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionCompatProviderService.java index be7d1b9c49..3fac9431e1 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionCompatProviderService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionCompatProviderService.java @@ -216,5 +216,11 @@ public class MediaSessionCompatProviderService extends Service { MediaSessionCompat session = sessionMap.get(sessionTag); session.setCaptioningEnabled(enabled); } + + @Override + public void setSessionExtras(String sessionTag, Bundle extras) throws RemoteException { + MediaSessionCompat session = sessionMap.get(sessionTag); + session.setExtras(extras); + } } } 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 3b3b06e3bb..6bf44ca49f 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 @@ -54,6 +54,7 @@ import static androidx.media3.test.session.common.CommonConstants.KEY_TRACK_SELE import static androidx.media3.test.session.common.CommonConstants.KEY_VIDEO_SIZE; import static androidx.media3.test.session.common.CommonConstants.KEY_VOLUME; import static androidx.media3.test.session.common.MediaSessionConstants.KEY_AVAILABLE_SESSION_COMMANDS; +import static androidx.media3.test.session.common.MediaSessionConstants.KEY_CONTROLLER; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_CONTROLLER_LISTENER_SESSION_REJECTS; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_GET_SESSION_ACTIVITY; import static androidx.media3.test.session.common.MediaSessionConstants.TEST_IS_SESSION_COMMAND_AVAILABLE; @@ -427,6 +428,29 @@ public class MediaSessionProviderService extends Service { }); } + @Override + public void setSessionExtras(String sessionId, Bundle extras) throws RemoteException { + runOnHandler(() -> sessionMap.get(sessionId).setSessionExtras(extras)); + } + + @Override + public void setSessionExtrasForController(String sessionId, String controllerKey, Bundle extras) + throws RemoteException { + runOnHandler( + () -> { + MediaSession mediaSession = sessionMap.get(sessionId); + for (ControllerInfo controllerInfo : mediaSession.getConnectedControllers()) { + if (controllerInfo + .getConnectionHints() + .getString(KEY_CONTROLLER, /* defaultValue= */ "") + .equals(controllerKey)) { + mediaSession.setSessionExtras(controllerInfo, extras); + break; + } + } + }); + } + //////////////////////////////////////////////////////////////////////////////// // MockPlayer methods //////////////////////////////////////////////////////////////////////////////// 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 65d249161b..9d22d6df39 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 @@ -197,6 +197,14 @@ public class RemoteMediaSession { binder.setCustomLayout(sessionId, bundleList); } + public void setSessionExtras(Bundle extras) throws RemoteException { + binder.setSessionExtras(sessionId, extras); + } + + public void setSessionExtras(String controllerKey, Bundle extras) throws RemoteException { + binder.setSessionExtrasForController(sessionId, controllerKey, extras); + } + //////////////////////////////////////////////////////////////////////////////// // RemoteMockPlayer methods //////////////////////////////////////////////////////////////////////////////// diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSessionCompat.java b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSessionCompat.java index a06760d460..da94920c59 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSessionCompat.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSessionCompat.java @@ -173,6 +173,10 @@ public class RemoteMediaSessionCompat { binder.setCaptioningEnabled(sessionTag, enabled); } + public void setExtras(Bundle extras) throws RemoteException { + binder.setSessionExtras(sessionTag, extras); + } + //////////////////////////////////////////////////////////////////////////////// // Non-public methods //////////////////////////////////////////////////////////////////////////////// diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/TestMediaBrowserListener.java b/libraries/test_session_current/src/main/java/androidx/media3/session/TestMediaBrowserListener.java index f8e9071860..7b76cb7366 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/TestMediaBrowserListener.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/TestMediaBrowserListener.java @@ -58,6 +58,11 @@ public final class TestMediaBrowserListener implements MediaBrowser.Listener { return delegate.onSetCustomLayout(controller, layout); } + @Override + public void onExtrasChanged(MediaController controller, Bundle extras) { + delegate.onExtrasChanged(controller, extras); + } + @Override public void onAvailableSessionCommandsChanged( MediaController controller, SessionCommands commands) {