Cleaner unified PlayerInfo update method in MediaControllerImplBase

`MediaControllerImplBase` has 2 methods for updating listeners about `PlayerInfo` changes - `updatePlayerInfo` (for masking the state) and `onPlayerInfoChanged` (when communicating with the session). There is a set number of listener callbacks related to `PlayerInfo` updates and both methods should go through the same control flow (whether we know that masking will ignore most of them or not).

A unified method `notifyPlayerInfoListenersWithReasons` encapsulates only the shared logic of 2 methods - listeners' callbacks. This ensures that both methods call them in the same order and none are missed out.

PiperOrigin-RevId: 542587879
This commit is contained in:
jbibik 2023-06-22 16:49:36 +00:00 committed by Tofunmi Adigun-Hameed
parent ca766b6979
commit c2d8051662
8 changed files with 263 additions and 233 deletions

View File

@ -428,12 +428,10 @@ import org.checkerframework.checker.nullness.qual.NonNull;
updatePlayerInfo(
newPlayerInfo,
/* ignored */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
/* positionDiscontinuity= */ false,
/* ignored */ Player.DISCONTINUITY_REASON_INTERNAL,
/* mediaItemTransition= */ false,
/* ignored */ Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT);
/* timelineChangeReason= */ null,
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ null,
/* mediaItemTransitionReason= */ null);
}
}
@ -949,14 +947,16 @@ import org.checkerframework.checker.nullness.qual.NonNull;
// Add media items to the end of the timeline if the index exceeds the window count.
index = min(index, playerInfo.timeline.getWindowCount());
PlayerInfo newPlayerInfo = maskPlaybackInfoForAddedItems(playerInfo, index, mediaItems);
@Nullable
@Player.MediaItemTransitionReason
Integer mediaItemTransitionReason =
playerInfo.timeline.isEmpty() ? Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED : null;
updatePlayerInfo(
newPlayerInfo,
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
/* positionDiscontinuity= */ false,
/* ignored */ Player.DISCONTINUITY_REASON_INTERNAL,
/* mediaItemTransition= */ playerInfo.timeline.isEmpty(),
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ null,
/* mediaItemTransitionReason= */ mediaItemTransitionReason);
}
private static PlayerInfo maskPlaybackInfoForAddedItems(
@ -1040,19 +1040,22 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (fromIndex >= playlistSize || fromIndex == toIndex || playlistSize == 0) {
return;
}
boolean currentItemRemoved =
boolean wasCurrentItemRemoved =
getCurrentMediaItemIndex() >= fromIndex && getCurrentMediaItemIndex() < toIndex;
PlayerInfo newPlayerInfo = maskPlayerInfoForRemovedItems(playerInfo, fromIndex, toIndex);
boolean didMediaItemTransitionHappen =
playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex >= fromIndex
&& playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex < toIndex;
updatePlayerInfo(
newPlayerInfo,
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
/* positionDiscontinuity= */ currentItemRemoved,
Player.DISCONTINUITY_REASON_REMOVE,
/* mediaItemTransition= */ playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex
>= fromIndex
&& playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex < toIndex,
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ wasCurrentItemRemoved
? Player.DISCONTINUITY_REASON_REMOVE
: null,
/* mediaItemTransitionReason= */ didMediaItemTransitionHappen
? Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
: null);
}
private static PlayerInfo maskPlayerInfoForRemovedItems(
@ -1265,17 +1268,19 @@ import org.checkerframework.checker.nullness.qual.NonNull;
toIndex = min(toIndex, playlistSize);
PlayerInfo newPlayerInfo = maskPlaybackInfoForAddedItems(playerInfo, toIndex, mediaItems);
newPlayerInfo = maskPlayerInfoForRemovedItems(newPlayerInfo, fromIndex, toIndex);
boolean replacedCurrentItem =
boolean wasCurrentItemReplaced =
playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex >= fromIndex
&& playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex < toIndex;
updatePlayerInfo(
newPlayerInfo,
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
/* positionDiscontinuity= */ replacedCurrentItem,
Player.DISCONTINUITY_REASON_REMOVE,
/* mediaItemTransition= */ replacedCurrentItem,
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ wasCurrentItemReplaced
? Player.DISCONTINUITY_REASON_REMOVE
: null,
/* mediaItemTransitionReason= */ wasCurrentItemReplaced
? Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
: null);
}
@Override
@ -1996,12 +2001,14 @@ import org.checkerframework.checker.nullness.qual.NonNull;
updatePlayerInfo(
newPlayerInfo,
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
/* positionDiscontinuity= */ !playerInfo.timeline.isEmpty(),
Player.DISCONTINUITY_REASON_REMOVE,
/* mediaItemTransition= */ !playerInfo.timeline.isEmpty()
|| !newPlayerInfo.timeline.isEmpty(),
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ !playerInfo.timeline.isEmpty()
? Player.DISCONTINUITY_REASON_REMOVE
: null,
/* mediaItemTransitionReason= */ !playerInfo.timeline.isEmpty()
|| !newPlayerInfo.timeline.isEmpty()
? Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
: null);
}
private void moveMediaItemsInternal(int fromIndex, int toIndex, int newIndex) {
@ -2056,11 +2063,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
updatePlayerInfo(
newPlayerInfo,
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
/* positionDiscontinuity= */ false,
/* ignored */ Player.DISCONTINUITY_REASON_INTERNAL,
/* mediaItemTransition= */ false,
/* ignored */ Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT);
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ null,
/* mediaItemTransitionReason= */ null);
}
}
@ -2132,12 +2137,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
updatePlayerInfo(
newPlayerInfo,
/* ignored */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
positionDiscontinuity,
/* timelineChangeReason= */ null,
/* playWhenReadyChangeReason= */ null,
/* positionDiscontinuityReason= */ Player.DISCONTINUITY_REASON_SEEK,
mediaItemTransition,
Player.MEDIA_ITEM_TRANSITION_REASON_SEEK);
/* mediaItemTransitionReason= */ mediaItemTransition
? Player.MEDIA_ITEM_TRANSITION_REASON_SEEK
: null);
}
private void setPlayWhenReady(
@ -2157,33 +2162,47 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playWhenReady, playWhenReadyChangeReason, playbackSuppressionReason);
updatePlayerInfo(
newPlayerInfo,
/* ignored */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
/* timelineChangeReason= */ null,
playWhenReadyChangeReason,
/* positionDiscontinuity= */ false,
/* ignored */ Player.DISCONTINUITY_REASON_INTERNAL,
/* mediaItemTransition= */ false,
/* ignored */ Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT);
/* positionDiscontinuityReason= */ null,
/* mediaItemTransitionReason= */ null);
}
private void updatePlayerInfo(
PlayerInfo newPlayerInfo,
@Player.TimelineChangeReason int timelineChangeReason,
@Player.PlayWhenReadyChangeReason int playWhenReadyChangeReason,
boolean positionDiscontinuity,
@Player.DiscontinuityReason int positionDiscontinuityReason,
boolean mediaItemTransition,
@Player.MediaItemTransitionReason int mediaItemTransitionReason) {
@Nullable @Player.TimelineChangeReason Integer timelineChangeReason,
@Nullable @Player.PlayWhenReadyChangeReason Integer playWhenReadyChangeReason,
@Nullable @Player.DiscontinuityReason Integer positionDiscontinuityReason,
@Nullable @Player.MediaItemTransitionReason Integer mediaItemTransitionReason) {
// Assign player info immediately such that all getters return the right values, but keep
// snapshot of previous and new states so that listener invocations are triggered correctly.
PlayerInfo oldPlayerInfo = this.playerInfo;
this.playerInfo = newPlayerInfo;
if (!oldPlayerInfo.timeline.equals(newPlayerInfo.timeline)) {
notifyPlayerInfoListenersWithReasons(
oldPlayerInfo,
newPlayerInfo,
timelineChangeReason,
playWhenReadyChangeReason,
positionDiscontinuityReason,
mediaItemTransitionReason);
}
@SuppressWarnings("deprecation") // Implementing and calling deprecated listener methods.
private void notifyPlayerInfoListenersWithReasons(
PlayerInfo oldPlayerInfo,
PlayerInfo newPlayerInfo,
@Nullable @Player.TimelineChangeReason Integer timelineChangeReason,
@Nullable @Player.PlayWhenReadyChangeReason Integer playWhenReadyChangeReason,
@Nullable @Player.DiscontinuityReason Integer positionDiscontinuityReason,
@Nullable @Player.MediaItemTransitionReason Integer mediaItemTransitionReason) {
if (timelineChangeReason != null) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TIMELINE_CHANGED,
listener -> listener.onTimelineChanged(newPlayerInfo.timeline, timelineChangeReason));
}
if (positionDiscontinuity) {
if (positionDiscontinuityReason != null) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_POSITION_DISCONTINUITY,
listener ->
@ -2192,12 +2211,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
newPlayerInfo.newPositionInfo,
positionDiscontinuityReason));
}
if (mediaItemTransition) {
MediaItem currentMediaItem = newPlayerInfo.getCurrentMediaItem();
if (mediaItemTransitionReason != null) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_MEDIA_ITEM_TRANSITION,
listener ->
listener.onMediaItemTransition(
newPlayerInfo.getCurrentMediaItem(), mediaItemTransitionReason));
listener -> listener.onMediaItemTransition(currentMediaItem, mediaItemTransitionReason));
}
PlaybackException oldPlayerError = oldPlayerInfo.playerError;
PlaybackException newPlayerError = newPlayerInfo.playerError;
@ -2214,12 +2232,27 @@ import org.checkerframework.checker.nullness.qual.NonNull;
listener -> listener.onPlayerError(newPlayerError));
}
}
if (!oldPlayerInfo.currentTracks.equals(newPlayerInfo.currentTracks)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksChanged(newPlayerInfo.currentTracks));
}
if (!oldPlayerInfo.mediaMetadata.equals(newPlayerInfo.mediaMetadata)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_MEDIA_METADATA_CHANGED,
listener -> listener.onMediaMetadataChanged(newPlayerInfo.mediaMetadata));
}
if (oldPlayerInfo.isLoading != newPlayerInfo.isLoading) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_IS_LOADING_CHANGED,
listener -> listener.onIsLoadingChanged(newPlayerInfo.isLoading));
}
if (oldPlayerInfo.playbackState != newPlayerInfo.playbackState) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYBACK_STATE_CHANGED,
listener -> listener.onPlaybackStateChanged(newPlayerInfo.playbackState));
}
if (oldPlayerInfo.playWhenReady != newPlayerInfo.playWhenReady) {
if (playWhenReadyChangeReason != null) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAY_WHEN_READY_CHANGED,
listener ->
@ -2237,6 +2270,85 @@ import org.checkerframework.checker.nullness.qual.NonNull;
/* eventFlag= */ Player.EVENT_IS_PLAYING_CHANGED,
listener -> listener.onIsPlayingChanged(newPlayerInfo.isPlaying));
}
if (!oldPlayerInfo.playbackParameters.equals(newPlayerInfo.playbackParameters)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
listener -> listener.onPlaybackParametersChanged(newPlayerInfo.playbackParameters));
}
if (oldPlayerInfo.repeatMode != newPlayerInfo.repeatMode) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_REPEAT_MODE_CHANGED,
listener -> listener.onRepeatModeChanged(newPlayerInfo.repeatMode));
}
if (oldPlayerInfo.shuffleModeEnabled != newPlayerInfo.shuffleModeEnabled) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
listener -> listener.onShuffleModeEnabledChanged(newPlayerInfo.shuffleModeEnabled));
}
if (!oldPlayerInfo.playlistMetadata.equals(newPlayerInfo.playlistMetadata)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYLIST_METADATA_CHANGED,
listener -> listener.onPlaylistMetadataChanged(newPlayerInfo.playlistMetadata));
}
if (oldPlayerInfo.volume != newPlayerInfo.volume) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_VOLUME_CHANGED,
listener -> listener.onVolumeChanged(newPlayerInfo.volume));
}
if (!oldPlayerInfo.audioAttributes.equals(newPlayerInfo.audioAttributes)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_AUDIO_ATTRIBUTES_CHANGED,
listener -> listener.onAudioAttributesChanged(newPlayerInfo.audioAttributes));
}
if (!oldPlayerInfo.cueGroup.cues.equals(newPlayerInfo.cueGroup.cues)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_CUES,
listener -> listener.onCues(newPlayerInfo.cueGroup.cues));
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_CUES, listener -> listener.onCues(newPlayerInfo.cueGroup));
}
if (!oldPlayerInfo.deviceInfo.equals(newPlayerInfo.deviceInfo)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_INFO_CHANGED,
listener -> listener.onDeviceInfoChanged(newPlayerInfo.deviceInfo));
}
if (oldPlayerInfo.deviceVolume != newPlayerInfo.deviceVolume
|| oldPlayerInfo.deviceMuted != newPlayerInfo.deviceMuted) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener ->
listener.onDeviceVolumeChanged(
newPlayerInfo.deviceVolume, newPlayerInfo.deviceMuted));
}
if (!oldPlayerInfo.videoSize.equals(newPlayerInfo.videoSize)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_VIDEO_SIZE_CHANGED,
listener -> listener.onVideoSizeChanged(newPlayerInfo.videoSize));
}
if (oldPlayerInfo.seekBackIncrementMs != newPlayerInfo.seekBackIncrementMs) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_SEEK_BACK_INCREMENT_CHANGED,
listener -> listener.onSeekBackIncrementChanged(newPlayerInfo.seekBackIncrementMs));
}
if (oldPlayerInfo.seekForwardIncrementMs != newPlayerInfo.seekForwardIncrementMs) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
listener -> listener.onSeekForwardIncrementChanged(newPlayerInfo.seekForwardIncrementMs));
}
if (oldPlayerInfo.maxSeekToPreviousPositionMs != newPlayerInfo.maxSeekToPreviousPositionMs) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED,
listener ->
listener.onMaxSeekToPreviousPositionChanged(
newPlayerInfo.maxSeekToPreviousPositionMs));
}
if (!oldPlayerInfo.trackSelectionParameters.equals(newPlayerInfo.trackSelectionParameters)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
listener ->
listener.onTrackSelectionParametersChanged(newPlayerInfo.trackSelectionParameters));
}
listeners.flushEvents();
}
@ -2431,7 +2543,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
});
}
@SuppressWarnings("deprecation") // Implementing and calling deprecated listener method.
void onPlayerInfoChanged(PlayerInfo newPlayerInfo, BundlingExclusions bundlingExclusions) {
if (!isConnected()) {
return;
@ -2467,168 +2578,43 @@ import org.checkerframework.checker.nullness.qual.NonNull;
intersectedPlayerCommands)
.first;
PlayerInfo finalPlayerInfo = playerInfo;
if (!oldPlayerInfo.timeline.equals(finalPlayerInfo.timeline)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TIMELINE_CHANGED,
listener ->
listener.onTimelineChanged(
finalPlayerInfo.timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
}
if (!oldPlayerInfo.oldPositionInfo.equals(finalPlayerInfo.oldPositionInfo)
|| !oldPlayerInfo.newPositionInfo.equals(finalPlayerInfo.newPositionInfo)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_POSITION_DISCONTINUITY,
listener ->
listener.onPositionDiscontinuity(
finalPlayerInfo.oldPositionInfo,
finalPlayerInfo.newPositionInfo,
finalPlayerInfo.discontinuityReason));
}
MediaItem oldCurrentMediaItem = oldPlayerInfo.getCurrentMediaItem();
MediaItem currentMediaItem = finalPlayerInfo.getCurrentMediaItem();
if (!Util.areEqual(oldCurrentMediaItem, currentMediaItem)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_MEDIA_ITEM_TRANSITION,
listener ->
listener.onMediaItemTransition(
currentMediaItem, finalPlayerInfo.mediaItemTransitionReason));
}
PlaybackException oldPlayerError = oldPlayerInfo.playerError;
PlaybackException playerError = finalPlayerInfo.playerError;
boolean errorsMatch =
oldPlayerError == playerError
|| (oldPlayerError != null && oldPlayerError.errorInfoEquals(playerError));
if (!errorsMatch) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerErrorChanged(finalPlayerInfo.playerError));
if (finalPlayerInfo.playerError != null) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerError(finalPlayerInfo.playerError));
}
}
if (!Util.areEqual(oldPlayerInfo.currentTracks, finalPlayerInfo.currentTracks)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksChanged(finalPlayerInfo.currentTracks));
}
if (!oldPlayerInfo.mediaMetadata.equals(finalPlayerInfo.mediaMetadata)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_MEDIA_METADATA_CHANGED,
listener -> listener.onMediaMetadataChanged(finalPlayerInfo.mediaMetadata));
}
if (oldPlayerInfo.isLoading != finalPlayerInfo.isLoading) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_IS_LOADING_CHANGED,
listener -> listener.onIsLoadingChanged(finalPlayerInfo.isLoading));
}
if (oldPlayerInfo.playbackState != finalPlayerInfo.playbackState) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYBACK_STATE_CHANGED,
listener -> listener.onPlaybackStateChanged(finalPlayerInfo.playbackState));
}
if (oldPlayerInfo.playWhenReady != finalPlayerInfo.playWhenReady) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAY_WHEN_READY_CHANGED,
listener ->
listener.onPlayWhenReadyChanged(
finalPlayerInfo.playWhenReady, finalPlayerInfo.playWhenReadyChangeReason));
}
if (oldPlayerInfo.playbackSuppressionReason != finalPlayerInfo.playbackSuppressionReason) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
listener ->
listener.onPlaybackSuppressionReasonChanged(
finalPlayerInfo.playbackSuppressionReason));
}
if (oldPlayerInfo.isPlaying != finalPlayerInfo.isPlaying) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_IS_PLAYING_CHANGED,
listener -> listener.onIsPlayingChanged(finalPlayerInfo.isPlaying));
}
if (!Util.areEqual(oldPlayerInfo.playbackParameters, finalPlayerInfo.playbackParameters)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
listener -> listener.onPlaybackParametersChanged(finalPlayerInfo.playbackParameters));
}
if (oldPlayerInfo.repeatMode != finalPlayerInfo.repeatMode) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_REPEAT_MODE_CHANGED,
listener -> listener.onRepeatModeChanged(finalPlayerInfo.repeatMode));
}
if (oldPlayerInfo.shuffleModeEnabled != finalPlayerInfo.shuffleModeEnabled) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
listener -> listener.onShuffleModeEnabledChanged(finalPlayerInfo.shuffleModeEnabled));
}
if (!Util.areEqual(oldPlayerInfo.playlistMetadata, finalPlayerInfo.playlistMetadata)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_PLAYLIST_METADATA_CHANGED,
listener -> listener.onPlaylistMetadataChanged(finalPlayerInfo.playlistMetadata));
}
if (oldPlayerInfo.volume != finalPlayerInfo.volume) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_VOLUME_CHANGED,
listener -> listener.onVolumeChanged(finalPlayerInfo.volume));
}
if (!Util.areEqual(oldPlayerInfo.audioAttributes, finalPlayerInfo.audioAttributes)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_AUDIO_ATTRIBUTES_CHANGED,
listener -> listener.onAudioAttributesChanged(finalPlayerInfo.audioAttributes));
}
if (!oldPlayerInfo.cueGroup.cues.equals(finalPlayerInfo.cueGroup.cues)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_CUES,
listener -> listener.onCues(finalPlayerInfo.cueGroup.cues));
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_CUES,
listener -> listener.onCues(finalPlayerInfo.cueGroup));
}
if (!Util.areEqual(oldPlayerInfo.deviceInfo, finalPlayerInfo.deviceInfo)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_INFO_CHANGED,
listener -> listener.onDeviceInfoChanged(finalPlayerInfo.deviceInfo));
}
if (oldPlayerInfo.deviceVolume != finalPlayerInfo.deviceVolume
|| oldPlayerInfo.deviceMuted != finalPlayerInfo.deviceMuted) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener ->
listener.onDeviceVolumeChanged(
finalPlayerInfo.deviceVolume, finalPlayerInfo.deviceMuted));
}
if (!oldPlayerInfo.videoSize.equals(finalPlayerInfo.videoSize)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_VIDEO_SIZE_CHANGED,
listener -> listener.onVideoSizeChanged(finalPlayerInfo.videoSize));
}
if (oldPlayerInfo.seekBackIncrementMs != finalPlayerInfo.seekBackIncrementMs) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_SEEK_BACK_INCREMENT_CHANGED,
listener -> listener.onSeekBackIncrementChanged(finalPlayerInfo.seekBackIncrementMs));
}
if (oldPlayerInfo.seekForwardIncrementMs != finalPlayerInfo.seekForwardIncrementMs) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
listener ->
listener.onSeekForwardIncrementChanged(finalPlayerInfo.seekForwardIncrementMs));
}
if (oldPlayerInfo.maxSeekToPreviousPositionMs != finalPlayerInfo.maxSeekToPreviousPositionMs) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED,
listener ->
listener.onMaxSeekToPreviousPositionChanged(
finalPlayerInfo.maxSeekToPreviousPositionMs));
}
if (!oldPlayerInfo.trackSelectionParameters.equals(finalPlayerInfo.trackSelectionParameters)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
listener ->
listener.onTrackSelectionParametersChanged(finalPlayerInfo.trackSelectionParameters));
}
listeners.flushEvents();
@Nullable
@Player.DiscontinuityReason
Integer positionDiscontinuityReasonIfAny =
(!oldPlayerInfo.oldPositionInfo.equals(newPlayerInfo.oldPositionInfo)
|| !oldPlayerInfo.newPositionInfo.equals(newPlayerInfo.newPositionInfo))
? finalPlayerInfo.discontinuityReason
: null;
@Nullable
@Player.MediaItemTransitionReason
Integer mediaItemTransitionReasonIfAny =
!Util.areEqual(oldPlayerInfo.getCurrentMediaItem(), finalPlayerInfo.getCurrentMediaItem())
? finalPlayerInfo.mediaItemTransitionReason
: null;
@Nullable
@Player.TimelineChangeReason
Integer timelineChangeReasonIfAny =
!oldPlayerInfo.timeline.equals(finalPlayerInfo.timeline)
? finalPlayerInfo.timelineChangeReason
: null;
@Nullable
@Player.PlayWhenReadyChangeReason
Integer playWhenReadyChangeReasonIfAny =
oldPlayerInfo.playWhenReady != finalPlayerInfo.playWhenReady
? finalPlayerInfo.playWhenReadyChangeReason
: null;
notifyPlayerInfoListenersWithReasons(
oldPlayerInfo,
finalPlayerInfo,
timelineChangeReasonIfAny,
playWhenReadyChangeReasonIfAny,
positionDiscontinuityReasonIfAny,
mediaItemTransitionReasonIfAny);
}
void onAvailableCommandsChangedFromSession(

View File

@ -650,7 +650,8 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
/* durationMs= */ C.TIME_UNSET,
/* bufferedPositionMs= */ 0,
/* bufferedPercentage= */ 0,
/* totalBufferedDurationMs= */ 0));
/* totalBufferedDurationMs= */ 0),
Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
ControllerInfo maskedControllerInfo =
new ControllerInfo(
maskedPlayerInfo,
@ -711,7 +712,9 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
calculateCurrentItemIndexAfterAddItems(currentMediaItemIndex, index, mediaItems.size());
PlayerInfo maskedPlayerInfo =
controllerInfo.playerInfo.copyWithTimelineAndMediaItemIndex(
newQueueTimeline, newCurrentMediaItemIndex);
newQueueTimeline,
newCurrentMediaItemIndex,
Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
ControllerInfo maskedControllerInfo =
new ControllerInfo(
maskedPlayerInfo,
@ -759,7 +762,9 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
}
PlayerInfo maskedPlayerInfo =
controllerInfo.playerInfo.copyWithTimelineAndMediaItemIndex(
newQueueTimeline, newCurrentMediaItemIndex);
newQueueTimeline,
newCurrentMediaItemIndex,
Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
ControllerInfo maskedControllerInfo =
new ControllerInfo(
@ -823,7 +828,9 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
queueTimeline.copyWithMovedMediaItems(fromIndex, toIndex, newIndex);
PlayerInfo maskedPlayerInfo =
controllerInfo.playerInfo.copyWithTimelineAndMediaItemIndex(
newQueueTimeline, newCurrentMediaItemIndex);
newQueueTimeline,
newCurrentMediaItemIndex,
Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED);
ControllerInfo maskedControllerInfo =
new ControllerInfo(
@ -1536,7 +1543,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
(listener) ->
listener.onTimelineChanged(
newControllerInfo.playerInfo.timeline,
Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED));
newControllerInfo.playerInfo.timelineChangeReason));
}
if (!Util.areEqual(oldLegacyPlayerInfo.queueTitle, newLegacyPlayerInfo.queueTitle)) {
listeners.queueEvent(
@ -2232,6 +2239,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
/* shuffleModeEnabled= */ shuffleModeEnabled,
/* videoSize= */ VideoSize.UNKNOWN,
/* timeline= */ currentTimeline,
/* timelineChangeReason= */ PlayerInfo.TIMELINE_CHANGE_REASON_DEFAULT,
/* playlistMetadata= */ playlistMetadata,
/* volume= */ 1.0f,
/* audioAttributes= */ audioAttributes,

View File

@ -1086,7 +1086,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
session.playerInfo =
session.playerInfo.copyWithTimelineAndSessionPositionInfo(
timeline, player.createSessionPositionInfoForBundling());
timeline, player.createSessionPositionInfoForBundling(), reason);
session.onPlayerInfoChangedHandler.sendPlayerInfoChangedMessage(
/* excludeTimeline= */ false, /* excludeTracks= */ true);
session.dispatchRemoteControllerTaskToLegacyStub(
@ -1361,7 +1361,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
playerInfo =
playerInfo.copyWithTimelineAndSessionPositionInfo(
getPlayerWrapper().getCurrentTimelineWithCommandCheck(),
getPlayerWrapper().createSessionPositionInfoForBundling());
getPlayerWrapper().createSessionPositionInfoForBundling(),
playerInfo.timelineChangeReason);
dispatchOnPlayerInfoChanged(playerInfo, excludeTimeline, excludeTracks);
excludeTimeline = true;
excludeTracks = true;

View File

@ -20,6 +20,7 @@ import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT;
import static androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE;
import static androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST;
import static androidx.media3.common.Player.STATE_IDLE;
import static androidx.media3.common.Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED;
import android.os.Bundle;
import android.os.SystemClock;
@ -128,6 +129,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
private @Player.RepeatMode int repeatMode;
private boolean shuffleModeEnabled;
private Timeline timeline;
private @Player.TimelineChangeReason int timelineChangeReason;
private VideoSize videoSize;
private MediaMetadata playlistMetadata;
private float volume;
@ -160,6 +162,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
repeatMode = playerInfo.repeatMode;
shuffleModeEnabled = playerInfo.shuffleModeEnabled;
timeline = playerInfo.timeline;
timelineChangeReason = playerInfo.timelineChangeReason;
videoSize = playerInfo.videoSize;
playlistMetadata = playerInfo.playlistMetadata;
volume = playerInfo.volume;
@ -243,6 +246,12 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
return this;
}
@CanIgnoreReturnValue
public Builder setTimelineChangeReason(@Player.TimelineChangeReason int timelineChangeReason) {
this.timelineChangeReason = timelineChangeReason;
return this;
}
@CanIgnoreReturnValue
public Builder setVideoSize(VideoSize videoSize) {
this.videoSize = videoSize;
@ -381,6 +390,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
shuffleModeEnabled,
videoSize,
timeline,
timelineChangeReason,
playlistMetadata,
volume,
audioAttributes,
@ -414,6 +424,9 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
public static final int PLAY_WHEN_READY_CHANGE_REASON_DEFAULT =
PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST;
/** Default timeline change reason. */
public static final int TIMELINE_CHANGE_REASON_DEFAULT = TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED;
public static final PlayerInfo DEFAULT =
new PlayerInfo(
/* playerError= */ null,
@ -427,6 +440,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
/* shuffleModeEnabled= */ false,
VideoSize.UNKNOWN,
Timeline.EMPTY,
TIMELINE_CHANGE_REASON_DEFAULT,
MediaMetadata.EMPTY,
/* volume= */ 1f,
AudioAttributes.DEFAULT,
@ -467,6 +481,8 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
public final Timeline timeline;
public final @Player.TimelineChangeReason int timelineChangeReason;
public final VideoSize videoSize;
public final MediaMetadata playlistMetadata;
@ -580,17 +596,24 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
@CheckResult
public PlayerInfo copyWithTimelineAndSessionPositionInfo(
Timeline timeline, SessionPositionInfo sessionPositionInfo) {
Timeline timeline,
SessionPositionInfo sessionPositionInfo,
@Player.TimelineChangeReason int timelineChangeReason) {
return new Builder(this)
.setTimeline(timeline)
.setSessionPositionInfo(sessionPositionInfo)
.setTimelineChangeReason(timelineChangeReason)
.build();
}
@CheckResult
public PlayerInfo copyWithTimelineAndMediaItemIndex(Timeline timeline, int mediaItemIndex) {
public PlayerInfo copyWithTimelineAndMediaItemIndex(
Timeline timeline,
int mediaItemIndex,
@Player.TimelineChangeReason int timelineChangeReason) {
return new Builder(this)
.setTimeline(timeline)
.setTimelineChangeReason(timelineChangeReason)
.setSessionPositionInfo(
new SessionPositionInfo(
new PositionInfo(
@ -696,6 +719,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
boolean shuffleModeEnabled,
VideoSize videoSize,
Timeline timeline,
@Player.TimelineChangeReason int timelineChangeReason,
MediaMetadata playlistMetadata,
float volume,
AudioAttributes audioAttributes,
@ -726,6 +750,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
this.shuffleModeEnabled = shuffleModeEnabled;
this.videoSize = videoSize;
this.timeline = timeline;
this.timelineChangeReason = timelineChangeReason;
this.playlistMetadata = playlistMetadata;
this.volume = volume;
this.audioAttributes = audioAttributes;
@ -796,7 +821,8 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
private static final String FIELD_MAX_SEEK_TO_PREVIOUS_POSITION_MS = Util.intToStringMaxRadix(28);
private static final String FIELD_TRACK_SELECTION_PARAMETERS = Util.intToStringMaxRadix(29);
private static final String FIELD_CURRENT_TRACKS = Util.intToStringMaxRadix(30);
// Next field key = 31
private static final String FIELD_TIMELINE_CHANGE_REASON = Util.intToStringMaxRadix(31);
// Next field key = 32
public Bundle toBundle(
Player.Commands availableCommands, boolean excludeTimeline, boolean excludeTracks) {
@ -828,6 +854,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
FIELD_TIMELINE,
timeline.toBundleWithOneWindowOnly(sessionPositionInfo.positionInfo.mediaItemIndex));
}
bundle.putInt(FIELD_TIMELINE_CHANGE_REASON, timelineChangeReason);
bundle.putBundle(FIELD_VIDEO_SIZE, videoSize.toBundle());
if (availableCommands.contains(Player.COMMAND_GET_METADATA)) {
bundle.putBundle(FIELD_PLAYLIST_METADATA, playlistMetadata.toBundle());
@ -911,6 +938,9 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
@Nullable Bundle timelineBundle = bundle.getBundle(FIELD_TIMELINE);
Timeline timeline =
timelineBundle == null ? Timeline.EMPTY : Timeline.CREATOR.fromBundle(timelineBundle);
int timelineChangeReason =
bundle.getInt(
FIELD_TIMELINE_CHANGE_REASON, /* defaultValue= */ TIMELINE_CHANGE_REASON_DEFAULT);
@Nullable Bundle videoSizeBundle = bundle.getBundle(FIELD_VIDEO_SIZE);
VideoSize videoSize =
videoSizeBundle == null ? VideoSize.UNKNOWN : VideoSize.CREATOR.fromBundle(videoSizeBundle);
@ -982,6 +1012,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
shuffleModeEnabled,
videoSize,
timeline,
timelineChangeReason,
playlistMetadata,
volume,
audioAttributes,

View File

@ -1169,6 +1169,7 @@ import java.util.List;
getShuffleModeEnabled(),
getVideoSize(),
getCurrentTimelineWithCommandCheck(),
PlayerInfo.TIMELINE_CHANGE_REASON_DEFAULT,
getPlaylistMetadataWithCommandCheck(),
getVolumeWithCommandCheck(),
getAudioAttributesWithCommandCheck(),

View File

@ -118,6 +118,7 @@ public class PlayerInfoTest {
/* contentDurationMs= */ 27000,
/* contentBufferedPositionMs= */ 15000))
.setTimeline(new FakeTimeline(/* windowCount= */ 10))
.setTimelineChangeReason(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.setMediaMetadata(new MediaMetadata.Builder().setTitle("title").build())
.setPlaylistMetadata(new MediaMetadata.Builder().setArtist("artist").build())
.setVolume(0.5f)
@ -202,6 +203,8 @@ public class PlayerInfoTest {
assertThat(infoAfterBundling.sessionPositionInfo.contentDurationMs).isEqualTo(27000);
assertThat(infoAfterBundling.sessionPositionInfo.contentBufferedPositionMs).isEqualTo(15000);
assertThat(infoAfterBundling.timeline.getWindowCount()).isEqualTo(10);
assertThat(infoAfterBundling.timelineChangeReason)
.isEqualTo(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
assertThat(infoAfterBundling.mediaMetadata.title).isEqualTo("title");
assertThat(infoAfterBundling.playlistMetadata.artist).isEqualTo("artist");
assertThat(infoAfterBundling.volume).isEqualTo(0.5f);

View File

@ -63,7 +63,7 @@ import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
/** Tests for state masking {@link MediaController} calls. */
/** Tests for state masking {@link MediaController} ({@link MediaControllerImplBase}) calls. */
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MediaControllerStateMaskingTest {

View File

@ -75,7 +75,7 @@ import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
/** Tests for state masking {@link MediaController} calls. */
/** Tests for state masking {@link MediaController} ({@link MediaControllerImplLegacy}) calls. */
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MediaControllerStateMaskingWithMediaSessionCompatTest {