mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Create actual copy of listener list instead of just copying the reference.
Forwarding the listeners to the notification update is meant to ensure we only notify the listeners which were registered at the time the event happened However, we currently just copy the reference to the actual list instead of doing a deep copy of the listeners. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=222227735
This commit is contained in:
parent
b7ab570094
commit
55cc0df558
1 changed files with 77 additions and 35 deletions
|
|
@ -37,8 +37,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
|
|
||||||
/** An {@link ExoPlayer} implementation. Instances can be obtained from {@link ExoPlayerFactory}. */
|
/** An {@link ExoPlayer} implementation. Instances can be obtained from {@link ExoPlayerFactory}. */
|
||||||
/* package */ final class ExoPlayerImpl extends BasePlayer implements ExoPlayer {
|
/* package */ final class ExoPlayerImpl extends BasePlayer implements ExoPlayer {
|
||||||
|
|
@ -59,7 +58,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
private final Handler eventHandler;
|
private final Handler eventHandler;
|
||||||
private final ExoPlayerImplInternal internalPlayer;
|
private final ExoPlayerImplInternal internalPlayer;
|
||||||
private final Handler internalPlayerHandler;
|
private final Handler internalPlayerHandler;
|
||||||
private final CopyOnWriteArraySet<Player.EventListener> listeners;
|
private final CopyOnWriteArrayList<ListenerHolder> listeners;
|
||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
private final ArrayDeque<Runnable> pendingListenerNotifications;
|
private final ArrayDeque<Runnable> pendingListenerNotifications;
|
||||||
|
|
||||||
|
|
@ -111,7 +110,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
this.playWhenReady = false;
|
this.playWhenReady = false;
|
||||||
this.repeatMode = Player.REPEAT_MODE_OFF;
|
this.repeatMode = Player.REPEAT_MODE_OFF;
|
||||||
this.shuffleModeEnabled = false;
|
this.shuffleModeEnabled = false;
|
||||||
this.listeners = new CopyOnWriteArraySet<>();
|
this.listeners = new CopyOnWriteArrayList<>();
|
||||||
emptyTrackSelectorResult =
|
emptyTrackSelectorResult =
|
||||||
new TrackSelectorResult(
|
new TrackSelectorResult(
|
||||||
new RendererConfiguration[renderers.length],
|
new RendererConfiguration[renderers.length],
|
||||||
|
|
@ -172,12 +171,17 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(Player.EventListener listener) {
|
public void addListener(Player.EventListener listener) {
|
||||||
listeners.add(listener);
|
listeners.addIfAbsent(new ListenerHolder(listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeListener(Player.EventListener listener) {
|
public void removeListener(Player.EventListener listener) {
|
||||||
listeners.remove(listener);
|
for (ListenerHolder listenerHolder : listeners) {
|
||||||
|
if (listenerHolder.listener.equals(listener)) {
|
||||||
|
listenerHolder.release();
|
||||||
|
listeners.remove(listenerHolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -694,12 +698,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyListeners(ListenerInvocation listenerInvocation) {
|
private void notifyListeners(ListenerInvocation listenerInvocation) {
|
||||||
notifyListeners(
|
CopyOnWriteArrayList<ListenerHolder> listenerSnapshot = new CopyOnWriteArrayList<>(listeners);
|
||||||
() -> {
|
notifyListeners(() -> invokeAll(listenerSnapshot, listenerInvocation));
|
||||||
for (Player.EventListener listener : listeners) {
|
|
||||||
listenerInvocation.invokeListener(listener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyListeners(Runnable listenerNotificationRunnable) {
|
private void notifyListeners(Runnable listenerNotificationRunnable) {
|
||||||
|
|
@ -728,7 +728,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
private static final class PlaybackInfoUpdate implements Runnable {
|
private static final class PlaybackInfoUpdate implements Runnable {
|
||||||
|
|
||||||
private final PlaybackInfo playbackInfo;
|
private final PlaybackInfo playbackInfo;
|
||||||
private final Set<Player.EventListener> listeners;
|
private final CopyOnWriteArrayList<ListenerHolder> listenerSnapshot;
|
||||||
private final TrackSelector trackSelector;
|
private final TrackSelector trackSelector;
|
||||||
private final boolean positionDiscontinuity;
|
private final boolean positionDiscontinuity;
|
||||||
private final @Player.DiscontinuityReason int positionDiscontinuityReason;
|
private final @Player.DiscontinuityReason int positionDiscontinuityReason;
|
||||||
|
|
@ -743,7 +743,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
public PlaybackInfoUpdate(
|
public PlaybackInfoUpdate(
|
||||||
PlaybackInfo playbackInfo,
|
PlaybackInfo playbackInfo,
|
||||||
PlaybackInfo previousPlaybackInfo,
|
PlaybackInfo previousPlaybackInfo,
|
||||||
Set<Player.EventListener> listeners,
|
CopyOnWriteArrayList<ListenerHolder> listeners,
|
||||||
TrackSelector trackSelector,
|
TrackSelector trackSelector,
|
||||||
boolean positionDiscontinuity,
|
boolean positionDiscontinuity,
|
||||||
@Player.DiscontinuityReason int positionDiscontinuityReason,
|
@Player.DiscontinuityReason int positionDiscontinuityReason,
|
||||||
|
|
@ -751,7 +751,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
boolean seekProcessed,
|
boolean seekProcessed,
|
||||||
boolean playWhenReady) {
|
boolean playWhenReady) {
|
||||||
this.playbackInfo = playbackInfo;
|
this.playbackInfo = playbackInfo;
|
||||||
this.listeners = listeners;
|
this.listenerSnapshot = new CopyOnWriteArrayList<>(listeners);
|
||||||
this.trackSelector = trackSelector;
|
this.trackSelector = trackSelector;
|
||||||
this.positionDiscontinuity = positionDiscontinuity;
|
this.positionDiscontinuity = positionDiscontinuity;
|
||||||
this.positionDiscontinuityReason = positionDiscontinuityReason;
|
this.positionDiscontinuityReason = positionDiscontinuityReason;
|
||||||
|
|
@ -770,43 +770,85 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (timelineOrManifestChanged || timelineChangeReason == TIMELINE_CHANGE_REASON_PREPARED) {
|
if (timelineOrManifestChanged || timelineChangeReason == TIMELINE_CHANGE_REASON_PREPARED) {
|
||||||
for (Player.EventListener listener : listeners) {
|
invokeAll(
|
||||||
listener.onTimelineChanged(
|
listenerSnapshot,
|
||||||
playbackInfo.timeline, playbackInfo.manifest, timelineChangeReason);
|
listener ->
|
||||||
}
|
listener.onTimelineChanged(
|
||||||
|
playbackInfo.timeline, playbackInfo.manifest, timelineChangeReason));
|
||||||
}
|
}
|
||||||
if (positionDiscontinuity) {
|
if (positionDiscontinuity) {
|
||||||
for (Player.EventListener listener : listeners) {
|
invokeAll(
|
||||||
listener.onPositionDiscontinuity(positionDiscontinuityReason);
|
listenerSnapshot,
|
||||||
}
|
listener -> listener.onPositionDiscontinuity(positionDiscontinuityReason));
|
||||||
}
|
}
|
||||||
if (trackSelectorResultChanged) {
|
if (trackSelectorResultChanged) {
|
||||||
trackSelector.onSelectionActivated(playbackInfo.trackSelectorResult.info);
|
trackSelector.onSelectionActivated(playbackInfo.trackSelectorResult.info);
|
||||||
for (Player.EventListener listener : listeners) {
|
invokeAll(
|
||||||
listener.onTracksChanged(
|
listenerSnapshot,
|
||||||
playbackInfo.trackGroups, playbackInfo.trackSelectorResult.selections);
|
listener ->
|
||||||
}
|
listener.onTracksChanged(
|
||||||
|
playbackInfo.trackGroups, playbackInfo.trackSelectorResult.selections));
|
||||||
}
|
}
|
||||||
if (isLoadingChanged) {
|
if (isLoadingChanged) {
|
||||||
for (Player.EventListener listener : listeners) {
|
invokeAll(listenerSnapshot, listener -> listener.onLoadingChanged(playbackInfo.isLoading));
|
||||||
listener.onLoadingChanged(playbackInfo.isLoading);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (playbackStateChanged) {
|
if (playbackStateChanged) {
|
||||||
for (Player.EventListener listener : listeners) {
|
invokeAll(
|
||||||
listener.onPlayerStateChanged(playWhenReady, playbackInfo.playbackState);
|
listenerSnapshot,
|
||||||
}
|
listener -> listener.onPlayerStateChanged(playWhenReady, playbackInfo.playbackState));
|
||||||
}
|
}
|
||||||
if (seekProcessed) {
|
if (seekProcessed) {
|
||||||
for (Player.EventListener listener : listeners) {
|
invokeAll(listenerSnapshot, EventListener::onSeekProcessed);
|
||||||
listener.onSeekProcessed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void invokeAll(
|
||||||
|
CopyOnWriteArrayList<ListenerHolder> listeners, ListenerInvocation listenerInvocation) {
|
||||||
|
for (ListenerHolder listenerHolder : listeners) {
|
||||||
|
listenerHolder.invoke(listenerInvocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private interface ListenerInvocation {
|
private interface ListenerInvocation {
|
||||||
|
|
||||||
void invokeListener(Player.EventListener listener);
|
void invokeListener(Player.EventListener listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class ListenerHolder {
|
||||||
|
|
||||||
|
private final Player.EventListener listener;
|
||||||
|
|
||||||
|
private boolean released;
|
||||||
|
|
||||||
|
public ListenerHolder(Player.EventListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
released = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invoke(ListenerInvocation listenerInvocation) {
|
||||||
|
if (!released) {
|
||||||
|
listenerInvocation.invokeListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (other == null || getClass() != other.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return listener.equals(((ListenerHolder) other).listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return listener.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue