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)
This commit is contained in:
tonihei 2024-10-22 04:00:53 -07:00 committed by Iván Budnik
parent 8304c26e08
commit b68d455b5e
2 changed files with 60 additions and 6 deletions

View File

@ -1237,8 +1237,7 @@ public class MediaSession {
* @param sessionExtras The session extras. * @param sessionExtras The session extras.
*/ */
public final void setSessionExtras(Bundle sessionExtras) { public final void setSessionExtras(Bundle sessionExtras) {
checkNotNull(sessionExtras); impl.setSessionExtras(new Bundle(sessionExtras));
impl.setSessionExtras(sessionExtras);
} }
/** /**
@ -1259,8 +1258,7 @@ public class MediaSession {
*/ */
public final void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) { public final void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) {
checkNotNull(controller, "controller must not be null"); checkNotNull(controller, "controller must not be null");
checkNotNull(sessionExtras); impl.setSessionExtras(controller, new Bundle(sessionExtras));
impl.setSessionExtras(controller, sessionExtras);
} }
/** Returns the {@link BitmapLoader}. */ /** Returns the {@link BitmapLoader}. */
@ -2284,8 +2282,8 @@ public class MediaSession {
checkArgument(player.canAdvertiseSession()); checkArgument(player.canAdvertiseSession());
id = ""; id = "";
this.callback = callback; this.callback = callback;
tokenExtras = Bundle.EMPTY; tokenExtras = new Bundle();
sessionExtras = Bundle.EMPTY; sessionExtras = new Bundle();
customLayout = ImmutableList.of(); customLayout = ImmutableList.of();
mediaButtonPreferences = ImmutableList.of(); mediaButtonPreferences = ImmutableList.of();
playIfSuppressed = true; playIfSuppressed = true;

View File

@ -991,6 +991,62 @@ public class MediaSessionTest {
assertThat(isEventHandled).isFalse(); 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<String> 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) { private static Intent getMediaButtonIntent(int keyCode) {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.setComponent( intent.setComponent(