From 69cfba7c53b563577390e4074fd270f078bf6069 Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 18 Jan 2023 13:49:01 +0000 Subject: [PATCH] Correctly filter PlayerInfo by available getter commands. When bundling PlayerInfo, we need to remove information if the controller is not allowed to access it. This was only partially done at the moment. PiperOrigin-RevId: 502852798 --- .../java/androidx/media3/common/Player.java | 44 +- .../androidx/media3/session/MediaSession.java | 6 +- .../media3/session/MediaSessionImpl.java | 35 +- .../session/MediaSessionLegacyStub.java | 6 +- .../media3/session/MediaSessionStub.java | 9 +- .../androidx/media3/session/PlayerInfo.java | 34 +- .../media3/session/PlayerWrapper.java | 39 +- .../media3/session/SessionPositionInfo.java | 34 +- .../media3/session/PlayerInfoTest.java | 500 ++++++++++++++++++ 9 files changed, 646 insertions(+), 61 deletions(-) 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); + } }