Skip to content

Commit e48a380

Browse files
committed
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.
1 parent ec6ac47 commit e48a380

File tree

5 files changed

+216
-62
lines changed

5 files changed

+216
-62
lines changed

‎libraries/common/src/main/java/androidx/media3/common/MediaItem.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
import static androidx.media3.common.util.Util.usToMs;
2323

2424
import android.net.Uri;
25+
import android.os.Binder;
2526
import android.os.Bundle;
27+
import android.os.IBinder;
2628
import androidx.annotation.IntRange;
2729
import androidx.annotation.Nullable;
30+
import androidx.annotation.RestrictTo;
2831
import androidx.annotation.VisibleForTesting;
2932
import androidx.media3.common.util.Assertions;
3033
import androidx.media3.common.util.BundleCollectionUtil;
@@ -2394,6 +2397,7 @@ public int hashCode() {
23942397
private static final String FIELD_CLIPPING_PROPERTIES = Util.intToStringMaxRadix(3);
23952398
private static final String FIELD_REQUEST_METADATA = Util.intToStringMaxRadix(4);
23962399
private static final String FIELD_LOCAL_CONFIGURATION = Util.intToStringMaxRadix(5);
2400+
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(6);
23972401

23982402
@UnstableApi
23992403
private Bundle toBundle(boolean includeLocalConfiguration) {
@@ -2439,6 +2443,17 @@ public Bundle toBundleIncludeLocalConfiguration() {
24392443
return toBundle(/* includeLocalConfiguration= */ true);
24402444
}
24412445

2446+
/**
2447+
* Returns a {@link Bundle} containing the entirety of this {@link #MediaItem} object without
2448+
* bundling it, for use in local process communication only.
2449+
*/
2450+
@UnstableApi
2451+
public Bundle toBundleIncludeLocalConfigurationForLocalProcess() {
2452+
Bundle bundle = new Bundle();
2453+
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
2454+
return bundle;
2455+
}
2456+
24422457
/**
24432458
* Restores a {@code MediaItem} from a {@link Bundle}.
24442459
*
@@ -2447,6 +2462,10 @@ public Bundle toBundleIncludeLocalConfiguration() {
24472462
@UnstableApi
24482463
@SuppressWarnings("deprecation") // Unbundling to ClippingProperties while it still exists.
24492464
public static MediaItem fromBundle(Bundle bundle) {
2465+
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
2466+
if (inProcessBinder instanceof InProcessBinder) {
2467+
return ((InProcessBinder) inProcessBinder).getMediaItem();
2468+
}
24502469
String mediaId = checkNotNull(bundle.getString(FIELD_MEDIA_ID, DEFAULT_MEDIA_ID));
24512470
@Nullable Bundle liveConfigurationBundle = bundle.getBundle(FIELD_LIVE_CONFIGURATION);
24522471
LiveConfiguration liveConfiguration;
@@ -2491,4 +2510,24 @@ public static MediaItem fromBundle(Bundle bundle) {
24912510
mediaMetadata,
24922511
requestMetadata);
24932512
}
2513+
2514+
private final class InProcessBinder extends Binder {
2515+
public MediaItem getMediaItem() {
2516+
return MediaItem.this;
2517+
}
2518+
}
2519+
2520+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
2521+
@UnstableApi
2522+
public static final class ListInProcessBinder extends Binder {
2523+
private final ImmutableList<MediaItem> theList;
2524+
2525+
public ListInProcessBinder(List<MediaItem> theList) {
2526+
this.theList = ImmutableList.copyOf(theList);
2527+
}
2528+
2529+
public ImmutableList<MediaItem> getMediaItemList() {
2530+
return theList;
2531+
}
2532+
}
24942533
}

‎libraries/common/src/main/java/androidx/media3/common/MediaMetadata.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
import static java.lang.annotation.ElementType.TYPE_USE;
2424

2525
import android.net.Uri;
26+
import android.os.Binder;
2627
import android.os.Bundle;
28+
import android.os.IBinder;
2729
import androidx.annotation.IntDef;
2830
import androidx.annotation.IntRange;
2931
import androidx.annotation.Nullable;
@@ -1334,6 +1336,7 @@ public int hashCode() {
13341336
private static final String FIELD_IS_BROWSABLE = Util.intToStringMaxRadix(32);
13351337
private static final String FIELD_DURATION_MS = Util.intToStringMaxRadix(33);
13361338
private static final String FIELD_SUPPORTED_COMMANDS = Util.intToStringMaxRadix(34);
1339+
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(35);
13371340
private static final String FIELD_EXTRAS = Util.intToStringMaxRadix(1000);
13381341

13391342
@SuppressWarnings("deprecation") // Bundling deprecated fields.
@@ -1448,10 +1451,25 @@ public Bundle toBundle() {
14481451
return bundle;
14491452
}
14501453

1454+
/**
1455+
* Returns a {@link Bundle} containing the entirety of this {@link #MediaMetadata} object without
1456+
* bundling it, for use in local process communication only.
1457+
*/
1458+
@UnstableApi
1459+
public Bundle toBundleForLocalProcess() {
1460+
Bundle bundle = new Bundle();
1461+
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
1462+
return bundle;
1463+
}
1464+
14511465
/** Restores a {@code MediaMetadata} from a {@link Bundle}. */
14521466
@UnstableApi
14531467
@SuppressWarnings("deprecation") // Unbundling deprecated fields.
14541468
public static MediaMetadata fromBundle(Bundle bundle) {
1469+
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
1470+
if (inProcessBinder instanceof InProcessBinder) {
1471+
return ((InProcessBinder) inProcessBinder).getMediaMetadata();
1472+
}
14551473
Builder builder = new Builder();
14561474
builder
14571475
.setTitle(bundle.getCharSequence(FIELD_TITLE))
@@ -1612,4 +1630,10 @@ public static MediaMetadata fromBundle(Bundle bundle) {
16121630
return MEDIA_TYPE_FOLDER_MIXED;
16131631
}
16141632
}
1633+
1634+
private final class InProcessBinder extends Binder {
1635+
public MediaMetadata getMediaMetadata() {
1636+
return MediaMetadata.this;
1637+
}
1638+
}
16151639
}

‎libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
import static java.lang.annotation.RetentionPolicy.SOURCE;
2323

2424
import android.content.Context;
25+
import android.os.Binder;
2526
import android.os.Bundle;
27+
import android.os.IBinder;
2628
import android.view.accessibility.CaptioningManager;
2729
import androidx.annotation.CallSuper;
2830
import androidx.annotation.IntDef;
@@ -1597,6 +1599,7 @@ public int hashCode() {
15971599
private static final String FIELD_PREFERRED_VIDEO_LABELS = Util.intToStringMaxRadix(36);
15981600
private static final String FIELD_PREFERRED_AUDIO_LABELS = Util.intToStringMaxRadix(37);
15991601
private static final String FIELD_PREFERRED_TEXT_LABELS = Util.intToStringMaxRadix(38);
1602+
private static final String FIELD_IN_PROCESS_BINDER = Util.intToStringMaxRadix(39);
16001603

16011604
/**
16021605
* Defines a minimum field ID value for subclasses to use when implementing {@link #toBundle()}
@@ -1675,8 +1678,29 @@ public Bundle toBundle() {
16751678
return bundle;
16761679
}
16771680

1681+
/**
1682+
* Returns a {@link Bundle} containing the entirety of this {@link #TrackSelectionParameters}
1683+
* object without bundling it, for use in local process communication only.
1684+
*/
1685+
@UnstableApi
1686+
public Bundle toBundleForLocalProcess() {
1687+
Bundle bundle = new Bundle();
1688+
bundle.putBinder(FIELD_IN_PROCESS_BINDER, new InProcessBinder());
1689+
return bundle;
1690+
}
1691+
16781692
/** Construct an instance from a {@link Bundle} produced by {@link #toBundle()}. */
16791693
public static TrackSelectionParameters fromBundle(Bundle bundle) {
1694+
IBinder inProcessBinder = bundle.getBinder(FIELD_IN_PROCESS_BINDER);
1695+
if (inProcessBinder instanceof InProcessBinder) {
1696+
return ((InProcessBinder) inProcessBinder).getTrackSelectionParameters();
1697+
}
16801698
return new Builder(bundle).build();
16811699
}
1700+
1701+
private final class InProcessBinder extends Binder {
1702+
public TrackSelectionParameters getTrackSelectionParameters() {
1703+
return TrackSelectionParameters.this;
1704+
}
1705+
}
16821706
}

‎libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java

Lines changed: 73 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,11 @@ public void setMediaItem(MediaItem mediaItem) {
831831
dispatchRemoteSessionTaskWithPlayerCommand(
832832
(iSession, seq) ->
833833
iSession.setMediaItem(
834-
controllerStub, seq, mediaItem.toBundleIncludeLocalConfiguration()));
834+
controllerStub,
835+
seq,
836+
iSession instanceof MediaSessionStub
837+
? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()
838+
: mediaItem.toBundleIncludeLocalConfiguration()));
835839

