From cf1dcede591e3db5481ef578e0637e271be8f336 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 7 Feb 2022 11:59:39 +0000 Subject: [PATCH] Remove deprecated EventListener PiperOrigin-RevId: 426876984 --- RELEASENOTES.md | 1 + .../exoplayer2/ext/cast/CastPlayer.java | 36 +- .../android/exoplayer2/ForwardingPlayer.java | 322 +++++---- .../com/google/android/exoplayer2/Player.java | 647 ++++++++---------- .../exoplayer2/ForwardingPlayerTest.java | 15 - .../google/android/exoplayer2/ExoPlayer.java | 24 - .../android/exoplayer2/ExoPlayerImpl.java | 116 ++-- .../android/exoplayer2/SimpleExoPlayer.java | 12 - .../exoplayer2/testutil/StubExoPlayer.java | 11 - 9 files changed, 494 insertions(+), 690 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 169f5cc652..82b73f50ac 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -152,6 +152,7 @@ `DefaultMediaItemConverter` ([#9663](https://github.com/google/ExoPlayer/issues/9663)). * Remove deprecated symbols: + * Remove `Player.EventLister`. Use `Player.Listener` instead. * Remove `MediaSourceFactory#setDrmSessionManager`, `MediaSourceFactory#setDrmHttpDataSourceFactory`, and `MediaSourceFactory#setDrmUserAgent`. Use diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java index 40e61c8135..11172eb186 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java @@ -135,7 +135,7 @@ public final class CastPlayer extends BasePlayer { private final SeekResultCallback seekResultCallback; // Listeners and notification. - private final ListenerSet listeners; + private final ListenerSet listeners; @Nullable private SessionAvailabilityListener sessionAvailabilityListener; // Internal state. @@ -278,41 +278,11 @@ public final class CastPlayer extends BasePlayer { @Override public void addListener(Listener listener) { - EventListener eventListener = listener; - addListener(eventListener); - } - - /** - * Registers a listener to receive events from the player. - * - *

The listener's methods will be called on the thread associated with {@link - * #getApplicationLooper()}. - * - * @param listener The listener to register. - * @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead. - */ - @Deprecated - @SuppressWarnings("deprecation") - public void addListener(EventListener listener) { listeners.add(listener); } @Override public void removeListener(Listener listener) { - EventListener eventListener = listener; - removeListener(eventListener); - } - - /** - * Unregister a listener registered through {@link #addListener(EventListener)}. The listener will - * no longer receive events from the player. - * - * @param listener The listener to unregister. - * @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead. - */ - @Deprecated - @SuppressWarnings("deprecation") - public void removeListener(EventListener listener) { listeners.remove(listener); } @@ -471,7 +441,7 @@ public final class CastPlayer extends BasePlayer { } updateAvailableCommandsAndNotifyIfChanged(); } else if (pendingSeekCount == 0) { - listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); + listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed); } listeners.flushEvents(); } @@ -1475,7 +1445,7 @@ public final class CastPlayer extends BasePlayer { currentWindowIndex = pendingSeekWindowIndex; pendingSeekWindowIndex = C.INDEX_UNSET; pendingSeekPositionMs = C.TIME_UNSET; - listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); + listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed); } } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java index 18070ba53b..62d4c275c6 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/ForwardingPlayer.java @@ -823,191 +823,159 @@ public class ForwardingPlayer implements Player { return player; } - @SuppressWarnings("deprecation") // Use of deprecated type for backwards compatibility. - private static class ForwardingEventListener implements EventListener { + private static final class ForwardingListener implements Listener { private final ForwardingPlayer forwardingPlayer; - private final EventListener eventListener; + private final Listener listener; - private ForwardingEventListener( - ForwardingPlayer forwardingPlayer, EventListener eventListener) { + public ForwardingListener(ForwardingPlayer forwardingPlayer, Listener listener) { this.forwardingPlayer = forwardingPlayer; - this.eventListener = eventListener; - } - - @Override - public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) { - eventListener.onTimelineChanged(timeline, reason); - } - - @Override - public void onMediaItemTransition( - @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { - eventListener.onMediaItemTransition(mediaItem, reason); - } - - @Override - public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { - eventListener.onTracksChanged(trackGroups, trackSelections); - } - - @Override - public void onTracksInfoChanged(TracksInfo tracksInfo) { - eventListener.onTracksInfoChanged(tracksInfo); - } - - @Override - public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { - eventListener.onMediaMetadataChanged(mediaMetadata); - } - - @Override - public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) { - eventListener.onPlaylistMetadataChanged(mediaMetadata); - } - - @Override - public void onIsLoadingChanged(boolean isLoading) { - eventListener.onIsLoadingChanged(isLoading); - } - - @Override - public void onLoadingChanged(boolean isLoading) { - eventListener.onIsLoadingChanged(isLoading); - } - - @Override - public void onAvailableCommandsChanged(Commands availableCommands) { - eventListener.onAvailableCommandsChanged(availableCommands); - } - - @Override - public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) { - eventListener.onTrackSelectionParametersChanged(parameters); - } - - @Override - public void onPlayerStateChanged(boolean playWhenReady, @State int playbackState) { - eventListener.onPlayerStateChanged(playWhenReady, playbackState); - } - - @Override - public void onPlaybackStateChanged(@State int playbackState) { - eventListener.onPlaybackStateChanged(playbackState); - } - - @Override - public void onPlayWhenReadyChanged( - boolean playWhenReady, @PlayWhenReadyChangeReason int reason) { - eventListener.onPlayWhenReadyChanged(playWhenReady, reason); - } - - @Override - public void onPlaybackSuppressionReasonChanged( - @PlayWhenReadyChangeReason int playbackSuppressionReason) { - eventListener.onPlaybackSuppressionReasonChanged(playbackSuppressionReason); - } - - @Override - public void onIsPlayingChanged(boolean isPlaying) { - eventListener.onIsPlayingChanged(isPlaying); - } - - @Override - public void onRepeatModeChanged(@RepeatMode int repeatMode) { - eventListener.onRepeatModeChanged(repeatMode); - } - - @Override - public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { - eventListener.onShuffleModeEnabledChanged(shuffleModeEnabled); - } - - @Override - public void onPlayerError(PlaybackException error) { - eventListener.onPlayerError(error); - } - - @Override - public void onPlayerErrorChanged(@Nullable PlaybackException error) { - eventListener.onPlayerErrorChanged(error); - } - - @Override - public void onPositionDiscontinuity(@DiscontinuityReason int reason) { - eventListener.onPositionDiscontinuity(reason); - } - - @Override - public void onPositionDiscontinuity( - PositionInfo oldPosition, PositionInfo newPosition, @DiscontinuityReason int reason) { - eventListener.onPositionDiscontinuity(oldPosition, newPosition, reason); - } - - @Override - public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { - eventListener.onPlaybackParametersChanged(playbackParameters); - } - - @Override - public void onSeekBackIncrementChanged(long seekBackIncrementMs) { - eventListener.onSeekBackIncrementChanged(seekBackIncrementMs); - } - - @Override - public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) { - eventListener.onSeekForwardIncrementChanged(seekForwardIncrementMs); - } - - @Override - public void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) { - eventListener.onMaxSeekToPreviousPositionChanged(maxSeekToPreviousPositionMs); - } - - @Override - public void onSeekProcessed() { - eventListener.onSeekProcessed(); + this.listener = listener; } @Override public void onEvents(Player player, Events events) { // Replace player with forwarding player. - eventListener.onEvents(forwardingPlayer, events); + listener.onEvents(forwardingPlayer, events); } @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ForwardingEventListener)) { - return false; - } - - ForwardingEventListener that = (ForwardingEventListener) o; - - if (!forwardingPlayer.equals(that.forwardingPlayer)) { - return false; - } - return eventListener.equals(that.eventListener); + public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) { + listener.onTimelineChanged(timeline, reason); } @Override - public int hashCode() { - int result = forwardingPlayer.hashCode(); - result = 31 * result + eventListener.hashCode(); - return result; + public void onMediaItemTransition( + @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) { + listener.onMediaItemTransition(mediaItem, reason); } - } - private static final class ForwardingListener extends ForwardingEventListener - implements Listener { + @Override + @SuppressWarnings("deprecation") + public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { + listener.onTracksChanged(trackGroups, trackSelections); + } - private final Listener listener; + @Override + public void onTracksInfoChanged(TracksInfo tracksInfo) { + listener.onTracksInfoChanged(tracksInfo); + } - public ForwardingListener(ForwardingPlayer forwardingPlayer, Listener listener) { - super(forwardingPlayer, listener); - this.listener = listener; + @Override + public void onMediaMetadataChanged(MediaMetadata mediaMetadata) { + listener.onMediaMetadataChanged(mediaMetadata); + } + + @Override + public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) { + listener.onPlaylistMetadataChanged(mediaMetadata); + } + + @Override + public void onIsLoadingChanged(boolean isLoading) { + listener.onIsLoadingChanged(isLoading); + } + + @Override + @SuppressWarnings("deprecation") + public void onLoadingChanged(boolean isLoading) { + listener.onIsLoadingChanged(isLoading); + } + + @Override + public void onAvailableCommandsChanged(Commands availableCommands) { + listener.onAvailableCommandsChanged(availableCommands); + } + + @Override + public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) { + listener.onTrackSelectionParametersChanged(parameters); + } + + @Override + @SuppressWarnings("deprecation") + public void onPlayerStateChanged(boolean playWhenReady, @State int playbackState) { + listener.onPlayerStateChanged(playWhenReady, playbackState); + } + + @Override + public void onPlaybackStateChanged(@State int playbackState) { + listener.onPlaybackStateChanged(playbackState); + } + + @Override + public void onPlayWhenReadyChanged( + boolean playWhenReady, @PlayWhenReadyChangeReason int reason) { + listener.onPlayWhenReadyChanged(playWhenReady, reason); + } + + @Override + public void onPlaybackSuppressionReasonChanged( + @PlayWhenReadyChangeReason int playbackSuppressionReason) { + listener.onPlaybackSuppressionReasonChanged(playbackSuppressionReason); + } + + @Override + public void onIsPlayingChanged(boolean isPlaying) { + listener.onIsPlayingChanged(isPlaying); + } + + @Override + public void onRepeatModeChanged(@RepeatMode int repeatMode) { + listener.onRepeatModeChanged(repeatMode); + } + + @Override + public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { + listener.onShuffleModeEnabledChanged(shuffleModeEnabled); + } + + @Override + public void onPlayerError(PlaybackException error) { + listener.onPlayerError(error); + } + + @Override + public void onPlayerErrorChanged(@Nullable PlaybackException error) { + listener.onPlayerErrorChanged(error); + } + + @Override + @SuppressWarnings("deprecation") + public void onPositionDiscontinuity(@DiscontinuityReason int reason) { + listener.onPositionDiscontinuity(reason); + } + + @Override + public void onPositionDiscontinuity( + PositionInfo oldPosition, PositionInfo newPosition, @DiscontinuityReason int reason) { + listener.onPositionDiscontinuity(oldPosition, newPosition, reason); + } + + @Override + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { + listener.onPlaybackParametersChanged(playbackParameters); + } + + @Override + public void onSeekBackIncrementChanged(long seekBackIncrementMs) { + listener.onSeekBackIncrementChanged(seekBackIncrementMs); + } + + @Override + public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) { + listener.onSeekForwardIncrementChanged(seekForwardIncrementMs); + } + + @Override + public void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) { + listener.onMaxSeekToPreviousPositionChanged(maxSeekToPreviousPositionMs); + } + + @Override + @SuppressWarnings("deprecation") + public void onSeekProcessed() { + listener.onSeekProcessed(); } @Override @@ -1064,5 +1032,27 @@ public class ForwardingPlayer implements Player { public void onDeviceVolumeChanged(int volume, boolean muted) { listener.onDeviceVolumeChanged(volume, muted); } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ForwardingListener)) { + return false; + } + ForwardingListener that = (ForwardingListener) o; + if (!forwardingPlayer.equals(that.forwardingPlayer)) { + return false; + } + return listener.equals(that.listener); + } + + @Override + public int hashCode() { + int result = forwardingPlayer.hashCode(); + result = 31 * result + listener.hashCode(); + return result; + } } } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Player.java b/library/common/src/main/java/com/google/android/exoplayer2/Player.java index ce136c505d..987a9f4d3f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Player.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Player.java @@ -70,341 +70,6 @@ import java.util.List; */ public interface Player { - /** - * Listener of changes in player state. - * - *

All methods have no-op default implementations to allow selective overrides. - * - *

Listeners can choose to implement individual events (e.g. {@link - * #onIsPlayingChanged(boolean)}) or {@link #onEvents(Player, Events)}, which is called after one - * or more events occurred together. - * - * @deprecated Use {@link Player.Listener}. - */ - @Deprecated - interface EventListener { - - /** - * Called when the timeline has been refreshed. - * - *

Note that the current {@link MediaItem} or playback position may change as a result of a - * timeline change. If playback can't continue smoothly because of this timeline change, a - * separate {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} callback will be - * triggered. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param timeline The latest timeline. Never null, but may be empty. - * @param reason The {@link TimelineChangeReason} responsible for this timeline change. - */ - default void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {} - - /** - * Called when playback transitions to a media item or starts repeating a media item according - * to the current {@link #getRepeatMode() repeat mode}. - * - *

Note that this callback is also called when the playlist becomes non-empty or empty as a - * consequence of a playlist change. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param mediaItem The {@link MediaItem}. May be null if the playlist becomes empty. - * @param reason The reason for the transition. - */ - default void onMediaItemTransition( - @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {} - - /** - * Called when the available or selected tracks change. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param trackGroups The available tracks. Never null, but may be of length zero. - * @param trackSelections The selected tracks. Never null, but may contain null elements. A - * concrete implementation may include null elements if it has a fixed number of renderer - * components, wishes to report a TrackSelection for each of them, and has one or more - * renderer components that is not assigned any selected tracks. - * @deprecated Use {@link #onTracksInfoChanged(TracksInfo)} instead. - */ - @Deprecated - default void onTracksChanged( - TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {} - - /** - * Called when the available or selected tracks change. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param tracksInfo The available tracks information. Never null, but may be of length zero. - */ - default void onTracksInfoChanged(TracksInfo tracksInfo) {} - - /** - * Called when the combined {@link MediaMetadata} changes. - * - *

The provided {@link MediaMetadata} is a combination of the {@link MediaItem#mediaMetadata} - * and the static and dynamic metadata from the {@link TrackSelection#getFormat(int) track - * selections' formats} and {@link Listener#onMetadata(Metadata)}. If a field is populated in - * the {@link MediaItem#mediaMetadata}, it will be prioritised above the same field coming from - * static or dynamic metadata. - * - *

This method may be called multiple times in quick succession. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param mediaMetadata The combined {@link MediaMetadata}. - */ - default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {} - - /** Called when the playlist {@link MediaMetadata} changes. */ - default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {} - - /** - * Called when the player starts or stops loading the source. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param isLoading Whether the source is currently being loaded. - */ - default void onIsLoadingChanged(boolean isLoading) {} - - /** @deprecated Use {@link #onIsLoadingChanged(boolean)} instead. */ - @Deprecated - default void onLoadingChanged(boolean isLoading) {} - - /** - * Called when the value returned from {@link #isCommandAvailable(int)} changes for at least one - * {@link Command}. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param availableCommands The available {@link Commands}. - */ - default void onAvailableCommandsChanged(Commands availableCommands) {} - - /** - * Called when the value returned from {@link #getTrackSelectionParameters()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param parameters The new {@link TrackSelectionParameters}. - */ - default void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) {} - - /** - * @deprecated Use {@link #onPlaybackStateChanged(int)} and {@link - * #onPlayWhenReadyChanged(boolean, int)} instead. - */ - @Deprecated - default void onPlayerStateChanged(boolean playWhenReady, @State int playbackState) {} - - /** - * Called when the value returned from {@link #getPlaybackState()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param playbackState The new playback {@link State state}. - */ - default void onPlaybackStateChanged(@State int playbackState) {} - - /** - * Called when the value returned from {@link #getPlayWhenReady()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param playWhenReady Whether playback will proceed when ready. - * @param reason The {@link PlayWhenReadyChangeReason reason} for the change. - */ - default void onPlayWhenReadyChanged( - boolean playWhenReady, @PlayWhenReadyChangeReason int reason) {} - - /** - * Called when the value returned from {@link #getPlaybackSuppressionReason()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param playbackSuppressionReason The current {@link PlaybackSuppressionReason}. - */ - default void onPlaybackSuppressionReasonChanged( - @PlaybackSuppressionReason int playbackSuppressionReason) {} - - /** - * Called when the value of {@link #isPlaying()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param isPlaying Whether the player is playing. - */ - default void onIsPlayingChanged(boolean isPlaying) {} - - /** - * Called when the value of {@link #getRepeatMode()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param repeatMode The {@link RepeatMode} used for playback. - */ - default void onRepeatModeChanged(@RepeatMode int repeatMode) {} - - /** - * Called when the value of {@link #getShuffleModeEnabled()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param shuffleModeEnabled Whether shuffling of {@link MediaItem media items} is enabled. - */ - default void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {} - - /** - * Called when an error occurs. The playback state will transition to {@link #STATE_IDLE} - * immediately after this method is called. The player instance can still be used, and {@link - * #release()} must still be called on the player should it no longer be required. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - *

Implementations of Player may pass an instance of a subclass of {@link PlaybackException} - * to this method in order to include more information about the error. - * - * @param error The error. - */ - default void onPlayerError(PlaybackException error) {} - - /** - * Called when the {@link PlaybackException} returned by {@link #getPlayerError()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - *

Implementations of Player may pass an instance of a subclass of {@link PlaybackException} - * to this method in order to include more information about the error. - * - * @param error The new error, or null if the error is being cleared. - */ - default void onPlayerErrorChanged(@Nullable PlaybackException error) {} - - /** - * @deprecated Use {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} instead. - */ - @Deprecated - default void onPositionDiscontinuity(@DiscontinuityReason int reason) {} - - /** - * Called when a position discontinuity occurs. - * - *

A position discontinuity occurs when the playing period changes, the playback position - * jumps within the period currently being played, or when the playing period has been skipped - * or removed. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param oldPosition The position before the discontinuity. - * @param newPosition The position after the discontinuity. - * @param reason The {@link DiscontinuityReason} responsible for the discontinuity. - */ - default void onPositionDiscontinuity( - PositionInfo oldPosition, PositionInfo newPosition, @DiscontinuityReason int reason) {} - - /** - * Called when the current playback parameters change. The playback parameters may change due to - * a call to {@link #setPlaybackParameters(PlaybackParameters)}, or the player itself may change - * them (for example, if audio playback switches to passthrough or offload mode, where speed - * adjustment is no longer possible). - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param playbackParameters The playback parameters. - */ - default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {} - - /** - * Called when the value of {@link #getSeekBackIncrement()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param seekBackIncrementMs The {@link #seekBack()} increment, in milliseconds. - */ - default void onSeekBackIncrementChanged(long seekBackIncrementMs) {} - - /** - * Called when the value of {@link #getSeekForwardIncrement()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds. - */ - default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {} - - /** - * Called when the value of {@link #getMaxSeekToPreviousPosition()} changes. - * - *

{@link #onEvents(Player, Events)} will also be called to report this event along with - * other events that happen in the same {@link Looper} message queue iteration. - * - * @param maxSeekToPreviousPositionMs The maximum position for which {@link #seekToPrevious()} - * seeks to the previous position, in milliseconds. - */ - default void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) {} - - /** - * @deprecated Seeks are processed without delay. Listen to {@link - * #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} with reason {@link - * #DISCONTINUITY_REASON_SEEK} instead. - */ - @Deprecated - default void onSeekProcessed() {} - - /** - * Called when one or more player states changed. - * - *

State changes and events that happen within one {@link Looper} message queue iteration are - * reported together and only after all individual callbacks were triggered. - * - *

Only state changes represented by {@link Event events} are reported through this method. - * - *

Listeners should prefer this method over individual callbacks in the following cases: - * - *

    - *
  • They intend to trigger the same logic for multiple events (e.g. when updating a UI for - * both {@link #onPlaybackStateChanged(int)} and {@link #onPlayWhenReadyChanged(boolean, - * int)}). - *
  • They need access to the {@link Player} object to trigger further events (e.g. to call - * {@link Player#seekTo(long)} after a {@link #onMediaItemTransition(MediaItem, int)}). - *
  • They intend to use multiple state values together or in combination with {@link Player} - * getter methods. For example using {@link #getCurrentMediaItemIndex()} with the {@code - * timeline} provided in {@link #onTimelineChanged(Timeline, int)} is only safe from - * within this method. - *
  • They are interested in events that logically happened together (e.g {@link - * #onPlaybackStateChanged(int)} to {@link #STATE_BUFFERING} because of {@link - * #onMediaItemTransition(MediaItem, int)}). - *
- * - * @param player The {@link Player} whose state changed. Use the getters to obtain the latest - * states. - * @param events The {@link Events} that happened in this iteration, indicating which player - * states changed. - */ - default void onEvents(Player player, Events events) {} - } - /** A set of {@link Event events}. */ final class Events { @@ -937,62 +602,327 @@ public interface Player { * *

All methods have no-op default implementations to allow selective overrides. */ - interface Listener extends EventListener { + interface Listener { - @Override + /** + * Called when one or more player states changed. + * + *

State changes and events that happen within one {@link Looper} message queue iteration are + * reported together and only after all individual callbacks were triggered. + * + *

Only state changes represented by {@link Event events} are reported through this method. + * + *

Listeners should prefer this method over individual callbacks in the following cases: + * + *

    + *
  • They intend to trigger the same logic for multiple events (e.g. when updating a UI for + * both {@link #onPlaybackStateChanged(int)} and {@link #onPlayWhenReadyChanged(boolean, + * int)}). + *
  • They need access to the {@link Player} object to trigger further events (e.g. to call + * {@link Player#seekTo(long)} after a {@link #onMediaItemTransition(MediaItem, int)}). + *
  • They intend to use multiple state values together or in combination with {@link Player} + * getter methods. For example using {@link #getCurrentMediaItemIndex()} with the {@code + * timeline} provided in {@link #onTimelineChanged(Timeline, int)} is only safe from + * within this method. + *
  • They are interested in events that logically happened together (e.g {@link + * #onPlaybackStateChanged(int)} to {@link #STATE_BUFFERING} because of {@link + * #onMediaItemTransition(MediaItem, int)}). + *
+ * + * @param player The {@link Player} whose state changed. Use the getters to obtain the latest + * states. + * @param events The {@link Events} that happened in this iteration, indicating which player + * states changed. + */ + default void onEvents(Player player, Events events) {} + + /** + * Called when the timeline has been refreshed. + * + *

Note that the current {@link MediaItem} or playback position may change as a result of a + * timeline change. If playback can't continue smoothly because of this timeline change, a + * separate {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} callback will be + * triggered. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param timeline The latest timeline. Never null, but may be empty. + * @param reason The {@link TimelineChangeReason} responsible for this timeline change. + */ default void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {} - @Override + /** + * Called when playback transitions to a media item or starts repeating a media item according + * to the current {@link #getRepeatMode() repeat mode}. + * + *

Note that this callback is also called when the playlist becomes non-empty or empty as a + * consequence of a playlist change. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param mediaItem The {@link MediaItem}. May be null if the playlist becomes empty. + * @param reason The reason for the transition. + */ default void onMediaItemTransition( @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {} - @Override + /** + * Called when the available or selected tracks change. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param trackGroups The available tracks. Never null, but may be of length zero. + * @param trackSelections The selected tracks. Never null, but may contain null elements. A + * concrete implementation may include null elements if it has a fixed number of renderer + * components, wishes to report a TrackSelection for each of them, and has one or more + * renderer components that is not assigned any selected tracks. + * @deprecated Use {@link #onTracksInfoChanged(TracksInfo)} instead. + */ + @Deprecated + default void onTracksChanged( + TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {} + + /** + * Called when the available or selected tracks change. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param tracksInfo The available tracks information. Never null, but may be of length zero. + */ default void onTracksInfoChanged(TracksInfo tracksInfo) {} - @Override + /** + * Called when the combined {@link MediaMetadata} changes. + * + *

The provided {@link MediaMetadata} is a combination of the {@link MediaItem#mediaMetadata} + * and the static and dynamic metadata from the {@link TrackSelection#getFormat(int) track + * selections' formats} and {@link Listener#onMetadata(Metadata)}. If a field is populated in + * the {@link MediaItem#mediaMetadata}, it will be prioritised above the same field coming from + * static or dynamic metadata. + * + *

This method may be called multiple times in quick succession. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param mediaMetadata The combined {@link MediaMetadata}. + */ + default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {} + + /** Called when the playlist {@link MediaMetadata} changes. */ + default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {} + + /** + * Called when the player starts or stops loading the source. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param isLoading Whether the source is currently being loaded. + */ default void onIsLoadingChanged(boolean isLoading) {} - @Override + /** @deprecated Use {@link #onIsLoadingChanged(boolean)} instead. */ + @Deprecated + default void onLoadingChanged(boolean isLoading) {} + + /** + * Called when the value returned from {@link #isCommandAvailable(int)} changes for at least one + * {@link Command}. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param availableCommands The available {@link Commands}. + */ default void onAvailableCommandsChanged(Commands availableCommands) {} - @Override + /** + * Called when the value returned from {@link #getTrackSelectionParameters()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param parameters The new {@link TrackSelectionParameters}. + */ + default void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) {} + + /** + * @deprecated Use {@link #onPlaybackStateChanged(int)} and {@link + * #onPlayWhenReadyChanged(boolean, int)} instead. + */ + @Deprecated + default void onPlayerStateChanged(boolean playWhenReady, @State int playbackState) {} + + /** + * Called when the value returned from {@link #getPlaybackState()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param playbackState The new playback {@link State state}. + */ default void onPlaybackStateChanged(@State int playbackState) {} - @Override + /** + * Called when the value returned from {@link #getPlayWhenReady()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param playWhenReady Whether playback will proceed when ready. + * @param reason The {@link PlayWhenReadyChangeReason reason} for the change. + */ default void onPlayWhenReadyChanged( boolean playWhenReady, @PlayWhenReadyChangeReason int reason) {} - @Override + /** + * Called when the value returned from {@link #getPlaybackSuppressionReason()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param playbackSuppressionReason The current {@link PlaybackSuppressionReason}. + */ default void onPlaybackSuppressionReasonChanged( @PlaybackSuppressionReason int playbackSuppressionReason) {} - @Override + /** + * Called when the value of {@link #isPlaying()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param isPlaying Whether the player is playing. + */ default void onIsPlayingChanged(boolean isPlaying) {} - @Override + /** + * Called when the value of {@link #getRepeatMode()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param repeatMode The {@link RepeatMode} used for playback. + */ default void onRepeatModeChanged(@RepeatMode int repeatMode) {} - @Override + /** + * Called when the value of {@link #getShuffleModeEnabled()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param shuffleModeEnabled Whether shuffling of {@link MediaItem media items} is enabled. + */ default void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {} - @Override + /** + * Called when an error occurs. The playback state will transition to {@link #STATE_IDLE} + * immediately after this method is called. The player instance can still be used, and {@link + * #release()} must still be called on the player should it no longer be required. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + *

Implementations of Player may pass an instance of a subclass of {@link PlaybackException} + * to this method in order to include more information about the error. + * + * @param error The error. + */ default void onPlayerError(PlaybackException error) {} - @Override + /** + * Called when the {@link PlaybackException} returned by {@link #getPlayerError()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + *

Implementations of Player may pass an instance of a subclass of {@link PlaybackException} + * to this method in order to include more information about the error. + * + * @param error The new error, or null if the error is being cleared. + */ default void onPlayerErrorChanged(@Nullable PlaybackException error) {} - @Override + /** + * @deprecated Use {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} instead. + */ + @Deprecated + default void onPositionDiscontinuity(@DiscontinuityReason int reason) {} + + /** + * Called when a position discontinuity occurs. + * + *

A position discontinuity occurs when the playing period changes, the playback position + * jumps within the period currently being played, or when the playing period has been skipped + * or removed. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param oldPosition The position before the discontinuity. + * @param newPosition The position after the discontinuity. + * @param reason The {@link DiscontinuityReason} responsible for the discontinuity. + */ default void onPositionDiscontinuity( PositionInfo oldPosition, PositionInfo newPosition, @DiscontinuityReason int reason) {} - @Override + /** + * Called when the current playback parameters change. The playback parameters may change due to + * a call to {@link #setPlaybackParameters(PlaybackParameters)}, or the player itself may change + * them (for example, if audio playback switches to passthrough or offload mode, where speed + * adjustment is no longer possible). + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param playbackParameters The playback parameters. + */ default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {} - @Override + /** + * Called when the value of {@link #getSeekBackIncrement()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param seekBackIncrementMs The {@link #seekBack()} increment, in milliseconds. + */ + default void onSeekBackIncrementChanged(long seekBackIncrementMs) {} + + /** + * Called when the value of {@link #getSeekForwardIncrement()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds. + */ default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {} - @Override - default void onSeekBackIncrementChanged(long seekBackIncrementMs) {} + /** + * Called when the value of {@link #getMaxSeekToPreviousPosition()} changes. + * + *

{@link #onEvents(Player, Events)} will also be called to report this event along with + * other events that happen in the same {@link Looper} message queue iteration. + * + * @param maxSeekToPreviousPositionMs The maximum position for which {@link #seekToPrevious()} + * seeks to the previous position, in milliseconds. + */ + default void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) {} + + /** + * @deprecated Seeks are processed without delay. Listen to {@link + * #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} with reason {@link + * #DISCONTINUITY_REASON_SEEK} instead. + */ + @Deprecated + default void onSeekProcessed() {} /** * Called when the audio session ID changes. @@ -1028,9 +958,6 @@ public interface Player { /** Called when the device volume or mute state changes. */ default void onDeviceVolumeChanged(int volume, boolean muted) {} - @Override - default void onEvents(Player player, Events events) {} - /** * Called each time there's a change in the size of the video being rendered. * @@ -1071,12 +998,6 @@ public interface Player { * @param metadata The metadata. */ default void onMetadata(Metadata metadata) {} - - @Override - default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {} - - @Override - default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {} } /** diff --git a/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java b/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java index 9c6e481e50..0f27ae8690 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/ForwardingPlayerTest.java @@ -116,21 +116,6 @@ public class ForwardingPlayerTest { } } - @Test - @SuppressWarnings("deprecation") // Testing backwards compatibility with deprecated type. - public void forwardingEventListener_overridesAllEventListenerMethods() throws Exception { - // Check with reflection that ForwardingListener overrides all Listener methods. - Class forwardingListenerClass = getInnerClass("ForwardingEventListener"); - List methods = getPublicMethods(Player.EventListener.class); - for (int i = 0; i < methods.size(); i++) { - Method method = methods.get(i); - assertThat( - forwardingListenerClass.getDeclaredMethod( - method.getName(), method.getParameterTypes())) - .isNotNull(); - } - } - @Test public void forwardingListener_overridesAllListenerMethods() throws Exception { // Check with reflection that ForwardingListener overrides all Listener methods. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index 6db9daa4b7..379f5fa6b9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -1041,30 +1041,6 @@ public interface ExoPlayer extends Player { @Deprecated DeviceComponent getDeviceComponent(); - /** - * Registers a listener to receive events from the player. - * - *

The listener's methods will be called on the thread associated with {@link - * #getApplicationLooper()}. - * - * @param listener The listener to register. - * @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead. - */ - @Deprecated - @SuppressWarnings("deprecation") - void addListener(EventListener listener); - - /** - * Unregister a listener registered through {@link #addListener(EventListener)}. The listener will - * no longer receive events from the player. - * - * @param listener The listener to unregister. - * @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead. - */ - @Deprecated - @SuppressWarnings("deprecation") - void removeListener(EventListener listener); - /** * Adds a listener to receive audio offload events. * diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 9902bd0675..94e6c9dbe4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -97,7 +97,6 @@ import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.ExoPlayer.AudioOffloadListener; import com.google.android.exoplayer2.Player.Commands; import com.google.android.exoplayer2.Player.DiscontinuityReason; -import com.google.android.exoplayer2.Player.EventListener; import com.google.android.exoplayer2.Player.Events; import com.google.android.exoplayer2.Player.Listener; import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason; @@ -181,9 +180,9 @@ import java.util.concurrent.TimeoutException; private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener; private final ExoPlayerImplInternal internalPlayer; - @SuppressWarnings("deprecation") // TODO(b/187152483): Merge with non-deprecated listeners. - private final ListenerSet eventListeners; - + private final ListenerSet listeners; + // TODO(b/187152483): Remove this once all events are dispatched via ListenerSet. + private final CopyOnWriteArraySet listenerArraySet; private final CopyOnWriteArraySet audioOffloadListeners; private final Timeline.Period period; private final Timeline.Window window; @@ -198,7 +197,6 @@ import java.util.concurrent.TimeoutException; private final Clock clock; private final ComponentListener componentListener; private final FrameMetadataListener frameMetadataListener; - private final CopyOnWriteArraySet listeners; private final AudioBecomingNoisyManager audioBecomingNoisyManager; private final AudioFocusManager audioFocusManager; private final StreamVolumeManager streamVolumeManager; @@ -284,7 +282,6 @@ import java.util.concurrent.TimeoutException; detachSurfaceTimeoutMs = builder.detachSurfaceTimeoutMs; componentListener = new ComponentListener(); frameMetadataListener = new FrameMetadataListener(); - listeners = new CopyOnWriteArraySet<>(); Handler eventHandler = new Handler(builder.looper); renderers = builder @@ -308,11 +305,12 @@ import java.util.concurrent.TimeoutException; this.applicationLooper = builder.looper; this.clock = builder.clock; this.wrappingPlayer = wrappingPlayer; - eventListeners = + listeners = new ListenerSet<>( applicationLooper, clock, (listener, flags) -> listener.onEvents(wrappingPlayer, new Events(flags))); + listenerArraySet = new CopyOnWriteArraySet<>(); audioOffloadListeners = new CopyOnWriteArraySet<>(); mediaSourceHolderSnapshots = new ArrayList<>(); shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0); @@ -400,9 +398,9 @@ import java.util.concurrent.TimeoutException; currentCues = ImmutableList.of(); throwsWhenUsingWrongThread = true; - addEventListener(analyticsCollector); + listeners.add(analyticsCollector); bandwidthMeter.addEventListener(new Handler(applicationLooper), analyticsCollector); - addEventListener(componentListener); + listeners.add(componentListener); addAudioOffloadListener(componentListener); if (builder.foregroundModeTimeoutMs > 0) { experimentalSetForegroundModeTimeoutMs(builder.foregroundModeTimeoutMs); @@ -478,18 +476,6 @@ import java.util.concurrent.TimeoutException; return clock; } - @SuppressWarnings("deprecation") // Register deprecated EventListener. - public void addEventListener(Player.EventListener eventListener) { - // Don't verify application thread. We allow calls to this method from any thread. - eventListeners.add(eventListener); - } - - @SuppressWarnings("deprecation") // Deregister deprecated EventListener. - public void removeEventListener(Player.EventListener eventListener) { - // Don't verify application thread. We allow calls to this method from any thread. - eventListeners.remove(eventListener); - } - public void addAudioOffloadListener(AudioOffloadListener listener) { // Don't verify application thread. We allow calls to this method from any thread. audioOffloadListeners.add(listener); @@ -795,10 +781,10 @@ import java.util.concurrent.TimeoutException; if (this.repeatMode != repeatMode) { this.repeatMode = repeatMode; internalPlayer.setRepeatMode(repeatMode); - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_REPEAT_MODE_CHANGED, listener -> listener.onRepeatModeChanged(repeatMode)); updateAvailableCommands(); - eventListeners.flushEvents(); + listeners.flushEvents(); } } @@ -812,11 +798,11 @@ import java.util.concurrent.TimeoutException; if (this.shuffleModeEnabled != shuffleModeEnabled) { this.shuffleModeEnabled = shuffleModeEnabled; internalPlayer.setShuffleModeEnabled(shuffleModeEnabled); - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED, listener -> listener.onShuffleModeEnabledChanged(shuffleModeEnabled)); updateAvailableCommands(); - eventListeners.flushEvents(); + listeners.flushEvents(); } } @@ -1018,7 +1004,7 @@ import java.util.concurrent.TimeoutException; audioFocusManager.release(); if (!internalPlayer.release()) { // One of the renderers timed out releasing its resources. - eventListeners.sendEvent( + listeners.sendEvent( Player.EVENT_PLAYER_ERROR, listener -> listener.onPlayerError( @@ -1026,7 +1012,7 @@ import java.util.concurrent.TimeoutException; new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_RELEASE), PlaybackException.ERROR_CODE_TIMEOUT))); } - eventListeners.release(); + listeners.release(); playbackInfoUpdateHandler.removeCallbacksAndMessages(null); bandwidthMeter.removeEventListener(analyticsCollector); playbackInfo = playbackInfo.copyWithPlaybackState(Player.STATE_IDLE); @@ -1206,7 +1192,7 @@ import java.util.concurrent.TimeoutException; return; } trackSelector.setParameters(parameters); - eventListeners.queueEvent( + listeners.queueEvent( EVENT_TRACK_SELECTION_PARAMETERS_CHANGED, listener -> listener.onTrackSelectionParametersChanged(parameters)); } @@ -1226,7 +1212,7 @@ import java.util.concurrent.TimeoutException; return; } mediaMetadata = newMediaMetadata; - eventListeners.sendEvent( + listeners.sendEvent( EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(mediaMetadata)); } @@ -1242,7 +1228,7 @@ import java.util.concurrent.TimeoutException; return; } this.playlistMetadata = playlistMetadata; - eventListeners.sendEvent( + listeners.sendEvent( EVENT_PLAYLIST_METADATA_CHANGED, listener -> listener.onPlaylistMetadataChanged(this.playlistMetadata)); } @@ -1399,7 +1385,7 @@ import java.util.concurrent.TimeoutException; streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage)); analyticsCollector.onAudioAttributesChanged(audioAttributes); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onAudioAttributesChanged(audioAttributes); } } @@ -1437,7 +1423,7 @@ import java.util.concurrent.TimeoutException; sendRendererMessage(TRACK_TYPE_VIDEO, MSG_SET_AUDIO_SESSION_ID, audioSessionId); analyticsCollector.onAudioSessionIdChanged(audioSessionId); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onAudioSessionIdChanged(audioSessionId); } } @@ -1465,7 +1451,7 @@ import java.util.concurrent.TimeoutException; sendVolumeToRenderers(); analyticsCollector.onVolumeChanged(volume); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onVolumeChanged(volume); } } @@ -1597,14 +1583,14 @@ import java.util.concurrent.TimeoutException; // Don't verify application thread. We allow calls to this method from any thread. checkNotNull(listener); listeners.add(listener); - addEventListener(listener); + listenerArraySet.add(listener); } public void removeListener(Listener listener) { // Don't verify application thread. We allow calls to this method from any thread. checkNotNull(listener); listeners.remove(listener); - removeEventListener(listener); + listenerArraySet.remove(listener); } public void setHandleWakeLock(boolean handleWakeLock) { @@ -1805,7 +1791,7 @@ import java.util.concurrent.TimeoutException; mediaMetadata = newMediaMetadata; if (!previousPlaybackInfo.timeline.equals(newPlaybackInfo.timeline)) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_TIMELINE_CHANGED, listener -> listener.onTimelineChanged(newPlaybackInfo.timeline, timelineChangeReason)); } @@ -1814,7 +1800,7 @@ import java.util.concurrent.TimeoutException; getPreviousPositionInfo( positionDiscontinuityReason, previousPlaybackInfo, oldMaskingMediaItemIndex); PositionInfo positionInfo = getPositionInfo(discontinuityWindowStartPositionUs); - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_POSITION_DISCONTINUITY, listener -> { listener.onPositionDiscontinuity(positionDiscontinuityReason); @@ -1824,16 +1810,16 @@ import java.util.concurrent.TimeoutException; } if (mediaItemTransitioned) { @Nullable final MediaItem finalMediaItem = mediaItem; - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_MEDIA_ITEM_TRANSITION, listener -> listener.onMediaItemTransition(finalMediaItem, mediaItemTransitionReason)); } if (previousPlaybackInfo.playbackError != newPlaybackInfo.playbackError) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_PLAYER_ERROR, listener -> listener.onPlayerErrorChanged(newPlaybackInfo.playbackError)); if (newPlaybackInfo.playbackError != null) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_PLAYER_ERROR, listener -> listener.onPlayerError(newPlaybackInfo.playbackError)); } @@ -1842,21 +1828,21 @@ import java.util.concurrent.TimeoutException; trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info); TrackSelectionArray newSelection = new TrackSelectionArray(newPlaybackInfo.trackSelectorResult.selections); - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksChanged(newPlaybackInfo.trackGroups, newSelection)); - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksInfoChanged(newPlaybackInfo.trackSelectorResult.tracksInfo)); } if (metadataChanged) { final MediaMetadata finalMediaMetadata = mediaMetadata; - eventListeners.queueEvent( + listeners.queueEvent( EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(finalMediaMetadata)); } if (previousPlaybackInfo.isLoading != newPlaybackInfo.isLoading) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_IS_LOADING_CHANGED, listener -> { listener.onLoadingChanged(newPlaybackInfo.isLoading); @@ -1865,19 +1851,19 @@ import java.util.concurrent.TimeoutException; } if (previousPlaybackInfo.playbackState != newPlaybackInfo.playbackState || previousPlaybackInfo.playWhenReady != newPlaybackInfo.playWhenReady) { - eventListeners.queueEvent( + listeners.queueEvent( /* eventFlag= */ C.INDEX_UNSET, listener -> listener.onPlayerStateChanged( newPlaybackInfo.playWhenReady, newPlaybackInfo.playbackState)); } if (previousPlaybackInfo.playbackState != newPlaybackInfo.playbackState) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_PLAYBACK_STATE_CHANGED, listener -> listener.onPlaybackStateChanged(newPlaybackInfo.playbackState)); } if (previousPlaybackInfo.playWhenReady != newPlaybackInfo.playWhenReady) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_PLAY_WHEN_READY_CHANGED, listener -> listener.onPlayWhenReadyChanged( @@ -1885,27 +1871,27 @@ import java.util.concurrent.TimeoutException; } if (previousPlaybackInfo.playbackSuppressionReason != newPlaybackInfo.playbackSuppressionReason) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, listener -> listener.onPlaybackSuppressionReasonChanged( newPlaybackInfo.playbackSuppressionReason)); } if (isPlaying(previousPlaybackInfo) != isPlaying(newPlaybackInfo)) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_IS_PLAYING_CHANGED, listener -> listener.onIsPlayingChanged(isPlaying(newPlaybackInfo))); } if (!previousPlaybackInfo.playbackParameters.equals(newPlaybackInfo.playbackParameters)) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_PLAYBACK_PARAMETERS_CHANGED, listener -> listener.onPlaybackParametersChanged(newPlaybackInfo.playbackParameters)); } if (seekProcessed) { - eventListeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); + listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed); } updateAvailableCommands(); - eventListeners.flushEvents(); + listeners.flushEvents(); if (previousPlaybackInfo.offloadSchedulingEnabled != newPlaybackInfo.offloadSchedulingEnabled) { for (AudioOffloadListener listener : audioOffloadListeners) { @@ -2062,7 +2048,7 @@ import java.util.concurrent.TimeoutException; Commands previousAvailableCommands = availableCommands; availableCommands = Util.getAvailableCommands(wrappingPlayer, permanentAvailableCommands); if (!availableCommands.equals(previousAvailableCommands)) { - eventListeners.queueEvent( + listeners.queueEvent( Player.EVENT_AVAILABLE_COMMANDS_CHANGED, listener -> listener.onAvailableCommandsChanged(availableCommands)); } @@ -2482,7 +2468,7 @@ import java.util.concurrent.TimeoutException; surfaceHeight = height; analyticsCollector.onSurfaceSizeChanged(width, height); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onSurfaceSizeChanged(width, height); } } @@ -2496,7 +2482,7 @@ import java.util.concurrent.TimeoutException; private void notifySkipSilenceEnabledChanged() { analyticsCollector.onSkipSilenceEnabledChanged(skipSilenceEnabled); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onSkipSilenceEnabledChanged(skipSilenceEnabled); } } @@ -2638,10 +2624,9 @@ import java.util.concurrent.TimeoutException; } } - // TODO(b/204189802): Remove self-listening to deprecated EventListener. - @SuppressWarnings("deprecation") private final class ComponentListener - implements VideoRendererEventListener, + implements Player.Listener, + VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput, @@ -2651,7 +2636,6 @@ import java.util.concurrent.TimeoutException; AudioFocusManager.PlayerControl, AudioBecomingNoisyManager.EventListener, StreamVolumeManager.Listener, - Player.EventListener, AudioOffloadListener { // VideoRendererEventListener implementation @@ -2686,7 +2670,7 @@ import java.util.concurrent.TimeoutException; ExoPlayerImpl.this.videoSize = videoSize; analyticsCollector.onVideoSizeChanged(videoSize); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onVideoSizeChanged(videoSize); } } @@ -2696,7 +2680,7 @@ import java.util.concurrent.TimeoutException; analyticsCollector.onRenderedFirstFrame(output, renderTimeMs); if (videoOutput == output) { // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onRenderedFirstFrame(); } } @@ -2793,7 +2777,7 @@ import java.util.concurrent.TimeoutException; public void onCues(List cues) { currentCues = cues; // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listeners : listeners) { + for (Listener listeners : listenerArraySet) { listeners.onCues(cues); } } @@ -2805,7 +2789,7 @@ import java.util.concurrent.TimeoutException; analyticsCollector.onMetadata(metadata); ExoPlayerImpl.this.onMetadata(metadata); // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onMetadata(metadata); } } @@ -2901,7 +2885,7 @@ import java.util.concurrent.TimeoutException; if (!deviceInfo.equals(ExoPlayerImpl.this.deviceInfo)) { ExoPlayerImpl.this.deviceInfo = deviceInfo; // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onDeviceInfoChanged(deviceInfo); } } @@ -2910,12 +2894,12 @@ import java.util.concurrent.TimeoutException; @Override public void onStreamVolumeChanged(int streamVolume, boolean streamMuted) { // TODO(internal b/187152483): Events should be dispatched via ListenerSet - for (Listener listener : listeners) { + for (Listener listener : listenerArraySet) { listener.onDeviceVolumeChanged(streamVolume, streamMuted); } } - // Player.EventListener implementation. + // Player.Listener implementation. @Override public void onIsLoadingChanged(boolean isLoading) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 32fd2a0aea..c27b16342e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -608,23 +608,11 @@ public class SimpleExoPlayer extends BasePlayer player.addListener(listener); } - @Deprecated - @Override - public void addListener(Player.EventListener listener) { - player.addEventListener(listener); - } - @Override public void removeListener(Listener listener) { player.removeListener(listener); } - @Deprecated - @Override - public void removeListener(Player.EventListener listener) { - player.removeEventListener(listener); - } - @Override public @State int getPlaybackState() { return player.getPlaybackState(); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java index 9db3cb6a3c..32a053cfcb 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java @@ -20,7 +20,6 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.PlayerMessage; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.SeekParameters; @@ -78,16 +77,6 @@ public class StubExoPlayer extends StubPlayer implements ExoPlayer { throw new UnsupportedOperationException(); } - @Override - public void addListener(Player.EventListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeListener(Player.EventListener listener) { - throw new UnsupportedOperationException(); - } - @Override public void addAudioOffloadListener(AudioOffloadListener listener) { throw new UnsupportedOperationException();