From 5f8cc71d1b5910fe1bf294644ee57285901ab04b Mon Sep 17 00:00:00 2001 From: ibaker Date: Mon, 16 Mar 2020 17:50:59 +0000 Subject: [PATCH] Use reference-counting for listeners from MediaSourceEventDispatcher Previously calling removeListener would remove all instances of that listener. Now it only removes a single instance. This probably should have been part of introducing the Multiset: https://github.com/google/ExoPlayer/commit/2bd4d61b9b8c838fb7dc81e7d6f513c4a4e00c76 PiperOrigin-RevId: 301191940 --- .../util/MediaSourceEventDispatcher.java | 5 +++++ .../util/MediaSourceEventDispatcherTest.java | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+) 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 {} }