836840
setMediaItemsInternal(
837841
Collections.singletonList(mediaItem),
@@ -851,7 +855,9 @@ public void setMediaItem(MediaItem mediaItem, long startPositionMs) {
851855
iSession.setMediaItemWithStartPosition(
852856
controllerStub,
853857
seq,
854-
mediaItem.toBundleIncludeLocalConfiguration(),
858+
iSession instanceof MediaSessionStub
859+
? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()
860+
: mediaItem.toBundleIncludeLocalConfiguration(),
855861
startPositionMs));
856862

857863
setMediaItemsInternal(
@@ -870,7 +876,12 @@ public void setMediaItem(MediaItem mediaItem, boolean resetPosition) {
870876
dispatchRemoteSessionTaskWithPlayerCommand(
871877
(iSession, seq) ->
872878
iSession.setMediaItemWithResetPosition(
873-
controllerStub, seq, mediaItem.toBundleIncludeLocalConfiguration(), resetPosition));
879+
controllerStub,
880+
seq,
881+
iSession instanceof MediaSessionStub
882+
? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()
883+
: mediaItem.toBundleIncludeLocalConfiguration(),
884+
resetPosition));
874885

875886
setMediaItemsInternal(
876887
Collections.singletonList(mediaItem),
@@ -890,9 +901,11 @@ public void setMediaItems(List<MediaItem> mediaItems) {
890901
iSession.setMediaItems(
891902
controllerStub,
892903
seq,
893-
new BundleListRetriever(
894-
BundleCollectionUtil.toBundleList(
895-
mediaItems, MediaItem::toBundleIncludeLocalConfiguration))));
904+
iSession instanceof MediaSessionStub
905+
? new MediaItem.ListInProcessBinder(mediaItems)
906+
: new BundleListRetriever(
907+
BundleCollectionUtil.toBundleList(
908+
mediaItems, MediaItem::toBundleIncludeLocalConfiguration))));
896909

