Remove deprecated EventListener

PiperOrigin-RevId: 427133817
This commit is contained in:
tonihei 2022-02-08 09:59:07 +00:00 committed by Ian Baker
parent 287182952d
commit 5cc3ce9a50
8 changed files with 498 additions and 697 deletions

View File

@ -137,7 +137,7 @@ public final class CastPlayer extends BasePlayer {
private final SeekResultCallback seekResultCallback; private final SeekResultCallback seekResultCallback;
// Listeners and notification. // Listeners and notification.
private final ListenerSet<Player.EventListener> listeners; private final ListenerSet<Listener> listeners;
@Nullable private SessionAvailabilityListener sessionAvailabilityListener; @Nullable private SessionAvailabilityListener sessionAvailabilityListener;
// Internal state. // Internal state.
@ -280,41 +280,11 @@ public final class CastPlayer extends BasePlayer {
@Override @Override
public void addListener(Listener listener) { public void addListener(Listener listener) {
EventListener eventListener = listener;
addListener(eventListener);
}
/**
* Registers a listener to receive events from the player.
*
* <p>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); listeners.add(listener);
} }
@Override @Override
public void removeListener(Listener listener) { 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); listeners.remove(listener);
} }
@ -473,7 +443,7 @@ public final class CastPlayer extends BasePlayer {
} }
updateAvailableCommandsAndNotifyIfChanged(); updateAvailableCommandsAndNotifyIfChanged();
} else if (pendingSeekCount == 0) { } else if (pendingSeekCount == 0) {
listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed);
} }
listeners.flushEvents(); listeners.flushEvents();
} }
@ -1477,7 +1447,7 @@ public final class CastPlayer extends BasePlayer {
currentWindowIndex = pendingSeekWindowIndex; currentWindowIndex = pendingSeekWindowIndex;
pendingSeekWindowIndex = C.INDEX_UNSET; pendingSeekWindowIndex = C.INDEX_UNSET;
pendingSeekPositionMs = C.TIME_UNSET; pendingSeekPositionMs = C.TIME_UNSET;
listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed);
} }
} }
} }

View File

@ -819,191 +819,159 @@ public class ForwardingPlayer implements Player {
return player; return player;
} }
@SuppressWarnings("deprecation") // Use of deprecated type for backwards compatibility. private static final class ForwardingListener implements Listener {
private static class ForwardingEventListener implements EventListener {
private final ForwardingPlayer forwardingPlayer; private final ForwardingPlayer forwardingPlayer;
private final EventListener eventListener; private final Listener listener;
private ForwardingEventListener( public ForwardingListener(ForwardingPlayer forwardingPlayer, Listener listener) {
ForwardingPlayer forwardingPlayer, EventListener eventListener) {
this.forwardingPlayer = forwardingPlayer; this.forwardingPlayer = forwardingPlayer;
this.eventListener = eventListener; this.listener = listener;
}
@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();
} }
@Override @Override
public void onEvents(Player player, Events events) { public void onEvents(Player player, Events events) {
// Replace player with forwarding player. // Replace player with forwarding player.
eventListener.onEvents(forwardingPlayer, events); listener.onEvents(forwardingPlayer, events);
} }
@Override @Override
public boolean equals(@Nullable Object o) { public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
if (this == o) { listener.onTimelineChanged(timeline, reason);
return true;
}
if (!(o instanceof ForwardingEventListener)) {
return false;
}
ForwardingEventListener that = (ForwardingEventListener) o;
if (!forwardingPlayer.equals(that.forwardingPlayer)) {
return false;
}
return eventListener.equals(that.eventListener);
} }
@Override @Override
public int hashCode() { public void onMediaItemTransition(
int result = forwardingPlayer.hashCode(); @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {
result = 31 * result + eventListener.hashCode(); listener.onMediaItemTransition(mediaItem, reason);
return result;
} }
}
private static final class ForwardingListener extends ForwardingEventListener @Override
implements Listener { @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) { @Override
super(forwardingPlayer, listener); public void onMediaMetadataChanged(MediaMetadata mediaMetadata) {
this.listener = listener; 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 @Override
@ -1060,5 +1028,27 @@ public class ForwardingPlayer implements Player {
public void onDeviceVolumeChanged(int volume, boolean muted) { public void onDeviceVolumeChanged(int volume, boolean muted) {
listener.onDeviceVolumeChanged(volume, 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;
}
} }
} }

View File

@ -63,343 +63,6 @@ import java.util.List;
*/ */
public interface Player { public interface Player {
/**
* Listener of changes in player state.
*
* <p>All methods have no-op default implementations to allow selective overrides.
*
* <p>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}.
*/
@UnstableApi
@Deprecated
interface EventListener {
/**
* Called when the timeline has been refreshed.
*
* <p>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.
*
* <p>{@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}.
*
* <p>Note that this callback is also called when the playlist becomes non-empty or empty as a
* consequence of a playlist change.
*
* <p>{@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.
*
* <p>{@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.
*/
@UnstableApi
@Deprecated
default void onTracksChanged(
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {}
/**
* Called when the available or selected tracks change.
*
* <p>{@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.
*
* <p>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.
*
* <p>This method may be called multiple times in quick succession.
*
* <p>{@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.
*
* <p>{@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}.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>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.
*
* <p>{@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.
*
* <p>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.
*
* <p>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.
*
* <p>{@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).
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>{@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.
*
* <p>State changes and events that happen within one {@link Looper} message queue iteration are
* reported together and only after all individual callbacks were triggered.
*
* <p>Only state changes represented by {@link Event events} are reported through this method.
*
* <p>Listeners should prefer this method over individual callbacks in the following cases:
*
* <ul>
* <li>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)}).
* <li>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)}).
* <li>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.
* <li>They are interested in events that logically happened together (e.g {@link
* #onPlaybackStateChanged(int)} to {@link #STATE_BUFFERING} because of {@link
* #onMediaItemTransition(MediaItem, int)}).
* </ul>
*
* @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}. */ /** A set of {@link Event events}. */
final class Events { final class Events {
@ -939,62 +602,332 @@ public interface Player {
* *
* <p>All methods have no-op default implementations to allow selective overrides. * <p>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.
*
* <p>State changes and events that happen within one {@link Looper} message queue iteration are
* reported together and only after all individual callbacks were triggered.
*
* <p>Only state changes represented by {@link Event events} are reported through this method.
*
* <p>Listeners should prefer this method over individual callbacks in the following cases:
*
* <ul>
* <li>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)}).
* <li>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)}).
* <li>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.
* <li>They are interested in events that logically happened together (e.g {@link
* #onPlaybackStateChanged(int)} to {@link #STATE_BUFFERING} because of {@link
* #onMediaItemTransition(MediaItem, int)}).
* </ul>
*
* @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.
*
* <p>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.
*
* <p>{@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) {} 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}.
*
* <p>Note that this callback is also called when the playlist becomes non-empty or empty as a
* consequence of a playlist change.
*
* <p>{@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( default void onMediaItemTransition(
@Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {} @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {}
@Override /**
* Called when the available or selected tracks change.
*
* <p>{@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.
*/
@UnstableApi
@Deprecated
default void onTracksChanged(
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {}
/**
* Called when the available or selected tracks change.
*
* <p>{@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) {} default void onTracksInfoChanged(TracksInfo tracksInfo) {}
@Override /**
* Called when the combined {@link MediaMetadata} changes.
*
* <p>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.
*
* <p>This method may be called multiple times in quick succession.
*
* <p>{@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.
*
* <p>{@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) {} default void onIsLoadingChanged(boolean isLoading) {}
@Override /** @deprecated Use {@link #onIsLoadingChanged(boolean)} instead. */
@Deprecated
@UnstableApi
default void onLoadingChanged(boolean isLoading) {}
/**
* Called when the value returned from {@link #isCommandAvailable(int)} changes for at least one
* {@link Command}.
*
* <p>{@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) {} default void onAvailableCommandsChanged(Commands availableCommands) {}
@Override /**
* Called when the value returned from {@link #getTrackSelectionParameters()} changes.
*
* <p>{@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
@UnstableApi
default void onPlayerStateChanged(boolean playWhenReady, @State int playbackState) {}
/**
* Called when the value returned from {@link #getPlaybackState()} changes.
*
* <p>{@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) {} default void onPlaybackStateChanged(@State int playbackState) {}
@Override /**
* Called when the value returned from {@link #getPlayWhenReady()} changes.
*
* <p>{@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( default void onPlayWhenReadyChanged(
boolean playWhenReady, @PlayWhenReadyChangeReason int reason) {} boolean playWhenReady, @PlayWhenReadyChangeReason int reason) {}
@Override /**
* Called when the value returned from {@link #getPlaybackSuppressionReason()} changes.
*
* <p>{@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( default void onPlaybackSuppressionReasonChanged(
@PlaybackSuppressionReason int playbackSuppressionReason) {} @PlaybackSuppressionReason int playbackSuppressionReason) {}
@Override /**
* Called when the value of {@link #isPlaying()} changes.
*
* <p>{@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) {} default void onIsPlayingChanged(boolean isPlaying) {}
@Override /**
* Called when the value of {@link #getRepeatMode()} changes.
*
* <p>{@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) {} default void onRepeatModeChanged(@RepeatMode int repeatMode) {}
@Override /**
* Called when the value of {@link #getShuffleModeEnabled()} changes.
*
* <p>{@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) {} 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.
*
* <p>{@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.
*
* <p>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) {} default void onPlayerError(PlaybackException error) {}
@Override /**
* Called when the {@link PlaybackException} returned by {@link #getPlayerError()} changes.
*
* <p>{@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.
*
* <p>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) {} default void onPlayerErrorChanged(@Nullable PlaybackException error) {}
@Override /**
* @deprecated Use {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} instead.
*/
@Deprecated
@UnstableApi
default void onPositionDiscontinuity(@DiscontinuityReason int reason) {}
/**
* Called when a position discontinuity occurs.
*
* <p>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.
*
* <p>{@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( default void onPositionDiscontinuity(
PositionInfo oldPosition, PositionInfo newPosition, @DiscontinuityReason int reason) {} 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).
*
* <p>{@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) {} default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
@Override /**
* Called when the value of {@link #getSeekBackIncrement()} changes.
*
* <p>{@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.
*
* <p>{@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) {} default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {}
@Override /**
default void onSeekBackIncrementChanged(long seekBackIncrementMs) {} * Called when the value of {@link #getMaxSeekToPreviousPosition()} changes.
*
* <p>{@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
@UnstableApi
default void onSeekProcessed() {}
/** /**
* Called when the audio session ID changes. * Called when the audio session ID changes.
@ -1031,9 +964,6 @@ public interface Player {
/** Called when the device volume or mute state changes. */ /** Called when the device volume or mute state changes. */
default void onDeviceVolumeChanged(int volume, boolean muted) {} 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. * Called each time there's a change in the size of the video being rendered.
* *
@ -1075,12 +1005,6 @@ public interface Player {
*/ */
@UnstableApi @UnstableApi
default void onMetadata(Metadata metadata) {} default void onMetadata(Metadata metadata) {}
@Override
default void onMediaMetadataChanged(MediaMetadata mediaMetadata) {}
@Override
default void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {}
} }
/** /**

View File

@ -115,21 +115,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<Method> 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 @Test
public void forwardingListener_overridesAllListenerMethods() throws Exception { public void forwardingListener_overridesAllListenerMethods() throws Exception {
// Check with reflection that ForwardingListener overrides all Listener methods. // Check with reflection that ForwardingListener overrides all Listener methods.

View File

@ -1081,32 +1081,6 @@ public interface ExoPlayer extends Player {
@Deprecated @Deprecated
DeviceComponent getDeviceComponent(); DeviceComponent getDeviceComponent();
/**
* Registers a listener to receive events from the player.
*
* <p>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.
*/
@UnstableApi
@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.
*/
@UnstableApi
@Deprecated
@SuppressWarnings("deprecation")
void removeListener(EventListener listener);
/** /**
* Adds a listener to receive audio offload events. * Adds a listener to receive audio offload events.
* *

View File

@ -109,7 +109,6 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Player.Commands; import androidx.media3.common.Player.Commands;
import androidx.media3.common.Player.DiscontinuityReason; import androidx.media3.common.Player.DiscontinuityReason;
import androidx.media3.common.Player.EventListener;
import androidx.media3.common.Player.Events; import androidx.media3.common.Player.Events;
import androidx.media3.common.Player.Listener; import androidx.media3.common.Player.Listener;
import androidx.media3.common.Player.PlayWhenReadyChangeReason; import androidx.media3.common.Player.PlayWhenReadyChangeReason;
@ -191,9 +190,9 @@ import java.util.concurrent.TimeoutException;
private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener; private final ExoPlayerImplInternal.PlaybackInfoUpdateListener playbackInfoUpdateListener;
private final ExoPlayerImplInternal internalPlayer; private final ExoPlayerImplInternal internalPlayer;
@SuppressWarnings("deprecation") // TODO(b/187152483): Merge with non-deprecated listeners. private final ListenerSet<Listener> listeners;
private final ListenerSet<Player.EventListener> eventListeners; // TODO(b/187152483): Remove this once all events are dispatched via ListenerSet.
private final CopyOnWriteArraySet<Listener> listenerArraySet;
private final CopyOnWriteArraySet<AudioOffloadListener> audioOffloadListeners; private final CopyOnWriteArraySet<AudioOffloadListener> audioOffloadListeners;
private final Timeline.Period period; private final Timeline.Period period;
private final Timeline.Window window; private final Timeline.Window window;
@ -208,7 +207,6 @@ import java.util.concurrent.TimeoutException;
private final Clock clock; private final Clock clock;
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final FrameMetadataListener frameMetadataListener; private final FrameMetadataListener frameMetadataListener;
private final CopyOnWriteArraySet<Listener> listeners;
private final AudioBecomingNoisyManager audioBecomingNoisyManager; private final AudioBecomingNoisyManager audioBecomingNoisyManager;
private final AudioFocusManager audioFocusManager; private final AudioFocusManager audioFocusManager;
private final StreamVolumeManager streamVolumeManager; private final StreamVolumeManager streamVolumeManager;
@ -294,7 +292,6 @@ import java.util.concurrent.TimeoutException;
detachSurfaceTimeoutMs = builder.detachSurfaceTimeoutMs; detachSurfaceTimeoutMs = builder.detachSurfaceTimeoutMs;
componentListener = new ComponentListener(); componentListener = new ComponentListener();
frameMetadataListener = new FrameMetadataListener(); frameMetadataListener = new FrameMetadataListener();
listeners = new CopyOnWriteArraySet<>();
Handler eventHandler = new Handler(builder.looper); Handler eventHandler = new Handler(builder.looper);
renderers = renderers =
builder builder
@ -318,11 +315,12 @@ import java.util.concurrent.TimeoutException;
this.applicationLooper = builder.looper; this.applicationLooper = builder.looper;
this.clock = builder.clock; this.clock = builder.clock;
this.wrappingPlayer = wrappingPlayer; this.wrappingPlayer = wrappingPlayer;
eventListeners = listeners =
new ListenerSet<>( new ListenerSet<>(
applicationLooper, applicationLooper,
clock, clock,
(listener, flags) -> listener.onEvents(wrappingPlayer, new Events(flags))); (listener, flags) -> listener.onEvents(wrappingPlayer, new Events(flags)));
listenerArraySet = new CopyOnWriteArraySet<>();
audioOffloadListeners = new CopyOnWriteArraySet<>(); audioOffloadListeners = new CopyOnWriteArraySet<>();
mediaSourceHolderSnapshots = new ArrayList<>(); mediaSourceHolderSnapshots = new ArrayList<>();
shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0); shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0);
@ -410,9 +408,9 @@ import java.util.concurrent.TimeoutException;
currentCues = ImmutableList.of(); currentCues = ImmutableList.of();
throwsWhenUsingWrongThread = true; throwsWhenUsingWrongThread = true;
addEventListener(analyticsCollector); listeners.add(analyticsCollector);
bandwidthMeter.addEventListener(new Handler(applicationLooper), analyticsCollector); bandwidthMeter.addEventListener(new Handler(applicationLooper), analyticsCollector);
addEventListener(componentListener); listeners.add(componentListener);
addAudioOffloadListener(componentListener); addAudioOffloadListener(componentListener);
if (builder.foregroundModeTimeoutMs > 0) { if (builder.foregroundModeTimeoutMs > 0) {
experimentalSetForegroundModeTimeoutMs(builder.foregroundModeTimeoutMs); experimentalSetForegroundModeTimeoutMs(builder.foregroundModeTimeoutMs);
@ -488,18 +486,6 @@ import java.util.concurrent.TimeoutException;
return clock; 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) { public void addAudioOffloadListener(AudioOffloadListener listener) {
// Don't verify application thread. We allow calls to this method from any thread. // Don't verify application thread. We allow calls to this method from any thread.
audioOffloadListeners.add(listener); audioOffloadListeners.add(listener);
@ -805,10 +791,10 @@ import java.util.concurrent.TimeoutException;
if (this.repeatMode != repeatMode) { if (this.repeatMode != repeatMode) {
this.repeatMode = repeatMode; this.repeatMode = repeatMode;
internalPlayer.setRepeatMode(repeatMode); internalPlayer.setRepeatMode(repeatMode);
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_REPEAT_MODE_CHANGED, listener -> listener.onRepeatModeChanged(repeatMode)); Player.EVENT_REPEAT_MODE_CHANGED, listener -> listener.onRepeatModeChanged(repeatMode));
updateAvailableCommands(); updateAvailableCommands();
eventListeners.flushEvents(); listeners.flushEvents();
} }
} }
@ -822,11 +808,11 @@ import java.util.concurrent.TimeoutException;
if (this.shuffleModeEnabled != shuffleModeEnabled) { if (this.shuffleModeEnabled != shuffleModeEnabled) {
this.shuffleModeEnabled = shuffleModeEnabled; this.shuffleModeEnabled = shuffleModeEnabled;
internalPlayer.setShuffleModeEnabled(shuffleModeEnabled); internalPlayer.setShuffleModeEnabled(shuffleModeEnabled);
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED, Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
listener -> listener.onShuffleModeEnabledChanged(shuffleModeEnabled)); listener -> listener.onShuffleModeEnabledChanged(shuffleModeEnabled));
updateAvailableCommands(); updateAvailableCommands();
eventListeners.flushEvents(); listeners.flushEvents();
} }
} }
@ -1028,7 +1014,7 @@ import java.util.concurrent.TimeoutException;
audioFocusManager.release(); audioFocusManager.release();
if (!internalPlayer.release()) { if (!internalPlayer.release()) {
// One of the renderers timed out releasing its resources. // One of the renderers timed out releasing its resources.
eventListeners.sendEvent( listeners.sendEvent(
Player.EVENT_PLAYER_ERROR, Player.EVENT_PLAYER_ERROR,
listener -> listener ->
listener.onPlayerError( listener.onPlayerError(
@ -1036,7 +1022,7 @@ import java.util.concurrent.TimeoutException;
new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_RELEASE), new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_RELEASE),
PlaybackException.ERROR_CODE_TIMEOUT))); PlaybackException.ERROR_CODE_TIMEOUT)));
} }
eventListeners.release(); listeners.release();
playbackInfoUpdateHandler.removeCallbacksAndMessages(null); playbackInfoUpdateHandler.removeCallbacksAndMessages(null);
bandwidthMeter.removeEventListener(analyticsCollector); bandwidthMeter.removeEventListener(analyticsCollector);
playbackInfo = playbackInfo.copyWithPlaybackState(Player.STATE_IDLE); playbackInfo = playbackInfo.copyWithPlaybackState(Player.STATE_IDLE);
@ -1216,7 +1202,7 @@ import java.util.concurrent.TimeoutException;
return; return;
} }
trackSelector.setParameters(parameters); trackSelector.setParameters(parameters);
eventListeners.queueEvent( listeners.queueEvent(
EVENT_TRACK_SELECTION_PARAMETERS_CHANGED, EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
listener -> listener.onTrackSelectionParametersChanged(parameters)); listener -> listener.onTrackSelectionParametersChanged(parameters));
} }
@ -1236,7 +1222,7 @@ import java.util.concurrent.TimeoutException;
return; return;
} }
mediaMetadata = newMediaMetadata; mediaMetadata = newMediaMetadata;
eventListeners.sendEvent( listeners.sendEvent(
EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(mediaMetadata)); EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(mediaMetadata));
} }
@ -1252,7 +1238,7 @@ import java.util.concurrent.TimeoutException;
return; return;
} }
this.playlistMetadata = playlistMetadata; this.playlistMetadata = playlistMetadata;
eventListeners.sendEvent( listeners.sendEvent(
EVENT_PLAYLIST_METADATA_CHANGED, EVENT_PLAYLIST_METADATA_CHANGED,
listener -> listener.onPlaylistMetadataChanged(this.playlistMetadata)); listener -> listener.onPlaylistMetadataChanged(this.playlistMetadata));
} }
@ -1409,7 +1395,7 @@ import java.util.concurrent.TimeoutException;
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage)); streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage));
analyticsCollector.onAudioAttributesChanged(audioAttributes); analyticsCollector.onAudioAttributesChanged(audioAttributes);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onAudioAttributesChanged(audioAttributes); listener.onAudioAttributesChanged(audioAttributes);
} }
} }
@ -1447,7 +1433,7 @@ import java.util.concurrent.TimeoutException;
sendRendererMessage(TRACK_TYPE_VIDEO, MSG_SET_AUDIO_SESSION_ID, audioSessionId); sendRendererMessage(TRACK_TYPE_VIDEO, MSG_SET_AUDIO_SESSION_ID, audioSessionId);
analyticsCollector.onAudioSessionIdChanged(audioSessionId); analyticsCollector.onAudioSessionIdChanged(audioSessionId);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onAudioSessionIdChanged(audioSessionId); listener.onAudioSessionIdChanged(audioSessionId);
} }
} }
@ -1475,7 +1461,7 @@ import java.util.concurrent.TimeoutException;
sendVolumeToRenderers(); sendVolumeToRenderers();
analyticsCollector.onVolumeChanged(volume); analyticsCollector.onVolumeChanged(volume);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onVolumeChanged(volume); listener.onVolumeChanged(volume);
} }
} }
@ -1607,14 +1593,14 @@ import java.util.concurrent.TimeoutException;
// Don't verify application thread. We allow calls to this method from any thread. // Don't verify application thread. We allow calls to this method from any thread.
checkNotNull(listener); checkNotNull(listener);
listeners.add(listener); listeners.add(listener);
addEventListener(listener); listenerArraySet.add(listener);
} }
public void removeListener(Listener listener) { public void removeListener(Listener listener) {
// Don't verify application thread. We allow calls to this method from any thread. // Don't verify application thread. We allow calls to this method from any thread.
checkNotNull(listener); checkNotNull(listener);
listeners.remove(listener); listeners.remove(listener);
removeEventListener(listener); listenerArraySet.remove(listener);
} }
public void setHandleWakeLock(boolean handleWakeLock) { public void setHandleWakeLock(boolean handleWakeLock) {
@ -1815,7 +1801,7 @@ import java.util.concurrent.TimeoutException;
mediaMetadata = newMediaMetadata; mediaMetadata = newMediaMetadata;
if (!previousPlaybackInfo.timeline.equals(newPlaybackInfo.timeline)) { if (!previousPlaybackInfo.timeline.equals(newPlaybackInfo.timeline)) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_TIMELINE_CHANGED, Player.EVENT_TIMELINE_CHANGED,
listener -> listener.onTimelineChanged(newPlaybackInfo.timeline, timelineChangeReason)); listener -> listener.onTimelineChanged(newPlaybackInfo.timeline, timelineChangeReason));
} }
@ -1824,7 +1810,7 @@ import java.util.concurrent.TimeoutException;
getPreviousPositionInfo( getPreviousPositionInfo(
positionDiscontinuityReason, previousPlaybackInfo, oldMaskingMediaItemIndex); positionDiscontinuityReason, previousPlaybackInfo, oldMaskingMediaItemIndex);
PositionInfo positionInfo = getPositionInfo(discontinuityWindowStartPositionUs); PositionInfo positionInfo = getPositionInfo(discontinuityWindowStartPositionUs);
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_POSITION_DISCONTINUITY, Player.EVENT_POSITION_DISCONTINUITY,
listener -> { listener -> {
listener.onPositionDiscontinuity(positionDiscontinuityReason); listener.onPositionDiscontinuity(positionDiscontinuityReason);
@ -1834,16 +1820,16 @@ import java.util.concurrent.TimeoutException;
} }
if (mediaItemTransitioned) { if (mediaItemTransitioned) {
@Nullable final MediaItem finalMediaItem = mediaItem; @Nullable final MediaItem finalMediaItem = mediaItem;
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_MEDIA_ITEM_TRANSITION, Player.EVENT_MEDIA_ITEM_TRANSITION,
listener -> listener.onMediaItemTransition(finalMediaItem, mediaItemTransitionReason)); listener -> listener.onMediaItemTransition(finalMediaItem, mediaItemTransitionReason));
} }
if (previousPlaybackInfo.playbackError != newPlaybackInfo.playbackError) { if (previousPlaybackInfo.playbackError != newPlaybackInfo.playbackError) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_PLAYER_ERROR, Player.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerErrorChanged(newPlaybackInfo.playbackError)); listener -> listener.onPlayerErrorChanged(newPlaybackInfo.playbackError));
if (newPlaybackInfo.playbackError != null) { if (newPlaybackInfo.playbackError != null) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_PLAYER_ERROR, Player.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerError(newPlaybackInfo.playbackError)); listener -> listener.onPlayerError(newPlaybackInfo.playbackError));
} }
@ -1852,21 +1838,21 @@ import java.util.concurrent.TimeoutException;
trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info); trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info);
TrackSelectionArray newSelection = TrackSelectionArray newSelection =
new TrackSelectionArray(newPlaybackInfo.trackSelectorResult.selections); new TrackSelectionArray(newPlaybackInfo.trackSelectorResult.selections);
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_TRACKS_CHANGED, Player.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksChanged(newPlaybackInfo.trackGroups, newSelection)); listener -> listener.onTracksChanged(newPlaybackInfo.trackGroups, newSelection));
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_TRACKS_CHANGED, Player.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksInfoChanged(newPlaybackInfo.trackSelectorResult.tracksInfo)); listener -> listener.onTracksInfoChanged(newPlaybackInfo.trackSelectorResult.tracksInfo));
} }
if (metadataChanged) { if (metadataChanged) {
final MediaMetadata finalMediaMetadata = mediaMetadata; final MediaMetadata finalMediaMetadata = mediaMetadata;
eventListeners.queueEvent( listeners.queueEvent(
EVENT_MEDIA_METADATA_CHANGED, EVENT_MEDIA_METADATA_CHANGED,
listener -> listener.onMediaMetadataChanged(finalMediaMetadata)); listener -> listener.onMediaMetadataChanged(finalMediaMetadata));
} }
if (previousPlaybackInfo.isLoading != newPlaybackInfo.isLoading) { if (previousPlaybackInfo.isLoading != newPlaybackInfo.isLoading) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_IS_LOADING_CHANGED, Player.EVENT_IS_LOADING_CHANGED,
listener -> { listener -> {
listener.onLoadingChanged(newPlaybackInfo.isLoading); listener.onLoadingChanged(newPlaybackInfo.isLoading);
@ -1875,19 +1861,19 @@ import java.util.concurrent.TimeoutException;
} }
if (previousPlaybackInfo.playbackState != newPlaybackInfo.playbackState if (previousPlaybackInfo.playbackState != newPlaybackInfo.playbackState
|| previousPlaybackInfo.playWhenReady != newPlaybackInfo.playWhenReady) { || previousPlaybackInfo.playWhenReady != newPlaybackInfo.playWhenReady) {
eventListeners.queueEvent( listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, /* eventFlag= */ C.INDEX_UNSET,
listener -> listener ->
listener.onPlayerStateChanged( listener.onPlayerStateChanged(
newPlaybackInfo.playWhenReady, newPlaybackInfo.playbackState)); newPlaybackInfo.playWhenReady, newPlaybackInfo.playbackState));
} }
if (previousPlaybackInfo.playbackState != newPlaybackInfo.playbackState) { if (previousPlaybackInfo.playbackState != newPlaybackInfo.playbackState) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_PLAYBACK_STATE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED,
listener -> listener.onPlaybackStateChanged(newPlaybackInfo.playbackState)); listener -> listener.onPlaybackStateChanged(newPlaybackInfo.playbackState));
} }
if (previousPlaybackInfo.playWhenReady != newPlaybackInfo.playWhenReady) { if (previousPlaybackInfo.playWhenReady != newPlaybackInfo.playWhenReady) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_PLAY_WHEN_READY_CHANGED, Player.EVENT_PLAY_WHEN_READY_CHANGED,
listener -> listener ->
listener.onPlayWhenReadyChanged( listener.onPlayWhenReadyChanged(
@ -1895,27 +1881,27 @@ import java.util.concurrent.TimeoutException;
} }
if (previousPlaybackInfo.playbackSuppressionReason if (previousPlaybackInfo.playbackSuppressionReason
!= newPlaybackInfo.playbackSuppressionReason) { != newPlaybackInfo.playbackSuppressionReason) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
listener -> listener ->
listener.onPlaybackSuppressionReasonChanged( listener.onPlaybackSuppressionReasonChanged(
newPlaybackInfo.playbackSuppressionReason)); newPlaybackInfo.playbackSuppressionReason));
} }
if (isPlaying(previousPlaybackInfo) != isPlaying(newPlaybackInfo)) { if (isPlaying(previousPlaybackInfo) != isPlaying(newPlaybackInfo)) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_IS_PLAYING_CHANGED, Player.EVENT_IS_PLAYING_CHANGED,
listener -> listener.onIsPlayingChanged(isPlaying(newPlaybackInfo))); listener -> listener.onIsPlayingChanged(isPlaying(newPlaybackInfo)));
} }
if (!previousPlaybackInfo.playbackParameters.equals(newPlaybackInfo.playbackParameters)) { if (!previousPlaybackInfo.playbackParameters.equals(newPlaybackInfo.playbackParameters)) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_PLAYBACK_PARAMETERS_CHANGED, Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
listener -> listener.onPlaybackParametersChanged(newPlaybackInfo.playbackParameters)); listener -> listener.onPlaybackParametersChanged(newPlaybackInfo.playbackParameters));
} }
if (seekProcessed) { if (seekProcessed) {
eventListeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed);
} }
updateAvailableCommands(); updateAvailableCommands();
eventListeners.flushEvents(); listeners.flushEvents();
if (previousPlaybackInfo.offloadSchedulingEnabled != newPlaybackInfo.offloadSchedulingEnabled) { if (previousPlaybackInfo.offloadSchedulingEnabled != newPlaybackInfo.offloadSchedulingEnabled) {
for (AudioOffloadListener listener : audioOffloadListeners) { for (AudioOffloadListener listener : audioOffloadListeners) {
@ -2072,7 +2058,7 @@ import java.util.concurrent.TimeoutException;
Commands previousAvailableCommands = availableCommands; Commands previousAvailableCommands = availableCommands;
availableCommands = Util.getAvailableCommands(wrappingPlayer, permanentAvailableCommands); availableCommands = Util.getAvailableCommands(wrappingPlayer, permanentAvailableCommands);
if (!availableCommands.equals(previousAvailableCommands)) { if (!availableCommands.equals(previousAvailableCommands)) {
eventListeners.queueEvent( listeners.queueEvent(
Player.EVENT_AVAILABLE_COMMANDS_CHANGED, Player.EVENT_AVAILABLE_COMMANDS_CHANGED,
listener -> listener.onAvailableCommandsChanged(availableCommands)); listener -> listener.onAvailableCommandsChanged(availableCommands));
} }
@ -2492,7 +2478,7 @@ import java.util.concurrent.TimeoutException;
surfaceHeight = height; surfaceHeight = height;
analyticsCollector.onSurfaceSizeChanged(width, height); analyticsCollector.onSurfaceSizeChanged(width, height);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onSurfaceSizeChanged(width, height); listener.onSurfaceSizeChanged(width, height);
} }
} }
@ -2506,7 +2492,7 @@ import java.util.concurrent.TimeoutException;
private void notifySkipSilenceEnabledChanged() { private void notifySkipSilenceEnabledChanged() {
analyticsCollector.onSkipSilenceEnabledChanged(skipSilenceEnabled); analyticsCollector.onSkipSilenceEnabledChanged(skipSilenceEnabled);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onSkipSilenceEnabledChanged(skipSilenceEnabled); listener.onSkipSilenceEnabledChanged(skipSilenceEnabled);
} }
} }
@ -2648,10 +2634,9 @@ import java.util.concurrent.TimeoutException;
} }
} }
// TODO(b/204189802): Remove self-listening to deprecated EventListener.
@SuppressWarnings("deprecation")
private final class ComponentListener private final class ComponentListener
implements VideoRendererEventListener, implements Player.Listener,
VideoRendererEventListener,
AudioRendererEventListener, AudioRendererEventListener,
TextOutput, TextOutput,
MetadataOutput, MetadataOutput,
@ -2661,7 +2646,6 @@ import java.util.concurrent.TimeoutException;
AudioFocusManager.PlayerControl, AudioFocusManager.PlayerControl,
AudioBecomingNoisyManager.EventListener, AudioBecomingNoisyManager.EventListener,
StreamVolumeManager.Listener, StreamVolumeManager.Listener,
Player.EventListener,
AudioOffloadListener { AudioOffloadListener {
// VideoRendererEventListener implementation // VideoRendererEventListener implementation
@ -2696,7 +2680,7 @@ import java.util.concurrent.TimeoutException;
ExoPlayerImpl.this.videoSize = videoSize; ExoPlayerImpl.this.videoSize = videoSize;
analyticsCollector.onVideoSizeChanged(videoSize); analyticsCollector.onVideoSizeChanged(videoSize);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onVideoSizeChanged(videoSize); listener.onVideoSizeChanged(videoSize);
} }
} }
@ -2706,7 +2690,7 @@ import java.util.concurrent.TimeoutException;
analyticsCollector.onRenderedFirstFrame(output, renderTimeMs); analyticsCollector.onRenderedFirstFrame(output, renderTimeMs);
if (videoOutput == output) { if (videoOutput == output) {
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onRenderedFirstFrame(); listener.onRenderedFirstFrame();
} }
} }
@ -2803,7 +2787,7 @@ import java.util.concurrent.TimeoutException;
public void onCues(List<Cue> cues) { public void onCues(List<Cue> cues) {
currentCues = cues; currentCues = cues;
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listeners : listeners) { for (Listener listeners : listenerArraySet) {
listeners.onCues(cues); listeners.onCues(cues);
} }
} }
@ -2815,7 +2799,7 @@ import java.util.concurrent.TimeoutException;
analyticsCollector.onMetadata(metadata); analyticsCollector.onMetadata(metadata);
ExoPlayerImpl.this.onMetadata(metadata); ExoPlayerImpl.this.onMetadata(metadata);
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onMetadata(metadata); listener.onMetadata(metadata);
} }
} }
@ -2911,7 +2895,7 @@ import java.util.concurrent.TimeoutException;
if (!deviceInfo.equals(ExoPlayerImpl.this.deviceInfo)) { if (!deviceInfo.equals(ExoPlayerImpl.this.deviceInfo)) {
ExoPlayerImpl.this.deviceInfo = deviceInfo; ExoPlayerImpl.this.deviceInfo = deviceInfo;
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onDeviceInfoChanged(deviceInfo); listener.onDeviceInfoChanged(deviceInfo);
} }
} }
@ -2920,12 +2904,12 @@ import java.util.concurrent.TimeoutException;
@Override @Override
public void onStreamVolumeChanged(int streamVolume, boolean streamMuted) { public void onStreamVolumeChanged(int streamVolume, boolean streamMuted) {
// TODO(internal b/187152483): Events should be dispatched via ListenerSet // TODO(internal b/187152483): Events should be dispatched via ListenerSet
for (Listener listener : listeners) { for (Listener listener : listenerArraySet) {
listener.onDeviceVolumeChanged(streamVolume, streamMuted); listener.onDeviceVolumeChanged(streamVolume, streamMuted);
} }
} }
// Player.EventListener implementation. // Player.Listener implementation.
@Override @Override
public void onIsLoadingChanged(boolean isLoading) { public void onIsLoadingChanged(boolean isLoading) {

View File

@ -33,7 +33,6 @@ import androidx.media3.common.Format;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaMetadata; import androidx.media3.common.MediaMetadata;
import androidx.media3.common.PlaybackParameters; import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.PriorityTaskManager; import androidx.media3.common.PriorityTaskManager;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroupArray; import androidx.media3.common.TrackGroupArray;
@ -672,26 +671,12 @@ public class SimpleExoPlayer extends BasePlayer
player.addListener(listener); player.addListener(listener);
} }
@Deprecated
@Override
public void addListener(Player.EventListener listener) {
blockUntilConstructorFinished();
player.addEventListener(listener);
}
@Override @Override
public void removeListener(Listener listener) { public void removeListener(Listener listener) {
blockUntilConstructorFinished(); blockUntilConstructorFinished();
player.removeListener(listener); player.removeListener(listener);
} }
@Deprecated
@Override
public void removeListener(Player.EventListener listener) {
blockUntilConstructorFinished();
player.removeEventListener(listener);
}
@Override @Override
public @State int getPlaybackState() { public @State int getPlaybackState() {
blockUntilConstructorFinished(); blockUntilConstructorFinished();

View File

@ -20,7 +20,6 @@ import androidx.annotation.Nullable;
import androidx.media3.common.AudioAttributes; import androidx.media3.common.AudioAttributes;
import androidx.media3.common.AuxEffectInfo; import androidx.media3.common.AuxEffectInfo;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.Player;
import androidx.media3.common.PriorityTaskManager; import androidx.media3.common.PriorityTaskManager;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -80,16 +79,6 @@ public class StubExoPlayer extends StubPlayer implements ExoPlayer {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public void addListener(Player.EventListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void removeListener(Player.EventListener listener) {
throw new UnsupportedOperationException();
}
@Override @Override
public void addAudioOffloadListener(AudioOffloadListener listener) { public void addAudioOffloadListener(AudioOffloadListener listener) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();