diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index b742815498..67ddf2b1af 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -17,6 +17,12 @@
* Muxers:
* IMA extension:
* Session:
+ * Allow the session activity to be set per controller to override the
+ global session activity. The session activity can be defined for a
+ controller at connection time by creating a `ConnectionResult` with
+ `AcceptedResultBuilder.setSessionActivivty(PendingIntent)`. Once
+ connected, the session activity can be updated with
+ `MediaSession.setSessionActivity(ControllerInfo, PendingIntent)`.
* UI:
* Downloads:
* OkHttp Extension:
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 a75902e2fa..5aa4ba1934 100644
--- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java
+++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java
@@ -759,6 +759,8 @@ public class MediaSession {
* Builder#setSessionActivity(PendingIntent) building the session}.
*
* @param activityPendingIntent The pending intent to start the session activity.
+ * @throws IllegalArgumentException if the {@link PendingIntent} passed into this method is
+ * {@linkplain PendingIntent#getActivity(Context, int, Intent, int) not an activity}.
*/
@UnstableApi
public final void setSessionActivity(PendingIntent activityPendingIntent) {
@@ -768,6 +770,30 @@ public class MediaSession {
impl.setSessionActivity(activityPendingIntent);
}
+ /**
+ * Sends the session activity to the connected controller.
+ *
+ *
This call immediately returns and doesn't wait for a result from the controller.
+ *
+ *
Interoperability: This call has no effect when called for a {@linkplain
+ * ControllerInfo#LEGACY_CONTROLLER_VERSION legacy controller}. To set the session activity of the
+ * platform session use {@linkplain #getMediaNotificationControllerInfo() the media notification
+ * controller} as the target controller.
+ *
+ * @param controller The controller to send the session activity to.
+ * @param activityPendingIntent The pending intent to start the session activity.
+ * @throws IllegalArgumentException if the {@link PendingIntent} passed into this method is
+ * {@linkplain PendingIntent#getActivity(Context, int, Intent, int) not an activity}.
+ */
+ @UnstableApi
+ public final void setSessionActivity(
+ ControllerInfo controller, PendingIntent activityPendingIntent) {
+ if (Util.SDK_INT >= 31) {
+ checkArgument(Api31.isActivity(activityPendingIntent));
+ }
+ impl.setSessionActivity(controller, activityPendingIntent);
+ }
+
/**
* Sets the underlying {@link Player} for this session to dispatch incoming events to.
*
@@ -1025,7 +1051,7 @@ public class MediaSession {
/**
* Broadcasts a custom command to all connected controllers.
*
- *
This is a synchronous call and doesn't wait for results from the controllers.
+ *
This call immediately returns and doesn't wait for a result from the controller.
*
*
A command is not accepted if it is not a custom command.
*
@@ -1061,7 +1087,7 @@ public class MediaSession {
*
The initial extras can be set {@linkplain Builder#setSessionExtras(Bundle) when building the
* session}.
*
- *
This is a synchronous call and doesn't wait for results from the controllers.
+ *
This call immediately returns and doesn't wait for a result from the controller.
*
* @param sessionExtras The session extras.
*/
@@ -1078,7 +1104,7 @@ public class MediaSession {
* ConnectionResult.AcceptedResultBuilder#setSessionExtras(Bundle) building the connection
* result}.
*
- *
This is a synchronous call and doesn't wait for results from the controller.
+ *
This call immediately returns and doesn't wait for a result from the controller.
*
*
Interoperability: This call has no effect when called for a {@linkplain
* ControllerInfo#LEGACY_CONTROLLER_VERSION legacy controller}.
@@ -1713,6 +1739,7 @@ public class MediaSession {
private Player.Commands availablePlayerCommands = DEFAULT_PLAYER_COMMANDS;
@Nullable private ImmutableList customLayout;
@Nullable private Bundle sessionExtras;
+ @Nullable private PendingIntent sessionActivity;
/**
* Creates an instance.
@@ -1788,6 +1815,18 @@ public class MediaSession {
return this;
}
+ /**
+ * Sets the session activity, overriding the {@linkplain MediaSession#getSessionActivity()
+ * session activity of the session}.
+ *
+ * The default is null to indicate that the session activity of the session should be used.
+ */
+ @CanIgnoreReturnValue
+ public AcceptedResultBuilder setSessionActivity(@Nullable PendingIntent sessionActivity) {
+ this.sessionActivity = sessionActivity;
+ return this;
+ }
+
/** Returns a new {@link ConnectionResult} instance for accepting a connection. */
public ConnectionResult build() {
return new ConnectionResult(
@@ -1795,7 +1834,8 @@ public class MediaSession {
availableSessionCommands,
availablePlayerCommands,
customLayout,
- sessionExtras);
+ sessionExtras,
+ sessionActivity);
}
}
@@ -1826,18 +1866,23 @@ public class MediaSession {
/** The session extras. */
@UnstableApi @Nullable public final Bundle sessionExtras;
+ /** The session activity. */
+ @UnstableApi @Nullable public final PendingIntent sessionActivity;
+
/** Creates a new instance with the given available session and player commands. */
private ConnectionResult(
boolean accepted,
SessionCommands availableSessionCommands,
Player.Commands availablePlayerCommands,
@Nullable ImmutableList customLayout,
- @Nullable Bundle sessionExtras) {
+ @Nullable Bundle sessionExtras,
+ @Nullable PendingIntent sessionActivity) {
isAccepted = accepted;
this.availableSessionCommands = availableSessionCommands;
this.availablePlayerCommands = availablePlayerCommands;
this.customLayout = customLayout;
this.sessionExtras = sessionExtras;
+ this.sessionActivity = sessionActivity;
}
/**
@@ -1857,7 +1902,8 @@ public class MediaSession {
availableSessionCommands,
availablePlayerCommands,
/* customLayout= */ null,
- /* sessionExtras= */ null);
+ /* sessionExtras= */ null,
+ /* sessionActivity= */ null);
}
/** Creates a {@link ConnectionResult} to reject a connection. */
@@ -1867,7 +1913,8 @@ public class MediaSession {
SessionCommands.EMPTY,
Player.Commands.EMPTY,
/* customLayout= */ ImmutableList.of(),
- /* sessionExtras= */ Bundle.EMPTY);
+ /* sessionExtras= */ Bundle.EMPTY,
+ /* sessionActivity= */ null);
}
}
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 678a0d4561..a6e4c12ecb 100644
--- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java
+++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java
@@ -783,19 +783,23 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@UnstableApi
protected void setSessionActivity(PendingIntent sessionActivity) {
- if (Objects.equals(this.sessionActivity, sessionActivity)) {
- return;
- }
this.sessionActivity = sessionActivity;
- sessionLegacyStub.getSessionCompat().setSessionActivity(sessionActivity);
ImmutableList connectedControllers =
sessionStub.getConnectedControllersManager().getConnectedControllers();
for (int i = 0; i < connectedControllers.size(); i++) {
- ControllerInfo controllerInfo = connectedControllers.get(i);
- if (controllerInfo.getControllerVersion() >= 3) {
- dispatchRemoteControllerTaskWithoutReturn(
- controllerInfo,
- (controller, seq) -> controller.onSessionActivityChanged(seq, sessionActivity));
+ setSessionActivity(connectedControllers.get(i), sessionActivity);
+ }
+ }
+
+ @UnstableApi
+ protected void setSessionActivity(ControllerInfo controller, PendingIntent sessionActivity) {
+ if (controller.getControllerVersion() >= 3
+ && sessionStub.getConnectedControllersManager().isConnected(controller)) {
+ dispatchRemoteControllerTaskWithoutReturn(
+ controller, (callback, seq) -> callback.onSessionActivityChanged(seq, sessionActivity));
+ if (isMediaNotificationController(controller)) {
+ dispatchRemoteControllerTaskToLegacyStub(
+ (callback, seq) -> callback.onSessionActivityChanged(seq, sessionActivity));
}
}
}
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 400dbd35da..e787973cd7 100644
--- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java
+++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java
@@ -1117,6 +1117,11 @@ import org.checkerframework.checker.initialization.qual.Initialized;
sessionCompat.setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat());
}
+ @Override
+ public void onSessionActivityChanged(int seq, PendingIntent sessionActivity) {
+ sessionCompat.setSessionActivity(sessionActivity);
+ }
+
@Override
public void onError(int seq, SessionError sessionError) {
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
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 b032a38924..9e32a005a1 100644
--- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java
+++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java
@@ -526,7 +526,9 @@ import java.util.concurrent.ExecutionException;
MediaLibraryInfo.VERSION_INT,
MediaSessionStub.VERSION_INT,
MediaSessionStub.this,
- sessionImpl.getSessionActivity(),
+ connectionResult.sessionActivity != null
+ ? connectionResult.sessionActivity
+ : sessionImpl.getSessionActivity(),
connectionResult.customLayout != null
? connectionResult.customLayout
: sessionImpl.getCustomLayout(),
diff --git a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl
index 2ff7a39d88..d74b940323 100644
--- a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl
+++ b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl
@@ -30,6 +30,9 @@ interface IRemoteMediaController {
// MediaController Methods
Bundle getConnectedSessionToken(String controllerId);
Bundle getSessionExtras(String controllerId);
+ Bundle getCustomLayout(String controllerId);
+ Bundle getAvailableCommands(String controllerId);
+ PendingIntent getSessionActivity(String controllerId);
void play(String controllerId);
void pause(String controllerId);
void setPlayWhenReady(String controllerId, boolean playWhenReady);
@@ -101,8 +104,6 @@ interface IRemoteMediaController {
int page,
int pageSize,
in Bundle libraryParams);
- Bundle getCustomLayout(String controllerId);
- Bundle getAvailableCommands(String controllerId);
Bundle getItem(String controllerId, String mediaId);
Bundle search(String controllerId, String query, in Bundle libraryParams);
Bundle getSearchResult(
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 f749757953..e59ed772d2 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
@@ -35,7 +35,7 @@ interface IRemoteMediaSession {
void setSessionExtras(String sessionId, in Bundle extras);
void setSessionExtrasForController(String sessionId, in String controllerKey, in Bundle extras);
void sendError(String sessionId, String controllerKey, in Bundle SessionError);
- void setSessionActivity(String sessionId, in PendingIntent sessionActivity);
+ void setSessionActivity(String sessionId, String controllerKey, in PendingIntent sessionActivity);
// Player Methods
void setPlayWhenReady(String sessionId, boolean playWhenReady, int reason);
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 64b2bfaeeb..cd380e9ba2 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
@@ -1227,7 +1227,8 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
}
@Test
- public void setSessionActivity_changedWhenReceivedWithSetter() throws Exception {
+ public void setSessionActivity_forAllControllers_changedWhenReceivedWithSetter()
+ throws Exception {
Intent intent = new Intent(context, SurfaceActivity.class);
PendingIntent sessionActivity =
PendingIntent.getActivity(
@@ -1243,7 +1244,34 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
controllerCompat.registerCallback(callback, handler);
assertThat(controllerCompat.getSessionActivity()).isNull();
- session.setSessionActivity(sessionActivity);
+ session.setSessionActivity(/* controllerKey= */ null, sessionActivity);
+ // The legacy API has no change listener for the session activity. Changing the state to
+ // trigger a callback.
+ session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
+
+ assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
+ assertThat(controllerCompat.getSessionActivity()).isEqualTo(sessionActivity);
+ }
+
+ @Test
+ public void setSessionActivity_setToNotificationController_changedWhenReceivedWithSetter()
+ throws Exception {
+ Intent intent = new Intent(context, SurfaceActivity.class);
+ PendingIntent sessionActivity =
+ PendingIntent.getActivity(
+ context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+ CountDownLatch latch = new CountDownLatch(1);
+ MediaControllerCompat.Callback callback =
+ new MediaControllerCompat.Callback() {
+ @Override
+ public void onPlaybackStateChanged(PlaybackStateCompat state) {
+ latch.countDown();
+ }
+ };
+ controllerCompat.registerCallback(callback, handler);
+ assertThat(controllerCompat.getSessionActivity()).isNull();
+
+ session.setSessionActivity(NOTIFICATION_CONTROLLER_KEY, sessionActivity);
// The legacy API has no change listener for the session activity. Changing the state to
// trigger a callback.
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
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 8ccc47d7a8..758bb863d6 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
@@ -2535,13 +2535,69 @@ public class MediaControllerListenerTest {
remoteSession.getToken(), /* connectionHints= */ null, listener);
assertThat(controller.getSessionActivity()).isNull();
- remoteSession.setSessionActivity(sessionActivity);
+ remoteSession.setSessionActivity(/* controllerKey= */ null, sessionActivity);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(controller.getSessionActivity()).isEqualTo(sessionActivity);
assertThat(receivedSessionActivities).containsExactly(sessionActivity);
}
+ @Test
+ public void setSessionActivity_forSpecificController_onSessionActivityChangedCalled()
+ throws Exception {
+ Intent intent = new Intent(context, SurfaceActivity.class);
+ PendingIntent sessionActivity =
+ PendingIntent.getActivity(
+ context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+ CountDownLatch latch1 = new CountDownLatch(1);
+ List receivedSessionActivities1 = new ArrayList<>();
+ MediaController.Listener listener1 =
+ new MediaController.Listener() {
+ @Override
+ public void onSessionActivityChanged(
+ MediaController controller, PendingIntent sessionActivity) {
+ receivedSessionActivities1.add(sessionActivity);
+ latch1.countDown();
+ }
+ };
+ Bundle connectionHints1 = new Bundle();
+ connectionHints1.putString(KEY_CONTROLLER, "ctrl-1");
+ MediaController controller1 =
+ controllerTestRule.createController(remoteSession.getToken(), connectionHints1, listener1);
+ List receivedSessionActivities2 = new ArrayList<>();
+ CountDownLatch latch2 = new CountDownLatch(1);
+ MediaController.Listener listener2 =
+ new MediaController.Listener() {
+ @Override
+ public void onSessionActivityChanged(
+ MediaController controller, PendingIntent sessionActivity) {
+ receivedSessionActivities2.add(sessionActivity);
+ latch2.countDown();
+ }
+ };
+ Bundle connectionHints2 = new Bundle();
+ connectionHints2.putString(KEY_CONTROLLER, "ctrl-2");
+ MediaController controller2 =
+ controllerTestRule.createController(remoteSession.getToken(), connectionHints2, listener2);
+ assertThat(controller1.getSessionActivity()).isNull();
+ assertThat(controller2.getSessionActivity()).isNull();
+
+ remoteSession.setSessionActivity(/* controllerKey= */ "ctrl-1", sessionActivity);
+
+ assertThat(latch1.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
+ assertThat(controller1.getSessionActivity()).isEqualTo(sessionActivity);
+ assertThat(controller2.getSessionActivity()).isNull();
+ assertThat(receivedSessionActivities1).containsExactly(sessionActivity);
+ assertThat(receivedSessionActivities2).isEmpty();
+
+ remoteSession.setSessionActivity(/* controllerKey= */ "ctrl-2", sessionActivity);
+
+ assertThat(latch2.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
+ assertThat(controller2.getSessionActivity()).isEqualTo(sessionActivity);
+ assertThat(receivedSessionActivities1).containsExactly(sessionActivity);
+ assertThat(receivedSessionActivities2).containsExactly(sessionActivity);
+ }
+
@Test
public void onVideoSizeChanged() throws Exception {
VideoSize defaultVideoSize = MediaTestUtils.createDefaultVideoSize();
diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java
index bb30dfccec..e8c361f83b 100644
--- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java
+++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java
@@ -29,7 +29,9 @@ import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.fail;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.Nullable;
@@ -45,6 +47,7 @@ import androidx.media3.session.MediaSession.ConnectionResult.AcceptedResultBuild
import androidx.media3.session.MediaSession.ControllerInfo;
import androidx.media3.test.session.common.HandlerThreadTestRule;
import androidx.media3.test.session.common.MainLooperTestRule;
+import androidx.media3.test.session.common.SurfaceActivity;
import androidx.media3.test.session.common.TestHandler;
import androidx.media3.test.session.common.TestUtils;
import androidx.media3.test.utils.TestExoPlayerBuilder;
@@ -293,6 +296,49 @@ public class MediaSessionCallbackTest {
assertThat(remoteController.getSessionExtras().getString("origin")).isEqualTo("controller");
}
+ @Test
+ public void onConnect_connectionResultSessionActivitySet_usesControllerSpecificSessionActivity()
+ throws Exception {
+ Intent intent = new Intent(context, SurfaceActivity.class);
+ PendingIntent controllerSpecificSessionActivity =
+ PendingIntent.getActivity(
+ context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+ MediaSession.Callback callback =
+ new MediaSession.Callback() {
+ @Override
+ public MediaSession.ConnectionResult onConnect(
+ MediaSession session, ControllerInfo controller) {
+ AcceptedResultBuilder connectionResult =
+ new AcceptedResultBuilder(session)
+ .setAvailablePlayerCommands(Player.Commands.EMPTY);
+ if (controller.getConnectionHints().getBoolean("want_session_activity", false)) {
+ connectionResult.setSessionActivity(controllerSpecificSessionActivity);
+ }
+ return connectionResult.build();
+ }
+ };
+ MediaSession session =
+ sessionTestRule.ensureReleaseAfterTest(
+ new MediaSession.Builder(context, player)
+ .setCallback(callback)
+ .setId(
+ "onConnect_connectionResultSessionActivitySet_usesControllerSpecificSessionActivity")
+ .build());
+ Bundle connectionHints = new Bundle();
+ connectionHints.putBoolean("want_session_activity", true);
+
+ RemoteMediaController remoteControllerWithSpecificSessionActivity =
+ remoteControllerTestRule.createRemoteController(
+ session.getToken(), /* waitForConnection= */ true, connectionHints);
+ RemoteMediaController remoteControllerWithoutSpecificSessionActivity =
+ remoteControllerTestRule.createRemoteController(
+ session.getToken(), /* waitForConnection= */ true, /* connectionHints= */ Bundle.EMPTY);
+
+ assertThat(remoteControllerWithSpecificSessionActivity.getSessionActivity())
+ .isEqualTo(controllerSpecificSessionActivity);
+ assertThat(remoteControllerWithoutSpecificSessionActivity.getSessionActivity()).isNull();
+ }
+
@Test
public void onConnect_connectionResultDefault_emptySessionExtras() throws Exception {
MediaSession session =
diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java
index 5c17cc70b5..a912560c56 100644
--- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java
+++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java
@@ -21,6 +21,7 @@ import static androidx.media3.test.session.common.CommonConstants.KEY_COMMAND_BU
import static androidx.media3.test.session.common.TestUtils.SERVICE_CONNECTION_TIMEOUT_MS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -854,6 +855,12 @@ public class MediaControllerProviderService extends Service {
return runOnHandler(controller::getAvailableCommands).toBundle();
}
+ @Override
+ public PendingIntent getSessionActivity(String controllerId) throws RemoteException {
+ MediaController controller = mediaControllerMap.get(controllerId);
+ return runOnHandler(controller::getSessionActivity);
+ }
+
@Override
public Bundle getItem(String controllerId, String mediaId) throws RemoteException {
MediaBrowser browser = (MediaBrowser) mediaControllerMap.get(controllerId);
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 206db15a60..6557d4ec3c 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
@@ -111,6 +111,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.Callable;
/**
@@ -607,9 +608,29 @@ public class MediaSessionProviderService extends Service {
}
@Override
- public void setSessionActivity(String sessionId, PendingIntent sessionActivity)
+ public void setSessionActivity(
+ String sessionId, @Nullable String controllerKey, PendingIntent sessionActivity)
throws RemoteException {
- runOnHandler(() -> sessionMap.get(sessionId).setSessionActivity(sessionActivity));
+ MediaSession mediaSession = sessionMap.get(sessionId);
+ if (mediaSession == null) {
+ return;
+ }
+ if (controllerKey == null) {
+ // Set to all controllers by using the global session method.
+ runOnHandler(() -> mediaSession.setSessionActivity(sessionActivity));
+ return;
+ }
+ List connectedControllers = mediaSession.getConnectedControllers();
+ for (int i = 0; i < connectedControllers.size(); i++) {
+ ControllerInfo controllerInfo = connectedControllers.get(i);
+ @Nullable
+ String connectedControllerKey =
+ controllerInfo.getConnectionHints().getString(KEY_CONTROLLER);
+ if (Objects.equals(controllerKey, connectedControllerKey)) {
+ // Set to controller for that the test case has given the provided controllerKey.
+ runOnHandler(() -> mediaSession.setSessionActivity(controllerInfo, sessionActivity));
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java
index 6b9ab66892..b8143f31e8 100644
--- a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java
+++ b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java
@@ -22,6 +22,7 @@ import static androidx.media3.test.session.common.TestUtils.SERVICE_CONNECTION_T
import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -393,6 +394,10 @@ public class RemoteMediaController {
return Player.Commands.fromBundle(commandsBundle);
}
+ public PendingIntent getSessionActivity() throws RemoteException {
+ return binder.getSessionActivity(controllerId);
+ }
+
////////////////////////////////////////////////////////////////////////////////
// Non-public 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 869b9eb164..70af785ff7 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
@@ -209,8 +209,9 @@ public class RemoteMediaSession {
binder.setSessionExtrasForController(sessionId, controllerKey, extras);
}
- public void setSessionActivity(PendingIntent sessionActivity) throws RemoteException {
- binder.setSessionActivity(sessionId, sessionActivity);
+ public void setSessionActivity(String controllerKey, PendingIntent sessionActivity)
+ throws RemoteException {
+ binder.setSessionActivity(sessionId, controllerKey, sessionActivity);
}
public void sendError(@Nullable String controllerKey, SessionError sessionError)