897910
setMediaItemsInternal(
898911
mediaItems,
@@ -912,9 +925,11 @@ public void setMediaItems(List<MediaItem> mediaItems, boolean resetPosition) {
912925
iSession.setMediaItemsWithResetPosition(
913926
controllerStub,
914927
seq,
915-
new BundleListRetriever(
916-
BundleCollectionUtil.toBundleList(
917-
mediaItems, MediaItem::toBundleIncludeLocalConfiguration)),
928+
iSession instanceof MediaSessionStub
929+
? new MediaItem.ListInProcessBinder(mediaItems)
930+
: new BundleListRetriever(
931+
BundleCollectionUtil.toBundleList(
932+
mediaItems, MediaItem::toBundleIncludeLocalConfiguration)),
918933
resetPosition));
919934

920935
setMediaItemsInternal(
@@ -935,9 +950,11 @@ public void setMediaItems(List<MediaItem> mediaItems, int startIndex, long start
935950
iSession.setMediaItemsWithStartIndex(
936951
controllerStub,
937952
seq,
938-
new BundleListRetriever(
939-
BundleCollectionUtil.toBundleList(
940-
mediaItems, MediaItem::toBundleIncludeLocalConfiguration)),
953+
iSession instanceof MediaSessionStub
954+
? new MediaItem.ListInProcessBinder(mediaItems)
955+
: new BundleListRetriever(
956+
BundleCollectionUtil.toBundleList(
957+
mediaItems, MediaItem::toBundleIncludeLocalConfiguration)),
941958
startIndex,
942959
startPositionMs));
943960

@@ -953,7 +970,12 @@ public void setPlaylistMetadata(MediaMetadata playlistMetadata) {
953970

954971
dispatchRemoteSessionTaskWithPlayerCommand(
955972
(iSession, seq) ->
956-
iSession.setPlaylistMetadata(controllerStub, seq, playlistMetadata.toBundle()));
973+
iSession.setPlaylistMetadata(
974+
controllerStub,
975+
seq,
976+
iSession instanceof MediaSessionStub
977+
? playlistMetadata.toBundleForLocalProcess()
978+
: playlistMetadata.toBundle()));
957979

958980
if (!playerInfo.playlistMetadata.equals(playlistMetadata)) {
959981
playerInfo = playerInfo.copyWithPlaylistMetadata(playlistMetadata);
@@ -978,7 +1000,11 @@ public void addMediaItem(MediaItem mediaItem) {
9781000
dispatchRemoteSessionTaskWithPlayerCommand(
9791001
(iSession, seq) ->
9801002
iSession.addMediaItem(
981-
controllerStub, seq, mediaItem.toBundleIncludeLocalConfiguration()));
1003+
controllerStub,
1004+
seq,
1005+
iSession instanceof MediaSessionStub
1006+
? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()
1007+
: mediaItem.toBundleIncludeLocalConfiguration()));
9821008

9831009
addMediaItemsInternal(
9841010
getCurrentTimeline().getWindowCount(), Collections.singletonList(mediaItem));
@@ -994,7 +1020,12 @@ public void addMediaItem(int index, MediaItem mediaItem) {
9941020
dispatchRemoteSessionTaskWithPlayerCommand(
9951021
(iSession, seq) ->
9961022
iSession.addMediaItemWithIndex(
997-
controllerStub, seq, index, mediaItem.toBundleIncludeLocalConfiguration()));
1023+
controllerStub,
1024+
seq,
1025+
index,
1026+
iSession instanceof MediaSessionStub
1027+
? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()
1028+
: mediaItem.toBundleIncludeLocalConfiguration()));
9981029

9991030
addMediaItemsInternal(index, Collections.singletonList(mediaItem));
10001031
}
@@ -1010,9 +1041,11 @@ public void addMediaItems(List<MediaItem> mediaItems) {
10101041
iSession.addMediaItems(
10111042
controllerStub,
10121043
seq,
1013-
new BundleListRetriever(
1014-
BundleCollectionUtil.toBundleList(
1015-
mediaItems, MediaItem::toBundleIncludeLocalConfiguration))));
1044+
iSession instanceof MediaSessionStub
1045+
? new MediaItem.ListInProcessBinder(mediaItems)
1046+
: new BundleListRetriever(
1047+
BundleCollectionUtil.toBundleList(
1048+
mediaItems, MediaItem::toBundleIncludeLocalConfiguration))));
10161049

