diff --git a/libraries/common/src/main/java/androidx/media3/common/Player.java b/libraries/common/src/main/java/androidx/media3/common/Player.java index 5d157a2b0f..3873f5eb9d 100644 --- a/libraries/common/src/main/java/androidx/media3/common/Player.java +++ b/libraries/common/src/main/java/androidx/media3/common/Player.java @@ -286,16 +286,31 @@ public interface Player { @UnstableApi @Override public Bundle toBundle() { + return toBundle(/* canAccessCurrentMediaItem= */ true, /* canAccessTimeline= */ true); + } + + /** + * Returns a {@link Bundle} representing the information stored in this object, filtered by + * available commands. + * + * @param canAccessCurrentMediaItem Whether the {@link Bundle} should contain information + * accessbile with {@link #COMMAND_GET_CURRENT_MEDIA_ITEM}. + * @param canAccessTimeline Whether the {@link Bundle} should contain information accessbile + * with {@link #COMMAND_GET_TIMELINE}. + */ + @UnstableApi + public Bundle toBundle(boolean canAccessCurrentMediaItem, boolean canAccessTimeline) { Bundle bundle = new Bundle(); - bundle.putInt(FIELD_MEDIA_ITEM_INDEX, mediaItemIndex); - if (mediaItem != null) { + bundle.putInt(FIELD_MEDIA_ITEM_INDEX, canAccessTimeline ? mediaItemIndex : 0); + if (mediaItem != null && canAccessCurrentMediaItem) { bundle.putBundle(FIELD_MEDIA_ITEM, mediaItem.toBundle()); } - bundle.putInt(FIELD_PERIOD_INDEX, periodIndex); - bundle.putLong(FIELD_POSITION_MS, positionMs); - bundle.putLong(FIELD_CONTENT_POSITION_MS, contentPositionMs); - bundle.putInt(FIELD_AD_GROUP_INDEX, adGroupIndex); - bundle.putInt(FIELD_AD_INDEX_IN_AD_GROUP, adIndexInAdGroup); + bundle.putInt(FIELD_PERIOD_INDEX, canAccessTimeline ? periodIndex : 0); + bundle.putLong(FIELD_POSITION_MS, canAccessCurrentMediaItem ? positionMs : 0); + bundle.putLong(FIELD_CONTENT_POSITION_MS, canAccessCurrentMediaItem ? contentPositionMs : 0); + bundle.putInt(FIELD_AD_GROUP_INDEX, canAccessCurrentMediaItem ? adGroupIndex : C.INDEX_UNSET); + bundle.putInt( + FIELD_AD_INDEX_IN_AD_GROUP, canAccessCurrentMediaItem ? adIndexInAdGroup : C.INDEX_UNSET); return bundle; } @@ -303,15 +318,14 @@ public interface Player { @UnstableApi public static final Creator CREATOR = PositionInfo::fromBundle; private static PositionInfo fromBundle(Bundle bundle) { - int mediaItemIndex = bundle.getInt(FIELD_MEDIA_ITEM_INDEX, /* defaultValue= */ C.INDEX_UNSET); + int mediaItemIndex = bundle.getInt(FIELD_MEDIA_ITEM_INDEX, /* defaultValue= */ 0); @Nullable Bundle mediaItemBundle = bundle.getBundle(FIELD_MEDIA_ITEM); @Nullable MediaItem mediaItem = mediaItemBundle == null ? null : MediaItem.CREATOR.fromBundle(mediaItemBundle); - int periodIndex = bundle.getInt(FIELD_PERIOD_INDEX, /* defaultValue= */ C.INDEX_UNSET); - long positionMs = bundle.getLong(FIELD_POSITION_MS, /* defaultValue= */ C.TIME_UNSET); - long contentPositionMs = - bundle.getLong(FIELD_CONTENT_POSITION_MS, /* defaultValue= */ C.TIME_UNSET); + int periodIndex = bundle.getInt(FIELD_PERIOD_INDEX, /* defaultValue= */ 0); + long positionMs = bundle.getLong(FIELD_POSITION_MS, /* defaultValue= */ 0); + long contentPositionMs = bundle.getLong(FIELD_CONTENT_POSITION_MS, /* defaultValue= */ 0); int adGroupIndex = bundle.getInt(FIELD_AD_GROUP_INDEX, /* defaultValue= */ C.INDEX_UNSET); int adIndexInAdGroup = bundle.getInt(FIELD_AD_INDEX_IN_AD_GROUP, /* defaultValue= */ C.INDEX_UNSET); @@ -2295,6 +2309,9 @@ public interface Player { *

Note: When the repeat mode is {@link #REPEAT_MODE_ONE}, this method behaves the same as when * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more * details. + * + *

This method must only be called if {@link #COMMAND_GET_TIMELINE} is {@linkplain + * #getAvailableCommands() available}. */ boolean hasPreviousMediaItem(); @@ -2381,6 +2398,9 @@ public interface Player { *

Note: When the repeat mode is {@link #REPEAT_MODE_ONE}, this method behaves the same as when * the current repeat mode is {@link #REPEAT_MODE_OFF}. See {@link #REPEAT_MODE_ONE} for more * details. + * + *

This method must only be called if {@link #COMMAND_GET_TIMELINE} is {@linkplain + * #getAvailableCommands() available}. */ boolean hasNextMediaItem(); 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 29b57bd0c5..c7ca83d86a 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -1163,7 +1163,11 @@ public class MediaSession { throws RemoteException {} default void onPeriodicSessionPositionInfoChanged( - int seq, SessionPositionInfo sessionPositionInfo) throws RemoteException {} + int seq, + SessionPositionInfo sessionPositionInfo, + boolean canAccessCurrentMediaItem, + boolean canAccessTimeline) + throws RemoteException {} // Mostly matched with MediaController.ControllerCallback diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java index b5ab1b28c1..5d65a88d8e 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -602,6 +602,38 @@ import org.checkerframework.checker.initialization.qual.Initialized; } } + private void dispatchOnPeriodicSessionPositionInfoChanged( + SessionPositionInfo sessionPositionInfo) { + ConnectedControllersManager controllersManager = + sessionStub.getConnectedControllersManager(); + List controllers = + sessionStub.getConnectedControllersManager().getConnectedControllers(); + for (int i = 0; i < controllers.size(); i++) { + ControllerInfo controller = controllers.get(i); + boolean canAccessCurrentMediaItem = + controllersManager.isPlayerCommandAvailable( + controller, Player.COMMAND_GET_CURRENT_MEDIA_ITEM); + boolean canAccessTimeline = + controllersManager.isPlayerCommandAvailable(controller, Player.COMMAND_GET_TIMELINE); + dispatchRemoteControllerTaskWithoutReturn( + controller, + (controllerCb, seq) -> + controllerCb.onPeriodicSessionPositionInfoChanged( + seq, sessionPositionInfo, canAccessCurrentMediaItem, canAccessTimeline)); + } + try { + sessionLegacyStub + .getControllerLegacyCbForBroadcast() + .onPeriodicSessionPositionInfoChanged( + /* seq= */ 0, + sessionPositionInfo, + /* canAccessCurrentMediaItem= */ true, + /* canAccessTimeline= */ true); + } catch (RemoteException e) { + Log.e(TAG, "Exception in using media1 API", e); + } + } + protected void dispatchRemoteControllerTaskWithoutReturn(RemoteControllerTask task) { List controllers = sessionStub.getConnectedControllersManager().getConnectedControllers(); @@ -720,8 +752,7 @@ import org.checkerframework.checker.initialization.qual.Initialized; } } SessionPositionInfo sessionPositionInfo = playerWrapper.createSessionPositionInfoForBundling(); - dispatchRemoteControllerTaskWithoutReturn( - (callback, seq) -> callback.onPeriodicSessionPositionInfoChanged(seq, sessionPositionInfo)); + dispatchOnPeriodicSessionPositionInfoChanged(sessionPositionInfo); schedulePeriodicSessionPositionInfoChanges(); } diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java index e130763ea2..d49b5b1666 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java @@ -1175,7 +1175,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @Override public void onPeriodicSessionPositionInfoChanged( - int unusedSeq, SessionPositionInfo unusedSessionPositionInfo) throws RemoteException { + int unusedSeq, + SessionPositionInfo unusedSessionPositionInfo, + boolean unusedCanAccessCurrentMediaItem, + boolean unusedCanAccessTimeline) + throws RemoteException { sessionImpl .getSessionCompat() .setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat()); 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 1cbb8106d5..3a36b80368 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java @@ -1684,9 +1684,14 @@ import java.util.concurrent.ExecutionException; @Override public void onPeriodicSessionPositionInfoChanged( - int sequenceNumber, SessionPositionInfo sessionPositionInfo) throws RemoteException { + int sequenceNumber, + SessionPositionInfo sessionPositionInfo, + boolean canAccessCurrentMediaItem, + boolean canAccessTimeline) + throws RemoteException { iController.onPeriodicSessionPositionInfoChanged( - sequenceNumber, sessionPositionInfo.toBundle()); + sequenceNumber, + sessionPositionInfo.toBundle(canAccessCurrentMediaItem, canAccessTimeline)); } @Override diff --git a/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java b/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java index 85ff904b80..93433bc2da 100644 --- a/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java +++ b/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java @@ -801,38 +801,53 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; public Bundle toBundle( Player.Commands availableCommands, boolean excludeTimeline, boolean excludeTracks) { Bundle bundle = new Bundle(); + boolean canAccessCurrentMediaItem = + availableCommands.contains(Player.COMMAND_GET_CURRENT_MEDIA_ITEM); + boolean canAccessTimeline = availableCommands.contains(Player.COMMAND_GET_TIMELINE); if (playerError != null) { bundle.putBundle(FIELD_PLAYBACK_ERROR, playerError.toBundle()); } bundle.putInt(FIELD_MEDIA_ITEM_TRANSITION_REASON, mediaItemTransitionReason); - bundle.putBundle(FIELD_SESSION_POSITION_INFO, sessionPositionInfo.toBundle()); - bundle.putBundle(FIELD_OLD_POSITION_INFO, oldPositionInfo.toBundle()); - bundle.putBundle(FIELD_NEW_POSITION_INFO, newPositionInfo.toBundle()); + bundle.putBundle( + FIELD_SESSION_POSITION_INFO, + sessionPositionInfo.toBundle(canAccessCurrentMediaItem, canAccessTimeline)); + bundle.putBundle( + FIELD_OLD_POSITION_INFO, + oldPositionInfo.toBundle(canAccessCurrentMediaItem, canAccessTimeline)); + bundle.putBundle( + FIELD_NEW_POSITION_INFO, + newPositionInfo.toBundle(canAccessCurrentMediaItem, canAccessTimeline)); bundle.putInt(FIELD_DISCONTINUITY_REASON, discontinuityReason); bundle.putBundle(FIELD_PLAYBACK_PARAMETERS, playbackParameters.toBundle()); bundle.putInt(FIELD_REPEAT_MODE, repeatMode); bundle.putBoolean(FIELD_SHUFFLE_MODE_ENABLED, shuffleModeEnabled); - if (!excludeTimeline && availableCommands.contains(Player.COMMAND_GET_TIMELINE)) { + if (!excludeTimeline && canAccessTimeline) { bundle.putBundle(FIELD_TIMELINE, timeline.toBundle()); } bundle.putBundle(FIELD_VIDEO_SIZE, videoSize.toBundle()); if (availableCommands.contains(Player.COMMAND_GET_MEDIA_ITEMS_METADATA)) { bundle.putBundle(FIELD_PLAYLIST_METADATA, playlistMetadata.toBundle()); } - bundle.putFloat(FIELD_VOLUME, volume); - bundle.putBundle(FIELD_AUDIO_ATTRIBUTES, audioAttributes.toBundle()); + if (availableCommands.contains(Player.COMMAND_GET_VOLUME)) { + bundle.putFloat(FIELD_VOLUME, volume); + } + if (availableCommands.contains(Player.COMMAND_GET_AUDIO_ATTRIBUTES)) { + bundle.putBundle(FIELD_AUDIO_ATTRIBUTES, audioAttributes.toBundle()); + } if (availableCommands.contains(Player.COMMAND_GET_TEXT)) { bundle.putBundle(FIELD_CUE_GROUP, cueGroup.toBundle()); } bundle.putBundle(FIELD_DEVICE_INFO, deviceInfo.toBundle()); - bundle.putInt(FIELD_DEVICE_VOLUME, deviceVolume); - bundle.putBoolean(FIELD_DEVICE_MUTED, deviceMuted); + if (availableCommands.contains(Player.COMMAND_GET_DEVICE_VOLUME)) { + bundle.putInt(FIELD_DEVICE_VOLUME, deviceVolume); + bundle.putBoolean(FIELD_DEVICE_MUTED, deviceMuted); + } bundle.putBoolean(FIELD_PLAY_WHEN_READY, playWhenReady); bundle.putInt(FIELD_PLAYBACK_SUPPRESSION_REASON, playbackSuppressionReason); bundle.putInt(FIELD_PLAYBACK_STATE, playbackState); bundle.putBoolean(FIELD_IS_PLAYING, isPlaying); bundle.putBoolean(FIELD_IS_LOADING, isLoading); - if (availableCommands.contains(Player.COMMAND_GET_TIMELINE)) { + if (availableCommands.contains(Player.COMMAND_GET_MEDIA_ITEMS_METADATA)) { bundle.putBundle(FIELD_MEDIA_METADATA, mediaMetadata.toBundle()); } bundle.putLong(FIELD_SEEK_BACK_INCREMENT_MS, seekBackIncrementMs); @@ -842,7 +857,6 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; bundle.putBundle(FIELD_CURRENT_TRACKS, currentTracks.toBundle()); } bundle.putBundle(FIELD_TRACK_SELECTION_PARAMETERS, trackSelectionParameters.toBundle()); - return bundle; } diff --git a/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java b/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java index bf5f2756c9..42c391f9c4 100644 --- a/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java +++ b/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java @@ -1031,19 +1031,18 @@ import java.util.List; *

This excludes window uid and period uid that wouldn't be preserved when bundling. */ public PositionInfo createPositionInfoForBundling() { - if (!isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) { - return SessionPositionInfo.DEFAULT_POSITION_INFO; - } + boolean canAccessCurrentMediaItem = isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM); + boolean canAccessTimeline = isCommandAvailable(COMMAND_GET_TIMELINE); return new PositionInfo( /* windowUid= */ null, - getCurrentMediaItemIndex(), - getCurrentMediaItem(), + canAccessTimeline ? getCurrentMediaItemIndex() : 0, + canAccessCurrentMediaItem ? getCurrentMediaItem() : null, /* periodUid= */ null, - getCurrentPeriodIndex(), - getCurrentPosition(), - getContentPosition(), - getCurrentAdGroupIndex(), - getCurrentAdIndexInAdGroup()); + canAccessTimeline ? getCurrentPeriodIndex() : 0, + canAccessCurrentMediaItem ? getCurrentPosition() : 0, + canAccessCurrentMediaItem ? getContentPosition() : 0, + canAccessCurrentMediaItem ? getCurrentAdGroupIndex() : C.INDEX_UNSET, + canAccessCurrentMediaItem ? getCurrentAdIndexInAdGroup() : C.INDEX_UNSET); } /** @@ -1052,20 +1051,18 @@ import java.util.List; *

This excludes window uid and period uid that wouldn't be preserved when bundling. */ public SessionPositionInfo createSessionPositionInfoForBundling() { - if (!isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) { - return SessionPositionInfo.DEFAULT; - } + boolean canAccessCurrentMediaItem = isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM); return new SessionPositionInfo( createPositionInfoForBundling(), - isPlayingAd(), + canAccessCurrentMediaItem && isPlayingAd(), /* eventTimeMs= */ SystemClock.elapsedRealtime(), - getDuration(), - getBufferedPosition(), - getBufferedPercentage(), - getTotalBufferedDuration(), - getCurrentLiveOffset(), - getContentDuration(), - getContentBufferedPosition()); + canAccessCurrentMediaItem ? getDuration() : C.TIME_UNSET, + canAccessCurrentMediaItem ? getBufferedPosition() : 0, + canAccessCurrentMediaItem ? getBufferedPercentage() : 0, + canAccessCurrentMediaItem ? getTotalBufferedDuration() : 0, + canAccessCurrentMediaItem ? getCurrentLiveOffset() : C.TIME_UNSET, + canAccessCurrentMediaItem ? getContentDuration() : C.TIME_UNSET, + canAccessCurrentMediaItem ? getContentBufferedPosition() : 0); } public PlayerInfo createPlayerInfoForBundling() { diff --git a/libraries/session/src/main/java/androidx/media3/session/SessionPositionInfo.java b/libraries/session/src/main/java/androidx/media3/session/SessionPositionInfo.java index f8960d2a87..a4d537f0cc 100644 --- a/libraries/session/src/main/java/androidx/media3/session/SessionPositionInfo.java +++ b/libraries/session/src/main/java/androidx/media3/session/SessionPositionInfo.java @@ -170,17 +170,28 @@ import com.google.common.base.Objects; @Override public Bundle toBundle() { + return toBundle(/* canAccessCurrentMediaItem= */ true, /* canAccessTimeline= */ true); + } + + public Bundle toBundle(boolean canAccessCurrentMediaItem, boolean canAccessTimeline) { Bundle bundle = new Bundle(); - bundle.putBundle(FIELD_POSITION_INFO, positionInfo.toBundle()); - bundle.putBoolean(FIELD_IS_PLAYING_AD, isPlayingAd); + bundle.putBundle( + FIELD_POSITION_INFO, positionInfo.toBundle(canAccessCurrentMediaItem, canAccessTimeline)); + bundle.putBoolean(FIELD_IS_PLAYING_AD, canAccessCurrentMediaItem && isPlayingAd); bundle.putLong(FIELD_EVENT_TIME_MS, eventTimeMs); - bundle.putLong(FIELD_DURATION_MS, durationMs); - bundle.putLong(FIELD_BUFFERED_POSITION_MS, bufferedPositionMs); - bundle.putInt(FIELD_BUFFERED_PERCENTAGE, bufferedPercentage); - bundle.putLong(FIELD_TOTAL_BUFFERED_DURATION_MS, totalBufferedDurationMs); - bundle.putLong(FIELD_CURRENT_LIVE_OFFSET_MS, currentLiveOffsetMs); - bundle.putLong(FIELD_CONTENT_DURATION_MS, contentDurationMs); - bundle.putLong(FIELD_CONTENT_BUFFERED_POSITION_MS, contentBufferedPositionMs); + bundle.putLong(FIELD_DURATION_MS, canAccessCurrentMediaItem ? durationMs : C.TIME_UNSET); + bundle.putLong(FIELD_BUFFERED_POSITION_MS, canAccessCurrentMediaItem ? bufferedPositionMs : 0); + bundle.putInt(FIELD_BUFFERED_PERCENTAGE, canAccessCurrentMediaItem ? bufferedPercentage : 0); + bundle.putLong( + FIELD_TOTAL_BUFFERED_DURATION_MS, canAccessCurrentMediaItem ? totalBufferedDurationMs : 0); + bundle.putLong( + FIELD_CURRENT_LIVE_OFFSET_MS, + canAccessCurrentMediaItem ? currentLiveOffsetMs : C.TIME_UNSET); + bundle.putLong( + FIELD_CONTENT_DURATION_MS, canAccessCurrentMediaItem ? contentDurationMs : C.TIME_UNSET); + bundle.putLong( + FIELD_CONTENT_BUFFERED_POSITION_MS, + canAccessCurrentMediaItem ? contentBufferedPositionMs : 0); return bundle; } @@ -196,8 +207,7 @@ import com.google.common.base.Objects; boolean isPlayingAd = bundle.getBoolean(FIELD_IS_PLAYING_AD, /* defaultValue= */ false); long eventTimeMs = bundle.getLong(FIELD_EVENT_TIME_MS, /* defaultValue= */ C.TIME_UNSET); long durationMs = bundle.getLong(FIELD_DURATION_MS, /* defaultValue= */ C.TIME_UNSET); - long bufferedPositionMs = - bundle.getLong(FIELD_BUFFERED_POSITION_MS, /* defaultValue= */ C.TIME_UNSET); + long bufferedPositionMs = bundle.getLong(FIELD_BUFFERED_POSITION_MS, /* defaultValue= */ 0); int bufferedPercentage = bundle.getInt(FIELD_BUFFERED_PERCENTAGE, /* defaultValue= */ 0); long totalBufferedDurationMs = bundle.getLong(FIELD_TOTAL_BUFFERED_DURATION_MS, /* defaultValue= */ 0); @@ -206,7 +216,7 @@ import com.google.common.base.Objects; long contentDurationMs = bundle.getLong(FIELD_CONTENT_DURATION_MS, /* defaultValue= */ C.TIME_UNSET); long contentBufferedPositionMs = - bundle.getLong(FIELD_CONTENT_BUFFERED_POSITION_MS, /* defaultValue= */ C.TIME_UNSET); + bundle.getLong(FIELD_CONTENT_BUFFERED_POSITION_MS, /* defaultValue= */ 0); return new SessionPositionInfo( positionInfo, diff --git a/libraries/session/src/test/java/androidx/media3/session/PlayerInfoTest.java b/libraries/session/src/test/java/androidx/media3/session/PlayerInfoTest.java index 7e8738f9d9..fdc4e2e4c0 100644 --- a/libraries/session/src/test/java/androidx/media3/session/PlayerInfoTest.java +++ b/libraries/session/src/test/java/androidx/media3/session/PlayerInfoTest.java @@ -15,10 +15,29 @@ */ package androidx.media3.session; +import static androidx.media3.common.MimeTypes.AUDIO_AAC; import static com.google.common.truth.Truth.assertThat; import android.os.Bundle; +import androidx.media3.common.AudioAttributes; +import androidx.media3.common.C; +import androidx.media3.common.DeviceInfo; +import androidx.media3.common.Format; +import androidx.media3.common.MediaItem; +import androidx.media3.common.MediaMetadata; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.PlaybackParameters; +import androidx.media3.common.Player; +import androidx.media3.common.Timeline; +import androidx.media3.common.TrackGroup; +import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; +import androidx.media3.common.VideoSize; +import androidx.media3.common.text.CueGroup; +import androidx.media3.test.utils.FakeTimeline; +import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.collect.ImmutableList; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,4 +69,485 @@ public class PlayerInfoTest { assertThat(resultingBundlingExclusions).isEqualTo(bundlingExclusions); } + + @Test + public void toBundleFromBundle_withAllCommands_restoresAllData() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setOldPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 5, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id1").build(), + /* periodUid= */ null, + /* periodIndex= */ 4, + /* positionMs= */ 4000, + /* contentPositionMs= */ 5000, + /* adGroupIndex= */ 3, + /* adIndexInAdGroup= */ 2)) + .setNewPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 6, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id2").build(), + /* periodUid= */ null, + /* periodIndex= */ 7, + /* positionMs= */ 8000, + /* contentPositionMs= */ 9000, + /* adGroupIndex= */ 5, + /* adIndexInAdGroup= */ 1)) + .setSessionPositionInfo( + new SessionPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 8, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id3").build(), + /* periodUid= */ null, + /* periodIndex= */ 9, + /* positionMs= */ 2000, + /* contentPositionMs= */ 7000, + /* adGroupIndex= */ 9, + /* adIndexInAdGroup= */ 1), + /* isPlayingAd= */ true, + /* eventTimeMs= */ 123456789, + /* durationMs= */ 30000, + /* bufferedPositionMs= */ 20000, + /* bufferedPercentage= */ 50, + /* totalBufferedDurationMs= */ 25000, + /* currentLiveOffsetMs= */ 3000, + /* contentDurationMs= */ 27000, + /* contentBufferedPositionMs= */ 15000)) + .setTimeline(new FakeTimeline(/* windowCount= */ 10)) + .setMediaMetadata(new MediaMetadata.Builder().setTitle("title").build()) + .setPlaylistMetadata(new MediaMetadata.Builder().setArtist("artist").build()) + .setVolume(0.5f) + .setDeviceVolume(10) + .setDeviceMuted(true) + .setAudioAttributes( + new AudioAttributes.Builder().setContentType(C.AUDIO_CONTENT_TYPE_SPEECH).build()) + .setCues(new CueGroup(/* cues= */ ImmutableList.of(), /* presentationTimeUs= */ 1234)) + .setCurrentTracks( + new Tracks( + ImmutableList.of( + new Tracks.Group( + new TrackGroup( + new Format.Builder().setSampleMimeType(AUDIO_AAC).build()), + /* adaptiveSupported= */ false, + new int[] {C.FORMAT_EXCEEDS_CAPABILITIES}, + /* trackSelected= */ new boolean[] {true})))) + .setDeviceInfo( + new DeviceInfo( + DeviceInfo.PLAYBACK_TYPE_REMOTE, /* minVolume= */ 4, /* maxVolume= */ 10)) + .setDiscontinuityReason(Player.DISCONTINUITY_REASON_REMOVE) + .setIsLoading(true) + .setIsPlaying(true) + .setMaxSeekToPreviousPositionMs(5000) + .setMediaItemTransitionReason(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) + .setPlaybackParameters(new PlaybackParameters(2f)) + .setPlaybackState(Player.STATE_BUFFERING) + .setPlaybackSuppressionReason( + Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS) + .setPlayerError( + new PlaybackException( + /* message= */ null, /* cause= */ null, PlaybackException.ERROR_CODE_TIMEOUT)) + .setPlayWhenReady(true) + .setPlayWhenReadyChangedReason(Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) + .setRepeatMode(Player.REPEAT_MODE_ONE) + .setSeekBackIncrement(7000) + .setSeekForwardIncrement(6000) + .setShuffleModeEnabled(true) + .setTrackSelectionParameters( + new TrackSelectionParameters.Builder(ApplicationProvider.getApplicationContext()) + .setMaxAudioBitrate(5000) + .build()) + .setVideoSize(new VideoSize(/* width= */ 1024, /* height= */ 768)) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder().addAllCommands().build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.oldPositionInfo.mediaItemIndex).isEqualTo(5); + assertThat(infoAfterBundling.oldPositionInfo.periodIndex).isEqualTo(4); + assertThat(infoAfterBundling.oldPositionInfo.mediaItem.mediaId).isEqualTo("id1"); + assertThat(infoAfterBundling.oldPositionInfo.positionMs).isEqualTo(4000); + assertThat(infoAfterBundling.oldPositionInfo.contentPositionMs).isEqualTo(5000); + assertThat(infoAfterBundling.oldPositionInfo.adGroupIndex).isEqualTo(3); + assertThat(infoAfterBundling.oldPositionInfo.adIndexInAdGroup).isEqualTo(2); + assertThat(infoAfterBundling.newPositionInfo.mediaItemIndex).isEqualTo(6); + assertThat(infoAfterBundling.newPositionInfo.periodIndex).isEqualTo(7); + assertThat(infoAfterBundling.newPositionInfo.mediaItem.mediaId).isEqualTo("id2"); + assertThat(infoAfterBundling.newPositionInfo.positionMs).isEqualTo(8000); + assertThat(infoAfterBundling.newPositionInfo.contentPositionMs).isEqualTo(9000); + assertThat(infoAfterBundling.newPositionInfo.adGroupIndex).isEqualTo(5); + assertThat(infoAfterBundling.newPositionInfo.adIndexInAdGroup).isEqualTo(1); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.mediaItemIndex).isEqualTo(8); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.periodIndex).isEqualTo(9); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.mediaItem.mediaId) + .isEqualTo("id3"); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.positionMs).isEqualTo(2000); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.contentPositionMs) + .isEqualTo(7000); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.adGroupIndex).isEqualTo(9); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.adIndexInAdGroup).isEqualTo(1); + assertThat(infoAfterBundling.sessionPositionInfo.isPlayingAd).isTrue(); + assertThat(infoAfterBundling.sessionPositionInfo.eventTimeMs).isEqualTo(123456789); + assertThat(infoAfterBundling.sessionPositionInfo.durationMs).isEqualTo(30000); + assertThat(infoAfterBundling.sessionPositionInfo.bufferedPositionMs).isEqualTo(20000); + assertThat(infoAfterBundling.sessionPositionInfo.bufferedPercentage).isEqualTo(50); + assertThat(infoAfterBundling.sessionPositionInfo.totalBufferedDurationMs).isEqualTo(25000); + assertThat(infoAfterBundling.sessionPositionInfo.currentLiveOffsetMs).isEqualTo(3000); + assertThat(infoAfterBundling.sessionPositionInfo.contentDurationMs).isEqualTo(27000); + assertThat(infoAfterBundling.sessionPositionInfo.contentBufferedPositionMs).isEqualTo(15000); + assertThat(infoAfterBundling.timeline.getWindowCount()).isEqualTo(10); + assertThat(infoAfterBundling.mediaMetadata.title).isEqualTo("title"); + assertThat(infoAfterBundling.playlistMetadata.artist).isEqualTo("artist"); + assertThat(infoAfterBundling.volume).isEqualTo(0.5f); + assertThat(infoAfterBundling.deviceVolume).isEqualTo(10); + assertThat(infoAfterBundling.deviceMuted).isTrue(); + assertThat(infoAfterBundling.audioAttributes.contentType) + .isEqualTo(C.AUDIO_CONTENT_TYPE_SPEECH); + assertThat(infoAfterBundling.cueGroup.presentationTimeUs).isEqualTo(1234); + assertThat(infoAfterBundling.currentTracks.getGroups()).hasSize(1); + assertThat(infoAfterBundling.deviceInfo.maxVolume).isEqualTo(10); + assertThat(infoAfterBundling.discontinuityReason).isEqualTo(Player.DISCONTINUITY_REASON_REMOVE); + assertThat(infoAfterBundling.isLoading).isTrue(); + assertThat(infoAfterBundling.isPlaying).isTrue(); + assertThat(infoAfterBundling.maxSeekToPreviousPositionMs).isEqualTo(5000); + assertThat(infoAfterBundling.mediaItemTransitionReason) + .isEqualTo(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED); + assertThat(infoAfterBundling.playbackParameters.speed).isEqualTo(2f); + assertThat(infoAfterBundling.playbackState).isEqualTo(Player.STATE_BUFFERING); + assertThat(infoAfterBundling.playbackSuppressionReason) + .isEqualTo(Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS); + assertThat(infoAfterBundling.playerError.errorCode) + .isEqualTo(PlaybackException.ERROR_CODE_TIMEOUT); + assertThat(infoAfterBundling.playWhenReady).isTrue(); + assertThat(infoAfterBundling.playWhenReadyChangedReason) + .isEqualTo(Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST); + assertThat(infoAfterBundling.repeatMode).isEqualTo(Player.REPEAT_MODE_ONE); + assertThat(infoAfterBundling.seekBackIncrementMs).isEqualTo(7000); + assertThat(infoAfterBundling.seekForwardIncrementMs).isEqualTo(6000); + assertThat(infoAfterBundling.shuffleModeEnabled).isTrue(); + assertThat(infoAfterBundling.trackSelectionParameters.maxAudioBitrate).isEqualTo(5000); + assertThat(infoAfterBundling.videoSize.width).isEqualTo(1024); + } + + @Test + public void toBundleFromBundle_withoutCommandGetCurrentMediaItem_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setOldPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 5, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id1").build(), + /* periodUid= */ null, + /* periodIndex= */ 4, + /* positionMs= */ 4000, + /* contentPositionMs= */ 5000, + /* adGroupIndex= */ 3, + /* adIndexInAdGroup= */ 2)) + .setNewPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 6, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id2").build(), + /* periodUid= */ null, + /* periodIndex= */ 7, + /* positionMs= */ 8000, + /* contentPositionMs= */ 9000, + /* adGroupIndex= */ 5, + /* adIndexInAdGroup= */ 1)) + .setSessionPositionInfo( + new SessionPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 8, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id3").build(), + /* periodUid= */ null, + /* periodIndex= */ 9, + /* positionMs= */ 2000, + /* contentPositionMs= */ 7000, + /* adGroupIndex= */ 9, + /* adIndexInAdGroup= */ 1), + /* isPlayingAd= */ true, + /* eventTimeMs= */ 123456789, + /* durationMs= */ 30000, + /* bufferedPositionMs= */ 20000, + /* bufferedPercentage= */ 50, + /* totalBufferedDurationMs= */ 25000, + /* currentLiveOffsetMs= */ 3000, + /* contentDurationMs= */ 25000, + /* contentBufferedPositionMs= */ 15000)) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_CURRENT_MEDIA_ITEM) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.oldPositionInfo.mediaItemIndex).isEqualTo(5); + assertThat(infoAfterBundling.oldPositionInfo.periodIndex).isEqualTo(4); + assertThat(infoAfterBundling.oldPositionInfo.mediaItem).isEqualTo(null); + assertThat(infoAfterBundling.oldPositionInfo.positionMs).isEqualTo(0); + assertThat(infoAfterBundling.oldPositionInfo.contentPositionMs).isEqualTo(0); + assertThat(infoAfterBundling.oldPositionInfo.adGroupIndex).isEqualTo(C.INDEX_UNSET); + assertThat(infoAfterBundling.oldPositionInfo.adIndexInAdGroup).isEqualTo(C.INDEX_UNSET); + assertThat(infoAfterBundling.newPositionInfo.mediaItemIndex).isEqualTo(6); + assertThat(infoAfterBundling.newPositionInfo.periodIndex).isEqualTo(7); + assertThat(infoAfterBundling.newPositionInfo.mediaItem).isEqualTo(null); + assertThat(infoAfterBundling.newPositionInfo.positionMs).isEqualTo(0); + assertThat(infoAfterBundling.newPositionInfo.contentPositionMs).isEqualTo(0); + assertThat(infoAfterBundling.newPositionInfo.adGroupIndex).isEqualTo(C.INDEX_UNSET); + assertThat(infoAfterBundling.newPositionInfo.adIndexInAdGroup).isEqualTo(C.INDEX_UNSET); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.mediaItemIndex).isEqualTo(8); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.periodIndex).isEqualTo(9); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.mediaItem).isEqualTo(null); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.positionMs).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.contentPositionMs).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.adGroupIndex) + .isEqualTo(C.INDEX_UNSET); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.adIndexInAdGroup) + .isEqualTo(C.INDEX_UNSET); + assertThat(infoAfterBundling.sessionPositionInfo.isPlayingAd).isFalse(); + assertThat(infoAfterBundling.sessionPositionInfo.eventTimeMs).isEqualTo(123456789); + assertThat(infoAfterBundling.sessionPositionInfo.durationMs).isEqualTo(C.TIME_UNSET); + assertThat(infoAfterBundling.sessionPositionInfo.bufferedPositionMs).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.bufferedPercentage).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.totalBufferedDurationMs).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.currentLiveOffsetMs).isEqualTo(C.TIME_UNSET); + assertThat(infoAfterBundling.sessionPositionInfo.contentDurationMs).isEqualTo(C.TIME_UNSET); + assertThat(infoAfterBundling.sessionPositionInfo.contentBufferedPositionMs).isEqualTo(0); + } + + @Test + public void toBundleFromBundle_withoutCommandGetTimeline_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setOldPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 5, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id1").build(), + /* periodUid= */ null, + /* periodIndex= */ 4, + /* positionMs= */ 4000, + /* contentPositionMs= */ 5000, + /* adGroupIndex= */ 3, + /* adIndexInAdGroup= */ 2)) + .setNewPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 6, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id2").build(), + /* periodUid= */ null, + /* periodIndex= */ 7, + /* positionMs= */ 8000, + /* contentPositionMs= */ 9000, + /* adGroupIndex= */ 5, + /* adIndexInAdGroup= */ 1)) + .setSessionPositionInfo( + new SessionPositionInfo( + new Player.PositionInfo( + /* windowUid= */ null, + /* mediaItemIndex= */ 8, + /* mediaItem= */ new MediaItem.Builder().setMediaId("id3").build(), + /* periodUid= */ null, + /* periodIndex= */ 9, + /* positionMs= */ 2000, + /* contentPositionMs= */ 7000, + /* adGroupIndex= */ 9, + /* adIndexInAdGroup= */ 1), + /* isPlayingAd= */ true, + /* eventTimeMs= */ 123456789, + /* durationMs= */ 30000, + /* bufferedPositionMs= */ 20000, + /* bufferedPercentage= */ 50, + /* totalBufferedDurationMs= */ 25000, + /* currentLiveOffsetMs= */ 3000, + /* contentDurationMs= */ 27000, + /* contentBufferedPositionMs= */ 15000)) + .setTimeline(new FakeTimeline(/* windowCount= */ 10)) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_TIMELINE) + .build(), + /* excludeTimeline= */ true, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.oldPositionInfo.mediaItemIndex).isEqualTo(0); + assertThat(infoAfterBundling.oldPositionInfo.periodIndex).isEqualTo(0); + assertThat(infoAfterBundling.oldPositionInfo.mediaItem.mediaId).isEqualTo("id1"); + assertThat(infoAfterBundling.oldPositionInfo.positionMs).isEqualTo(4000); + assertThat(infoAfterBundling.oldPositionInfo.contentPositionMs).isEqualTo(5000); + assertThat(infoAfterBundling.oldPositionInfo.adGroupIndex).isEqualTo(3); + assertThat(infoAfterBundling.oldPositionInfo.adIndexInAdGroup).isEqualTo(2); + assertThat(infoAfterBundling.newPositionInfo.mediaItemIndex).isEqualTo(0); + assertThat(infoAfterBundling.newPositionInfo.periodIndex).isEqualTo(0); + assertThat(infoAfterBundling.newPositionInfo.mediaItem.mediaId).isEqualTo("id2"); + assertThat(infoAfterBundling.newPositionInfo.positionMs).isEqualTo(8000); + assertThat(infoAfterBundling.newPositionInfo.contentPositionMs).isEqualTo(9000); + assertThat(infoAfterBundling.newPositionInfo.adGroupIndex).isEqualTo(5); + assertThat(infoAfterBundling.newPositionInfo.adIndexInAdGroup).isEqualTo(1); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.mediaItemIndex).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.periodIndex).isEqualTo(0); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.mediaItem.mediaId) + .isEqualTo("id3"); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.positionMs).isEqualTo(2000); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.contentPositionMs) + .isEqualTo(7000); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.adGroupIndex).isEqualTo(9); + assertThat(infoAfterBundling.sessionPositionInfo.positionInfo.adIndexInAdGroup).isEqualTo(1); + assertThat(infoAfterBundling.sessionPositionInfo.isPlayingAd).isTrue(); + assertThat(infoAfterBundling.sessionPositionInfo.eventTimeMs).isEqualTo(123456789); + assertThat(infoAfterBundling.sessionPositionInfo.durationMs).isEqualTo(30000); + assertThat(infoAfterBundling.sessionPositionInfo.bufferedPositionMs).isEqualTo(20000); + assertThat(infoAfterBundling.sessionPositionInfo.bufferedPercentage).isEqualTo(50); + assertThat(infoAfterBundling.sessionPositionInfo.totalBufferedDurationMs).isEqualTo(25000); + assertThat(infoAfterBundling.sessionPositionInfo.currentLiveOffsetMs).isEqualTo(3000); + assertThat(infoAfterBundling.sessionPositionInfo.contentDurationMs).isEqualTo(27000); + assertThat(infoAfterBundling.sessionPositionInfo.contentBufferedPositionMs).isEqualTo(15000); + assertThat(infoAfterBundling.timeline).isEqualTo(Timeline.EMPTY); + } + + @Test + public void toBundleFromBundle_withoutCommandGetMediaItemsMetadata_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setMediaMetadata(new MediaMetadata.Builder().setTitle("title").build()) + .setPlaylistMetadata(new MediaMetadata.Builder().setArtist("artist").build()) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_MEDIA_ITEMS_METADATA) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.mediaMetadata).isEqualTo(MediaMetadata.EMPTY); + assertThat(infoAfterBundling.playlistMetadata).isEqualTo(MediaMetadata.EMPTY); + } + + @Test + public void toBundleFromBundle_withoutCommandGetVolume_filtersInformation() { + PlayerInfo playerInfo = new PlayerInfo.Builder(PlayerInfo.DEFAULT).setVolume(0.5f).build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_VOLUME) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.volume).isEqualTo(1f); + } + + @Test + public void toBundleFromBundle_withoutCommandGetDeviceVolume_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT).setDeviceVolume(10).setDeviceMuted(true).build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_DEVICE_VOLUME) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.deviceVolume).isEqualTo(0); + assertThat(infoAfterBundling.deviceMuted).isFalse(); + } + + @Test + public void toBundleFromBundle_withoutCommandGetAudioAttributes_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setAudioAttributes( + new AudioAttributes.Builder().setContentType(C.AUDIO_CONTENT_TYPE_SPEECH).build()) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_AUDIO_ATTRIBUTES) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.audioAttributes).isEqualTo(AudioAttributes.DEFAULT); + } + + @Test + public void toBundleFromBundle_withoutCommandGetText_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setCues(new CueGroup(/* cues= */ ImmutableList.of(), /* presentationTimeUs= */ 1234)) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_TEXT) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ false)); + + assertThat(infoAfterBundling.cueGroup).isEqualTo(CueGroup.EMPTY_TIME_ZERO); + } + + @Test + public void toBundleFromBundle_withoutCommandGetTracks_filtersInformation() { + PlayerInfo playerInfo = + new PlayerInfo.Builder(PlayerInfo.DEFAULT) + .setCurrentTracks( + new Tracks( + ImmutableList.of( + new Tracks.Group( + new TrackGroup( + new Format.Builder().setSampleMimeType(AUDIO_AAC).build()), + /* adaptiveSupported= */ false, + new int[] {C.FORMAT_EXCEEDS_CAPABILITIES}, + /* trackSelected= */ new boolean[] {true})))) + .build(); + + PlayerInfo infoAfterBundling = + PlayerInfo.CREATOR.fromBundle( + playerInfo.toBundle( + new Player.Commands.Builder() + .addAllCommands() + .remove(Player.COMMAND_GET_TRACKS) + .build(), + /* excludeTimeline= */ false, + /* excludeTracks= */ true)); + + assertThat(infoAfterBundling.currentTracks).isEqualTo(Tracks.EMPTY); + } }