From cbd2208aa7bda7d4fae78e67faf840d99393fad7 Mon Sep 17 00:00:00 2001 From: nift4 Date: Wed, 23 Jul 2025 15:00:48 +0200 Subject: [PATCH] Make MediaControllerImplBase local binder aware The session->controller data flow already nicely avoids bundling if we don't have to bundle by skipping the entire PlayerInfo object which contains almost everything. But in the controller->session data flow, some complex objects (MediaMetadata, MediaItem and TrackSelectionParameters) were always bundled even if we don't have to. This change skips bundling for these object and should improve performance significantly when sending large lists of MediaItems to a session in the same process. --- .../androidx/media3/common/MediaItem.java | 39 ++++++++ .../androidx/media3/common/MediaMetadata.java | 24 +++++ .../common/TrackSelectionParameters.java | 24 +++++ .../androidx/media3/common/MediaItemTest.java | 9 ++ .../media3/common/MediaMetadataTest.java | 9 ++ .../common/TrackSelectionParametersTest.java | 10 ++ .../session/MediaControllerImplBase.java | 99 ++++++++++++++----- .../media3/session/MediaSessionStub.java | 92 ++++++++++------- 8 files changed, 244 insertions(+), 62 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/MediaItem.java b/libraries/common/src/main/java/androidx/media3/common/MediaItem.java index 757752da2f6..aac18faad88 100644 --- a/libraries/common/src/main/java/androidx/media3/common/MediaItem.java +++ b/libraries/common/src/main/java/androidx/media3/common/MediaItem.java @@ -22,9 +22,12 @@ import static androidx.media3.common.util.Util.usToMs; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; +import android.os.IBinder; import androidx.annotation.IntRange; import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; import androidx.annotation.VisibleForTesting; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.BundleCollectionUtil; @@ -2394,6 +2397,7 @@ public int hashCode() { private static final String FIELD_CLIPPING_PROPERTIES = Util.intToStringMaxRadix(3); private static final String FIELD_REQUEST_METADATA = Util.intToStringMaxRadix(4); private static final String FIELD_LOCAL_CONFIGURATION = Util.intToStringMaxRadix(5); + private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(6); @UnstableApi private Bundle toBundle(boolean includeLocalConfiguration) { @@ -2439,6 +2443,17 @@ public Bundle toBundleIncludeLocalConfiguration() { return toBundle(/* includeLocalConfiguration= */ true); } + /** + * Returns a {@link Bundle} containing the entirety of this {@link #MediaItem} object without + * bundling it, for use in local process communication only. + */ + @UnstableApi + public Bundle toBundleIncludeLocalConfigurationForLocalProcess() { + Bundle bundle = new Bundle(); + bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder()); + return bundle; + } + /** * Restores a {@code MediaItem} from a {@link Bundle}. * @@ -2447,6 +2462,10 @@ public Bundle toBundleIncludeLocalConfiguration() { @UnstableApi @SuppressWarnings("deprecation") // Unbundling to ClippingProperties while it still exists. public static MediaItem fromBundle(Bundle bundle) { + IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER); + if (inProcessBinder instanceof InProcessBinder) { + return ((InProcessBinder) inProcessBinder).getMediaItem(); + } String mediaId = checkNotNull(bundle.getString(FIELD_MEDIA_ID, DEFAULT_MEDIA_ID)); @Nullable Bundle liveConfigurationBundle = bundle.getBundle(FIELD_LIVE_CONFIGURATION); LiveConfiguration liveConfiguration; @@ -2491,4 +2510,24 @@ public static MediaItem fromBundle(Bundle bundle) { mediaMetadata, requestMetadata); } + + private final class InProcessBinder extends Binder { + public MediaItem getMediaItem() { + return MediaItem.this; + } + } + + @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) + @UnstableApi + public static final class ListInProcessBinder extends Binder { + private final ImmutableList theList; + + public ListInProcessBinder(List theList) { + this.theList = ImmutableList.copyOf(theList); + } + + public ImmutableList getMediaItemList() { + return theList; + } + } } diff --git a/libraries/common/src/main/java/androidx/media3/common/MediaMetadata.java b/libraries/common/src/main/java/androidx/media3/common/MediaMetadata.java index 7c686acfb24..75aee9b665b 100644 --- a/libraries/common/src/main/java/androidx/media3/common/MediaMetadata.java +++ b/libraries/common/src/main/java/androidx/media3/common/MediaMetadata.java @@ -23,7 +23,9 @@ import static java.lang.annotation.ElementType.TYPE_USE; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; +import android.os.IBinder; import androidx.annotation.IntDef; import androidx.annotation.IntRange; import androidx.annotation.Nullable; @@ -1334,6 +1336,7 @@ public int hashCode() { private static final String FIELD_IS_BROWSABLE = Util.intToStringMaxRadix(32); private static final String FIELD_DURATION_MS = Util.intToStringMaxRadix(33); private static final String FIELD_SUPPORTED_COMMANDS = Util.intToStringMaxRadix(34); + private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(35); private static final String FIELD_EXTRAS = Util.intToStringMaxRadix(1000); @SuppressWarnings("deprecation") // Bundling deprecated fields. @@ -1448,10 +1451,25 @@ public Bundle toBundle() { return bundle; } + /** + * Returns a {@link Bundle} containing the entirety of this {@link #MediaMetadata} object without + * bundling it, for use in local process communication only. + */ + @UnstableApi + public Bundle toBundleForLocalProcess() { + Bundle bundle = new Bundle(); + bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder()); + return bundle; + } + /** Restores a {@code MediaMetadata} from a {@link Bundle}. */ @UnstableApi @SuppressWarnings("deprecation") // Unbundling deprecated fields. public static MediaMetadata fromBundle(Bundle bundle) { + IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER); + if (inProcessBinder instanceof InProcessBinder) { + return ((InProcessBinder) inProcessBinder).getMediaMetadata(); + } Builder builder = new Builder(); builder .setTitle(bundle.getCharSequence(FIELD_TITLE)) @@ -1612,4 +1630,10 @@ public static MediaMetadata fromBundle(Bundle bundle) { return MEDIA_TYPE_FOLDER_MIXED; } } + + private final class InProcessBinder extends Binder { + public MediaMetadata getMediaMetadata() { + return MediaMetadata.this; + } + } } diff --git a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java index b28a4dadbc2..ba27c8f5d30 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java +++ b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java @@ -22,7 +22,9 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.content.Context; +import android.os.Binder; import android.os.Bundle; +import android.os.IBinder; import android.view.accessibility.CaptioningManager; import androidx.annotation.CallSuper; import androidx.annotation.IntDef; @@ -1597,6 +1599,7 @@ public int hashCode() { private static final String FIELD_PREFERRED_VIDEO_LABELS = Util.intToStringMaxRadix(36); private static final String FIELD_PREFERRED_AUDIO_LABELS = Util.intToStringMaxRadix(37); private static final String FIELD_PREFERRED_TEXT_LABELS = Util.intToStringMaxRadix(38); + private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(39); /** * Defines a minimum field ID value for subclasses to use when implementing {@link #toBundle()} @@ -1675,8 +1678,29 @@ public Bundle toBundle() { return bundle; } + /** + * Returns a {@link Bundle} containing the entirety of this {@link #TrackSelectionParameters} + * object without bundling it, for use in local process communication only. + */ + @UnstableApi + public Bundle toBundleForLocalProcess() { + Bundle bundle = new Bundle(); + bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder()); + return bundle; + } + /** Construct an instance from a {@link Bundle} produced by {@link #toBundle()}. */ public static TrackSelectionParameters fromBundle(Bundle bundle) { + IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER); + if (inProcessBinder instanceof InProcessBinder) { + return ((InProcessBinder) inProcessBinder).getTrackSelectionParameters(); + } return new Builder(bundle).build(); } + + private final class InProcessBinder extends Binder { + public TrackSelectionParameters getTrackSelectionParameters() { + return TrackSelectionParameters.this; + } + } } diff --git a/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java b/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java index cda440568ae..c4459ac6610 100644 --- a/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/MediaItemTest.java @@ -1021,6 +1021,15 @@ public void buildUpon_wholeObjectSetters_equalsToOriginal() { assertThat(copy).isEqualTo(mediaItem); } + @Test + public void roundTripViaBundleForLocalProcess_yieldsSameInstance() { + MediaItem mediaItem = new MediaItem.Builder().setUri(URI_STRING).build(); + MediaItem unbundledItem = + MediaItem.fromBundle(mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()); + + assertThat(mediaItem == unbundledItem).isTrue(); + } + @Test public void roundTripViaBundle_withoutLocalConfiguration_yieldsEqualInstance() { MediaItem mediaItem = diff --git a/libraries/common/src/test/java/androidx/media3/common/MediaMetadataTest.java b/libraries/common/src/test/java/androidx/media3/common/MediaMetadataTest.java index 54904024028..c9baf2f037f 100644 --- a/libraries/common/src/test/java/androidx/media3/common/MediaMetadataTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/MediaMetadataTest.java @@ -180,6 +180,15 @@ public void roundTripViaBundle_withJustNonNullExtras_restoresAllData() { assertThat(restoredMetadata.extras.get("key")).isEqualTo("value"); } + @Test + public void roundTripViaBundleForLocalProcess_yieldsSameInstance() { + MediaMetadata mediaMetadata = new MediaMetadata.Builder().setGenre("hi").build(); + MediaMetadata unbundledMetadata = + MediaMetadata.fromBundle(mediaMetadata.toBundleForLocalProcess()); + + assertThat(mediaMetadata == unbundledMetadata).isTrue(); + } + @SuppressWarnings("deprecation") // Testing deprecated setter. @Test public void builderSetFolderType_toNone_setsIsBrowsableToFalse() { diff --git a/libraries/common/src/test/java/androidx/media3/common/TrackSelectionParametersTest.java b/libraries/common/src/test/java/androidx/media3/common/TrackSelectionParametersTest.java index 62b95697cfc..139368fa537 100644 --- a/libraries/common/src/test/java/androidx/media3/common/TrackSelectionParametersTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/TrackSelectionParametersTest.java @@ -239,6 +239,16 @@ public void roundTripViaBundle_withOverride_yieldsEqualInstance() { .containsExactly(override.mediaTrackGroup, override); } + @Test + public void roundTripViaBundleForLocalProcess_yieldsSameInstance() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder().setMaxVideoSizeSd().build(); + TrackSelectionParameters unbundledParameters = + TrackSelectionParameters.fromBundle(parameters.toBundleForLocalProcess()); + + assertThat(parameters == unbundledParameters).isTrue(); + } + @Test public void roundTripViaBundle_withLegacyPreferenceFields_yieldsEqualInstance() { TrackSelectionParameters trackSelectionParameters = 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 5c7d4b29ee3..c1316e9f361 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java @@ -831,7 +831,11 @@ public void setMediaItem(MediaItem mediaItem) { dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> iSession.setMediaItem( - controllerStub, seq, mediaItem.toBundleIncludeLocalConfiguration())); + controllerStub, + seq, + iSession instanceof MediaSessionStub + ? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess() + : mediaItem.toBundleIncludeLocalConfiguration())); setMediaItemsInternal( Collections.singletonList(mediaItem), @@ -851,7 +855,9 @@ public void setMediaItem(MediaItem mediaItem, long startPositionMs) { iSession.setMediaItemWithStartPosition( controllerStub, seq, - mediaItem.toBundleIncludeLocalConfiguration(), + iSession instanceof MediaSessionStub + ? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess() + : mediaItem.toBundleIncludeLocalConfiguration(), startPositionMs)); setMediaItemsInternal( @@ -870,7 +876,12 @@ public void setMediaItem(MediaItem mediaItem, boolean resetPosition) { dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> iSession.setMediaItemWithResetPosition( - controllerStub, seq, mediaItem.toBundleIncludeLocalConfiguration(), resetPosition)); + controllerStub, + seq, + iSession instanceof MediaSessionStub + ? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess() + : mediaItem.toBundleIncludeLocalConfiguration(), + resetPosition)); setMediaItemsInternal( Collections.singletonList(mediaItem), @@ -890,9 +901,11 @@ public void setMediaItems(List mediaItems) { iSession.setMediaItems( controllerStub, seq, - new BundleListRetriever( - BundleCollectionUtil.toBundleList( - mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); + iSession instanceof MediaSessionStub + ? new MediaItem.ListInProcessBinder(mediaItems) + : new BundleListRetriever( + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); setMediaItemsInternal( mediaItems, @@ -912,9 +925,11 @@ public void setMediaItems(List mediaItems, boolean resetPosition) { iSession.setMediaItemsWithResetPosition( controllerStub, seq, - new BundleListRetriever( - BundleCollectionUtil.toBundleList( - mediaItems, MediaItem::toBundleIncludeLocalConfiguration)), + iSession instanceof MediaSessionStub + ? new MediaItem.ListInProcessBinder(mediaItems) + : new BundleListRetriever( + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)), resetPosition)); setMediaItemsInternal( @@ -935,9 +950,11 @@ public void setMediaItems(List mediaItems, int startIndex, long start iSession.setMediaItemsWithStartIndex( controllerStub, seq, - new BundleListRetriever( - BundleCollectionUtil.toBundleList( - mediaItems, MediaItem::toBundleIncludeLocalConfiguration)), + iSession instanceof MediaSessionStub + ? new MediaItem.ListInProcessBinder(mediaItems) + : new BundleListRetriever( + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)), startIndex, startPositionMs)); @@ -953,7 +970,12 @@ public void setPlaylistMetadata(MediaMetadata playlistMetadata) { dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> - iSession.setPlaylistMetadata(controllerStub, seq, playlistMetadata.toBundle())); + iSession.setPlaylistMetadata( + controllerStub, + seq, + iSession instanceof MediaSessionStub + ? playlistMetadata.toBundleForLocalProcess() + : playlistMetadata.toBundle())); if (!playerInfo.playlistMetadata.equals(playlistMetadata)) { playerInfo = playerInfo.copyWithPlaylistMetadata(playlistMetadata); @@ -978,7 +1000,11 @@ public void addMediaItem(MediaItem mediaItem) { dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> iSession.addMediaItem( - controllerStub, seq, mediaItem.toBundleIncludeLocalConfiguration())); + controllerStub, + seq, + iSession instanceof MediaSessionStub + ? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess() + : mediaItem.toBundleIncludeLocalConfiguration())); addMediaItemsInternal( getCurrentTimeline().getWindowCount(), Collections.singletonList(mediaItem)); @@ -994,7 +1020,12 @@ public void addMediaItem(int index, MediaItem mediaItem) { dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> iSession.addMediaItemWithIndex( - controllerStub, seq, index, mediaItem.toBundleIncludeLocalConfiguration())); + controllerStub, + seq, + index, + iSession instanceof MediaSessionStub + ? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess() + : mediaItem.toBundleIncludeLocalConfiguration())); addMediaItemsInternal(index, Collections.singletonList(mediaItem)); } @@ -1010,9 +1041,11 @@ public void addMediaItems(List mediaItems) { iSession.addMediaItems( controllerStub, seq, - new BundleListRetriever( - BundleCollectionUtil.toBundleList( - mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); + iSession instanceof MediaSessionStub + ? new MediaItem.ListInProcessBinder(mediaItems) + : new BundleListRetriever( + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); addMediaItemsInternal(getCurrentTimeline().getWindowCount(), mediaItems); } @@ -1030,9 +1063,11 @@ public void addMediaItems(int index, List mediaItems) { controllerStub, seq, index, - new BundleListRetriever( - BundleCollectionUtil.toBundleList( - mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); + iSession instanceof MediaSessionStub + ? new MediaItem.ListInProcessBinder(mediaItems) + : new BundleListRetriever( + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)))); addMediaItemsInternal(index, mediaItems); } @@ -1382,7 +1417,12 @@ public void replaceMediaItem(int index, MediaItem mediaItem) { (iSession, seq) -> { if (checkNotNull(connectedToken).getInterfaceVersion() >= 2) { iSession.replaceMediaItem( - controllerStub, seq, index, mediaItem.toBundleIncludeLocalConfiguration()); + controllerStub, + seq, + index, + iSession instanceof MediaSessionStub + ? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess() + : mediaItem.toBundleIncludeLocalConfiguration()); } else { iSession.addMediaItemWithIndex( controllerStub, seq, index + 1, mediaItem.toBundleIncludeLocalConfiguration()); @@ -1403,9 +1443,11 @@ public void replaceMediaItems(int fromIndex, int toIndex, List mediaI dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> { IBinder mediaItemsBundleBinder = - new BundleListRetriever( - BundleCollectionUtil.toBundleList( - mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); + iSession instanceof MediaSessionStub + ? new MediaItem.ListInProcessBinder(mediaItems) + : new BundleListRetriever( + BundleCollectionUtil.toBundleList( + mediaItems, MediaItem::toBundleIncludeLocalConfiguration)); if (checkNotNull(connectedToken).getInterfaceVersion() >= 2) { iSession.replaceMediaItems( controllerStub, seq, fromIndex, toIndex, mediaItemsBundleBinder); @@ -2107,7 +2149,12 @@ public void setTrackSelectionParameters(TrackSelectionParameters parameters) { dispatchRemoteSessionTaskWithPlayerCommand( (iSession, seq) -> - iSession.setTrackSelectionParameters(controllerStub, seq, parameters.toBundle())); + iSession.setTrackSelectionParameters( + controllerStub, + seq, + iSession instanceof MediaSessionStub + ? parameters.toBundleForLocalProcess() + : parameters.toBundle())); if (parameters != playerInfo.trackSelectionParameters) { playerInfo = playerInfo.copyWithTrackSelectionParameters(parameters); 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 0d5c65227c9..e973d206da8 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java @@ -1106,13 +1106,17 @@ public void setMediaItemsWithResetPosition( return; } List mediaItemList; - try { - mediaItemList = - BundleCollectionUtil.fromBundleList( - MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); - } catch (RuntimeException e) { - Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); - return; + if (mediaItemsRetriever instanceof MediaItem.ListInProcessBinder) { + mediaItemList = ((MediaItem.ListInProcessBinder) mediaItemsRetriever).getMediaItemList(); + } else { + try { + mediaItemList = + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); + } catch (RuntimeException e) { + Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); + return; + } } queueSessionTaskWithPlayerCommand( caller, @@ -1146,13 +1150,17 @@ public void setMediaItemsWithStartIndex( return; } List mediaItemList; - try { - mediaItemList = - BundleCollectionUtil.fromBundleList( - MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); - } catch (RuntimeException e) { - Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); - return; + if (mediaItemsRetriever instanceof MediaItem.ListInProcessBinder) { + mediaItemList = ((MediaItem.ListInProcessBinder) mediaItemsRetriever).getMediaItemList(); + } else { + try { + mediaItemList = + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); + } catch (RuntimeException e) { + Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); + return; + } } queueSessionTaskWithPlayerCommand( caller, @@ -1258,13 +1266,17 @@ public void addMediaItems( return; } List mediaItems; - try { - mediaItems = - BundleCollectionUtil.fromBundleList( - MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); - } catch (RuntimeException e) { - Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); - return; + if (mediaItemsRetriever instanceof MediaItem.ListInProcessBinder) { + mediaItems = ((MediaItem.ListInProcessBinder) mediaItemsRetriever).getMediaItemList(); + } else { + try { + mediaItems = + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); + } catch (RuntimeException e) { + Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); + return; + } } queueSessionTaskWithPlayerCommand( caller, @@ -1287,13 +1299,17 @@ public void addMediaItemsWithIndex( return; } List mediaItems; - try { - mediaItems = - BundleCollectionUtil.fromBundleList( - MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); - } catch (RuntimeException e) { - Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); - return; + if (mediaItemsRetriever instanceof MediaItem.ListInProcessBinder) { + mediaItems = ((MediaItem.ListInProcessBinder) mediaItemsRetriever).getMediaItemList(); + } else { + try { + mediaItems = + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); + } catch (RuntimeException e) { + Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); + return; + } } queueSessionTaskWithPlayerCommand( caller, @@ -1428,14 +1444,18 @@ public void replaceMediaItems( if (caller == null || mediaItemsRetriever == null || fromIndex < 0 || toIndex < fromIndex) { return; } - ImmutableList mediaItems; - try { - mediaItems = - BundleCollectionUtil.fromBundleList( - MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); - } catch (RuntimeException e) { - Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); - return; + List mediaItems; + if (mediaItemsRetriever instanceof MediaItem.ListInProcessBinder) { + mediaItems = ((MediaItem.ListInProcessBinder) mediaItemsRetriever).getMediaItemList(); + } else { + try { + mediaItems = + BundleCollectionUtil.fromBundleList( + MediaItem::fromBundle, BundleListRetriever.getList(mediaItemsRetriever)); + } catch (RuntimeException e) { + Log.w(TAG, "Ignoring malformed Bundle for MediaItem", e); + return; + } } queueSessionTaskWithPlayerCommand( caller,