From b68d455b5e1fa9491bc6e3d0fc9ecaa22d3e3e82 Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 22 Oct 2024 04:00:53 -0700 Subject: [PATCH] Ensure session extras Bundle is copied at least once If not copied, the extras Bundle can be accidentally changed by the app if it modifies the instance passed into MediaSession. On the flip side, the Bundle should be modifiable once created so that the session can amend the extras if needed without crashing. PiperOrigin-RevId: 688485963 (cherry picked from commit d9ca3c734aa1042731a3136712993277a45804f7) --- .../androidx/media3/session/MediaSession.java | 10 ++-- .../media3/session/MediaSessionTest.java | 56 +++++++++++++++++++ 2 files changed, 60 insertions(+), 6 deletions(-) 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 c19bf17c8a..577e6e2fd0 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -1237,8 +1237,7 @@ public class MediaSession { * @param sessionExtras The session extras. */ public final void setSessionExtras(Bundle sessionExtras) { - checkNotNull(sessionExtras); - impl.setSessionExtras(sessionExtras); + impl.setSessionExtras(new Bundle(sessionExtras)); } /** @@ -1259,8 +1258,7 @@ public class MediaSession { */ public final void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) { checkNotNull(controller, "controller must not be null"); - checkNotNull(sessionExtras); - impl.setSessionExtras(controller, sessionExtras); + impl.setSessionExtras(controller, new Bundle(sessionExtras)); } /** Returns the {@link BitmapLoader}. */ @@ -2284,8 +2282,8 @@ public class MediaSession { checkArgument(player.canAdvertiseSession()); id = ""; this.callback = callback; - tokenExtras = Bundle.EMPTY; - sessionExtras = Bundle.EMPTY; + tokenExtras = new Bundle(); + sessionExtras = new Bundle(); customLayout = ImmutableList.of(); mediaButtonPreferences = ImmutableList.of(); playIfSuppressed = true; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java index 5d3e2e0fc7..200648ffbe 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java @@ -991,6 +991,62 @@ public class MediaSessionTest { assertThat(isEventHandled).isFalse(); } + @Test + public void builderSetExtras_doesNotKeepOriginalInstance() { + Bundle extras = new Bundle(); + extras.putString("key", "value"); + + MediaSession session = new MediaSession.Builder(context, player).setExtras(extras).build(); + extras.putString("key", "newValue"); + String sessionExtraValue = session.getToken().getExtras().getString("key"); + session.release(); + + assertThat(sessionExtraValue).isEqualTo("value"); + } + + @Test + public void builderSetSessionExtras_doesNotKeepOriginalInstance() { + Bundle extras = new Bundle(); + extras.putString("key", "value"); + + MediaSession session = + new MediaSession.Builder(context, player).setSessionExtras(extras).build(); + extras.putString("key", "newValue"); + String sessionExtraValue = session.getSessionExtras().getString("key"); + session.release(); + + assertThat(sessionExtraValue).isEqualTo("value"); + } + + @Test + public void builder_defaultExtras_createsMutableInstance() { + MediaSession session = new MediaSession.Builder(context, player).build(); + + session.getSessionExtras().putString("key", "value"); + String sessionExtraValue = session.getSessionExtras().getString("key"); + session.release(); + + assertThat(sessionExtraValue).isEqualTo("value"); + } + + @Test + public void setSessionExtras_doesNotKeepOriginalInstance() throws Exception { + MediaSession session = new MediaSession.Builder(context, player).build(); + Bundle extras = new Bundle(); + extras.putString("key", "value"); + AtomicReference sessionExtraValue = new AtomicReference<>(); + + handler.postAndSync( + () -> { + session.setSessionExtras(extras); + extras.putString("key", "newValue"); + sessionExtraValue.set(session.getSessionExtras().getString("key")); + session.release(); + }); + + assertThat(sessionExtraValue.get()).isEqualTo("value"); + } + private static Intent getMediaButtonIntent(int keyCode) { Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); intent.setComponent(