diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcher.java b/library/core/src/main/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcher.java index b0b349a86e..a3ee0ac9ef 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcher.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcher.java @@ -117,6 +117,10 @@ public class MediaSourceEventDispatcher { /** * Removes a listener from the event dispatcher. * + *
If there are duplicate registrations of {@code {eventListener, listenerClass}} this will + * only remove one (so events dispatched to {@code listenerClass} will still be passed to {@code + * eventListener}). + * * @param eventListener The listener to be removed. * @param listenerClass The listener type passed to {@link #addEventListener(Handler, Object, * Class)}. @@ -126,6 +130,7 @@ public class MediaSourceEventDispatcher { if (listenerInfo.listener == eventListener && listenerInfo.listenerClass.equals(listenerClass)) { listenerInfos.remove(listenerInfo); + return; } } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcherTest.java b/library/core/src/test/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcherTest.java index 7fa55d3128..0063c4e738 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcherTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/util/MediaSourceEventDispatcherTest.java @@ -20,6 +20,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import android.os.Handler; import android.os.Looper; @@ -162,6 +163,26 @@ public class MediaSourceEventDispatcherTest { verify(mediaAndDrmEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID); } + @Test + public void listenersAreCountedBasedOnListenerAndType() { + // Add the listener twice and remove it once. + eventDispatcher.addEventListener( + Util.createHandler(), mediaSourceEventListener, MediaSourceEventListener.class); + eventDispatcher.addEventListener( + Util.createHandler(), mediaSourceEventListener, MediaSourceEventListener.class); + eventDispatcher.removeEventListener(mediaSourceEventListener, MediaSourceEventListener.class); + + eventDispatcher.dispatch( + MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class); + + verify(mediaSourceEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID); + + // Remove it a second time and confirm the events stop being propagated. + eventDispatcher.removeEventListener(mediaSourceEventListener, MediaSourceEventListener.class); + + verifyNoMoreInteractions(mediaSourceEventListener); + } + private interface MediaAndDrmEventListener extends MediaSourceEventListener, DrmSessionEventListener {} }