Skip to content

Commit 4ebe630

Browse files
toniheicopybara-github
authored andcommitted
Split available command filtering and bundling
A few methods in PlayerInfo and related classes combine filtering information with bundling in one method. This makes it impossible to use just the filtering for example and it's also easier to reason about than two dedicated methods. This change splits these methods into two parts accordingly. PiperOrigin-RevId: 572592458
1 parent 7fdc5b2 commit 4ebe630

File tree

7 files changed

+362
-196
lines changed

7 files changed

+362
-196
lines changed

libraries/common/src/main/java/androidx/media3/common/Player.java

Lines changed: 65 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,9 @@ public boolean equals(@Nullable Object o) {
350350
return false;
351351
}
352352
PositionInfo that = (PositionInfo) o;
353-
return mediaItemIndex == that.mediaItemIndex
354-
&& periodIndex == that.periodIndex
355-
&& positionMs == that.positionMs
356-
&& contentPositionMs == that.contentPositionMs
357-
&& adGroupIndex == that.adGroupIndex
358-
&& adIndexInAdGroup == that.adIndexInAdGroup
353+
return equalsForBundling(that)
359354
&& Objects.equal(windowUid, that.windowUid)
360-
&& Objects.equal(periodUid, that.periodUid)
361-
&& Objects.equal(mediaItem, that.mediaItem);
355+
&& Objects.equal(periodUid, that.periodUid);
362356
}
363357

364358
@Override
@@ -375,6 +369,21 @@ public int hashCode() {
375369
adIndexInAdGroup);
376370
}
377371

372+
/**
373+
* Returns whether this position info and the other position info would result in the same
374+
* {@link #toBundle() Bundle}.
375+
*/
376+
@UnstableApi
377+
public boolean equalsForBundling(PositionInfo other) {
378+
return mediaItemIndex == other.mediaItemIndex
379+
&& periodIndex == other.periodIndex
380+
&& positionMs == other.positionMs
381+
&& contentPositionMs == other.contentPositionMs
382+
&& adGroupIndex == other.adGroupIndex
383+
&& adIndexInAdGroup == other.adIndexInAdGroup
384+
&& Objects.equal(mediaItem, other.mediaItem);
385+
}
386+
378387
// Bundleable implementation.
379388

