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) {