Clarify docs around listener hierarchies in MediaSourceEventDispatcher

Also add a couple of tests to enforce the documentation.

PiperOrigin-RevId: 301796102
This commit is contained in:
ibaker 2020-03-19 12:50:45 +00:00 committed by Oliver Woodman
parent 818925d4a7
commit 181177a245
2 changed files with 39 additions and 0 deletions

View File

@ -103,6 +103,11 @@ public class MediaSourceEventDispatcher {
* event dispatched to {@code listenerClass} will only be passed to the {@code eventListener} * event dispatched to {@code listenerClass} will only be passed to the {@code eventListener}
* once. * once.
* *
* <p><b>NOTE</b>: This doesn't interact well with hierarchies of listener interfaces. If a
* listener is registered with a super-class type then it will only receive events dispatched
* directly to that super-class type. Similarly, if a listener is registered with a sub-class type
* then it will only receive events dispatched directly to that sub-class.
*
* @param handler A handler on the which listener events will be posted. * @param handler A handler on the which listener events will be posted.
* @param eventListener The listener to be added. * @param eventListener The listener to be added.
* @param listenerClass The type used to register the listener. Can be a superclass of {@code * @param listenerClass The type used to register the listener. Can be a superclass of {@code

View File

@ -18,15 +18,18 @@ package com.google.android.exoplayer2.util;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
@ -123,6 +126,33 @@ public class MediaSourceEventDispatcherTest {
verify(mediaAndDrmEventListener, never()).onDrmKeysLoaded(); verify(mediaAndDrmEventListener, never()).onDrmKeysLoaded();
} }
@Test
public void listenerDoesntReceiveEventsDispatchedToSubclass() {
SubclassListener subclassListener = mock(SubclassListener.class);
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()), subclassListener, MediaSourceEventListener.class);
eventDispatcher.dispatch(SubclassListener::subclassMethod, SubclassListener.class);
// subclassListener can handle the call to subclassMethod, but it isn't called because
// it was registered 'as-a' MediaSourceEventListener, not SubclassListener.
verify(subclassListener, never()).subclassMethod(anyInt(), any());
}
@Test
public void listenerDoesntReceiveEventsDispatchedToSuperclass() {
SubclassListener subclassListener = mock(SubclassListener.class);
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()), subclassListener, SubclassListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
// subclassListener 'is-a' a MediaSourceEventListener, but it isn't called because the event
// is dispatched specifically to listeners registered as MediaSourceEventListener.
verify(subclassListener, never()).onMediaPeriodCreated(anyInt(), any());
}
@Test @Test
public void listenersAreCopiedToNewDispatcher() { public void listenersAreCopiedToNewDispatcher() {
eventDispatcher.addEventListener( eventDispatcher.addEventListener(
@ -185,4 +215,8 @@ public class MediaSourceEventDispatcherTest {
private interface MediaAndDrmEventListener private interface MediaAndDrmEventListener
extends MediaSourceEventListener, DrmSessionEventListener {} extends MediaSourceEventListener, DrmSessionEventListener {}
private interface SubclassListener extends MediaSourceEventListener {
void subclassMethod(int windowIndex, @Nullable MediaPeriodId mediaPeriodId);
}
} }