380389
private static final String FIELD_MEDIA_ITEM_INDEX = Util.intToStringMaxRadix(0);
@@ -386,39 +395,66 @@ public int hashCode() {
386395
private static final String FIELD_AD_INDEX_IN_AD_GROUP = Util.intToStringMaxRadix(6);
387396

388397
/**
389-
* {@inheritDoc}
398+
* Returns a copy of this position info, filtered by the specified available commands.
390399
*
391-
* <p>It omits the {@link #windowUid} and {@link #periodUid} fields. The {@link #windowUid} and
392-
* {@link #periodUid} of an instance restored by {@link #CREATOR} will always be {@code null}.
400+
* <p>The filtered fields are reset to their default values.
401+
*
402+
* <p>The return value may be the same object if nothing is filtered.
403+
*
404+
* @param canAccessCurrentMediaItem Whether {@link Player#COMMAND_GET_CURRENT_MEDIA_ITEM} is
405+
* available.
406+
* @param canAccessTimeline Whether {@link Player#COMMAND_GET_TIMELINE} is available.
407+
* @return The filtered position info.
393408
*/
394409
@UnstableApi
395-
@Override
396-
public Bundle toBundle() {
397-
return toBundle(/* canAccessCurrentMediaItem= */ true, /* canAccessTimeline= */ true);
410+
public PositionInfo filterByAvailableCommands(
411+
boolean canAccessCurrentMediaItem, boolean canAccessTimeline) {
412+
if (canAccessCurrentMediaItem && canAccessTimeline) {
413+
return this;
414+
}
415+
return new PositionInfo(
416+
windowUid,
417+
canAccessTimeline ? mediaItemIndex : 0,
418+
canAccessCurrentMediaItem ? mediaItem : null,
419+
periodUid,
420+
canAccessTimeline ? periodIndex : 0,
421+
canAccessCurrentMediaItem ? positionMs : 0,
422+
canAccessCurrentMediaItem ? contentPositionMs : 0,
423+
canAccessCurrentMediaItem ? adGroupIndex : C.INDEX_UNSET,
424+
canAccessCurrentMediaItem ? adIndexInAdGroup : C.INDEX_UNSET);
398425
}
399426

400427
/**
401-
* Returns a {@link Bundle} representing the information stored in this object, filtered by
402-
* available commands.
428+
* {@inheritDoc}
403429
*
404-
* @param canAccessCurrentMediaItem Whether the {@link Bundle} should contain information
405-
* accessbile with {@link #COMMAND_GET_CURRENT_MEDIA_ITEM}.
406-
* @param canAccessTimeline Whether the {@link Bundle} should contain information accessbile
407-
* with {@link #COMMAND_GET_TIMELINE}.
430+
* <p>It omits the {@link #windowUid} and {@link #periodUid} fields. The {@link #windowUid} and
431+
* {@link #periodUid} of an instance restored by {@link #CREATOR} will always be {@code null}.
408432
*/
409433
@UnstableApi
410-
public Bundle toBundle(boolean canAccessCurrentMediaItem, boolean canAccessTimeline) {
434+
@Override
435+
public Bundle toBundle() {
411436
Bundle bundle = new Bundle();
412-
bundle.putInt(FIELD_MEDIA_ITEM_INDEX, canAccessTimeline ? mediaItemIndex : 0);
413-
if (mediaItem != null && canAccessCurrentMediaItem) {
437+
if (mediaItemIndex != 0) {
438+
bundle.putInt(FIELD_MEDIA_ITEM_INDEX, mediaItemIndex);
439+
}
440+
if (mediaItem != null) {
414441
bundle.putBundle(FIELD_MEDIA_ITEM, mediaItem.toBundle());
415442
}
416-
bundle.putInt(FIELD_PERIOD_INDEX, canAccessTimeline ? periodIndex : 0);
417-
bundle.putLong(FIELD_POSITION_MS, canAccessCurrentMediaItem ? positionMs : 0);
418-
bundle.putLong(FIELD_CONTENT_POSITION_MS, canAccessCurrentMediaItem ? contentPositionMs : 0);
419-
bundle.putInt(FIELD_AD_GROUP_INDEX, canAccessCurrentMediaItem ? adGroupIndex : C.INDEX_UNSET);
420-
bundle.putInt(
421-
FIELD_AD_INDEX_IN_AD_GROUP, canAccessCurrentMediaItem ? adIndexInAdGroup : C.INDEX_UNSET);
443+
if (periodIndex != 0) {
444+
bundle.putInt(FIELD_PERIOD_INDEX, periodIndex);
445+
}
446+
if (positionMs != 0) {
447+
bundle.putLong(FIELD_POSITION_MS, positionMs);
448+
}
449+
if (contentPositionMs != 0) {
450+
bundle.putLong(FIELD_CONTENT_POSITION_MS, contentPositionMs);
451+
}
452+
if (adGroupIndex != C.INDEX_UNSET) {
453+
bundle.putInt(FIELD_AD_GROUP_INDEX, adGroupIndex);
454+
}
455+
if (adIndexInAdGroup != C.INDEX_UNSET) {
456+
bundle.putInt(FIELD_AD_INDEX_IN_AD_GROUP, adIndexInAdGroup);
457+
}
422458
return bundle;
423459
}
424460

libraries/common/src/main/java/androidx/media3/common/Timeline.java

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,36 +1443,29 @@ public final Bundle toBundle() {
14431443
}
14441444

14451445
/**
1446-
* Returns a {@link Bundle} containing just the specified {@link Window}.
1446+
* Returns a copy of this timeline containing just the single specified {@link Window}.
14471447
*
1448-
* <p>The {@link #getWindow(int, Window)} windows} and {@link #getPeriod(int, Period) periods} of
1449-
* an instance restored by {@link #CREATOR} may have missing fields as described in {@link
1450-
* Window#toBundle()} and {@link Period#toBundle()}.
1448+
* <p>The method returns the same instance if there is only one window.
14511449
*
1452-
* @param windowIndex The index of the {@link Window} to include in the {@link Bundle}.
1450+
* @param windowIndex The index of the {@link Window} to include in the copy.
1451+
* @return A {@link Timeline} with just the single specified {@link Window}.
14531452
*/
14541453
@UnstableApi
1455-
public final Bundle toBundleWithOneWindowOnly(int windowIndex) {
1454+
public final Timeline copyWithSingleWindow(int windowIndex) {
1455+
if (getWindowCount() == 1) {
1456+
return this;
1457+
}
14561458
Window window = getWindow(windowIndex, new Window(), /* defaultPositionProjectionUs= */ 0);
1457-
1458-
List<Bundle> periodBundles = new ArrayList<>();
1459-
Period period = new Period();
1459+
ImmutableList.Builder<Period> periods = ImmutableList.builder();
14601460
for (int i = window.firstPeriodIndex; i <= window.lastPeriodIndex; i++) {
1461-
getPeriod(i, period, /* setIds= */ false);
1461+
Period period = getPeriod(i, new Period(), /* setIds= */ true);
14621462
period.windowIndex = 0;
1463-
periodBundles.add(period.toBundle());
1463+
periods.add(period);
14641464
}
1465-
14661465
window.lastPeriodIndex = window.lastPeriodIndex - window.firstPeriodIndex;
14671466
window.firstPeriodIndex = 0;
1468-
Bundle windowBundle = window.toBundle();
1469-
1470-
Bundle bundle = new Bundle();
1471-
BundleUtil.putBinder(
1472-
bundle, FIELD_WINDOWS, new BundleListRetriever(ImmutableList.of(windowBundle)));
1473-
BundleUtil.putBinder(bundle, FIELD_PERIODS, new BundleListRetriever(periodBundles));
1474-
bundle.putIntArray(FIELD_SHUFFLED_WINDOW_INDICES, new int[] {0});
1475-
return bundle;
1467+
return new RemotableTimeline(
1468+
ImmutableList.of(window), periods.build(), /* shuffledWindowIndices= */ new int[] {0});
14761469
}
14771470

14781471
/**

libraries/session/src/main/java/androidx/media3/session/ConnectionState.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ public Bundle toBundle() {
111111
MediaUtils.intersect(playerCommandsFromSession, playerCommandsFromPlayer);
112112
bundle.putBundle(
113113
FIELD_PLAYER_INFO,
114-
playerInfo.toBundle(
115-
intersectedCommands, /* excludeTimeline= */ false, /* excludeTracks= */ false));
114+
playerInfo
115+
.filterByAvailableCommands(
116+
intersectedCommands, /* excludeTimeline= */ false, /* excludeTracks= */ false)
117+
.toBundle());
116118
bundle.putInt(FIELD_SESSION_INTERFACE_VERSION, sessionInterfaceVersion);
117119
return bundle;
118120
}

libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,17 +1913,20 @@ public void onPlayerInfoChanged(
19131913
boolean bundlingExclusionsTracks =
19141914
excludeTracks || !availableCommands.contains(Player.COMMAND_GET_TRACKS);
19151915
if (controllerInterfaceVersion >= 2) {
1916+
PlayerInfo filteredPlayerInfo =
1917+
playerInfo.filterByAvailableCommands(availableCommands, excludeTimeline, excludeTracks);
19161918
iController.onPlayerInfoChangedWithExclusions(
19171919
sequenceNumber,
1918-
playerInfo.toBundle(availableCommands, excludeTimeline, excludeTracks),
1920+
filteredPlayerInfo.toBundle(),
19191921
new PlayerInfo.BundlingExclusions(bundlingExclusionsTimeline, bundlingExclusionsTracks)
19201922
.toBundle());
19211923
} else {
1924+
PlayerInfo filteredPlayerInfo =
1925+
playerInfo.filterByAvailableCommands(
1926+
availableCommands, excludeTimeline, /* excludeTracks= */ true);
19221927
//noinspection deprecation
19231928
iController.onPlayerInfoChanged(
1924-
sequenceNumber,
1925-
playerInfo.toBundle(availableCommands, excludeTimeline, /* excludeTracks= */ true),
1926-
bundlingExclusionsTimeline);
1929+
sequenceNumber, filteredPlayerInfo.toBundle(), bundlingExclusionsTimeline);
19271930
}
19281931
}
19291932

@@ -1992,7 +1995,9 @@ public void onPeriodicSessionPositionInfoChanged(
19921995
throws RemoteException {
19931996
iController.onPeriodicSessionPositionInfoChanged(
19941997
sequenceNumber,
1995-
sessionPositionInfo.toBundle(canAccessCurrentMediaItem, canAccessTimeline));
1998+
sessionPositionInfo
1999+
.filterByAvailableCommands(canAccessCurrentMediaItem, canAccessTimeline)
2000+
.toBundle());
19962001
}
19972002

19982003
@Override

0 commit comments

Comments
 (0)