10171050
addMediaItemsInternal(getCurrentTimeline().getWindowCount(), mediaItems);
10181051
}
@@ -1030,9 +1063,11 @@ public void addMediaItems(int index, List<MediaItem> mediaItems) {
10301063
controllerStub,
10311064
seq,
10321065
index,
1033-
new BundleListRetriever(
1034-
BundleCollectionUtil.toBundleList(
1035-
mediaItems, MediaItem::toBundleIncludeLocalConfiguration))));
1066+
iSession instanceof MediaSessionStub
1067+
? new MediaItem.ListInProcessBinder(mediaItems)
1068+
: new BundleListRetriever(
1069+
BundleCollectionUtil.toBundleList(
1070+
mediaItems, MediaItem::toBundleIncludeLocalConfiguration))));
10361071

10371072
addMediaItemsInternal(index, mediaItems);
10381073
}
@@ -1382,7 +1417,12 @@ public void replaceMediaItem(int index, MediaItem mediaItem) {
13821417
(iSession, seq) -> {
13831418
if (checkNotNull(connectedToken).getInterfaceVersion() >= 2) {
13841419
iSession.replaceMediaItem(
1385-
controllerStub, seq, index, mediaItem.toBundleIncludeLocalConfiguration());
1420+
controllerStub,
1421+
seq,
1422+
index,
1423+
iSession instanceof MediaSessionStub
1424+
? mediaItem.toBundleIncludeLocalConfigurationForLocalProcess()
1425+
: mediaItem.toBundleIncludeLocalConfiguration());
13861426
} else {
13871427
iSession.addMediaItemWithIndex(
13881428
controllerStub, seq, index + 1, mediaItem.toBundleIncludeLocalConfiguration());
@@ -1403,9 +1443,11 @@ public void replaceMediaItems(int fromIndex, int toIndex, List<MediaItem> mediaI
14031443
dispatchRemoteSessionTaskWithPlayerCommand(
14041444
(iSession, seq) -> {
14051445
IBinder mediaItemsBundleBinder =
1406-
new BundleListRetriever(
1407-
BundleCollectionUtil.toBundleList(
1408-
mediaItems, MediaItem::toBundleIncludeLocalConfiguration));
1446+
iSession instanceof MediaSessionStub
1447+
? new MediaItem.ListInProcessBinder(mediaItems)
1448+
: new BundleListRetriever(
1449+
BundleCollectionUtil.toBundleList(
1450+
mediaItems, MediaItem::toBundleIncludeLocalConfiguration));
14091451
if (checkNotNull(connectedToken).getInterfaceVersion() >= 2) {
14101452
iSession.replaceMediaItems(
14111453
controllerStub, seq, fromIndex, toIndex, mediaItemsBundleBinder);
@@ -2107,7 +2149,12 @@ public void setTrackSelectionParameters(TrackSelectionParameters parameters) {
21072149

21082150
dispatchRemoteSessionTaskWithPlayerCommand(
21092151
(iSession, seq) ->
2110-
iSession.setTrackSelectionParameters(controllerStub, seq, parameters.toBundle()));
2152+
iSession.setTrackSelectionParameters(
2153+
controllerStub,
2154+
seq,
2155+
iSession instanceof MediaSessionStub
2156+
? parameters.toBundleForLocalProcess()
2157+
: parameters.toBundle()));
21112158

21122159
if (parameters != playerInfo.trackSelectionParameters) {
21132160
playerInfo = playerInfo.copyWithTrackSelectionParameters(parameters);

0 commit comments

Comments
 (0)