Clarify and correct allowed multi-threading for some Player methods
Some Player methods like getting the Looper and adding listeners were always allowed to be called from any thread, but this is undocumented. This change makes the threading rules of these methods more explicit. Removing listeners was never meant to be called from another thread and we also don't support it safely because final callbacks may be triggered from the wrong thread. To find potential issues, we can assert the correct thread when releasing listeners. Finally, there is a potential race condition when calling addListener from a different thread at the same time as release, which may lead to a registered listener that could receive callbacks after the player is released. PiperOrigin-RevId: 493843981
This commit is contained in:
parent
533f5288f4
commit
927b2d6a43
@ -49,6 +49,10 @@ import java.util.List;
|
||||
* A media player interface defining traditional high-level functionality, such as the ability to
|
||||
* play, pause, seek and query properties of the currently playing media.
|
||||
*
|
||||
* <p>All methods must be called from a single {@linkplain #getApplicationLooper() application
|
||||
* thread} unless indicated otherwise. Callbacks in registered listeners are called on the same
|
||||
* thread.
|
||||
*
|
||||
* <p>This interface includes some convenience methods that can be implemented by calling other
|
||||
* methods in the interface. {@link BasePlayer} implements these convenience methods so inheriting
|
||||
* {@link BasePlayer} is recommended when implementing the interface so that only the minimal set of
|
||||
@ -1557,6 +1561,8 @@ public interface Player {
|
||||
/**
|
||||
* Returns the {@link Looper} associated with the application thread that's used to access the
|
||||
* player and on which player events are received.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*/
|
||||
Looper getApplicationLooper();
|
||||
|
||||
@ -1566,6 +1572,8 @@ public interface Player {
|
||||
* <p>The listener's methods will be called on the thread associated with {@link
|
||||
* #getApplicationLooper()}.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
void addListener(Listener listener);
|
||||
|
@ -1978,8 +1978,7 @@ public abstract class SimpleBasePlayer extends BasePlayer {
|
||||
|
||||
@Override
|
||||
public final void removeListener(Listener listener) {
|
||||
// Don't verify application thread. We allow calls to this method from any thread.
|
||||
checkNotNull(listener);
|
||||
verifyApplicationThreadAndInitState();
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,12 @@
|
||||
*/
|
||||
package androidx.media3.common.util;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import androidx.annotation.CheckResult;
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.FlagSet;
|
||||
@ -34,6 +37,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
* <p>Events are also guaranteed to be only sent to the listeners registered at the time the event
|
||||
* was enqueued and haven't been removed since.
|
||||
*
|
||||
* <p>All methods must be called on the {@link Looper} passed to the constructor unless indicated
|
||||
* otherwise.
|
||||
*
|
||||
* @param <T> The listener type.
|
||||
*/
|
||||
@UnstableApi
|
||||
@ -76,14 +82,18 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
private final CopyOnWriteArraySet<ListenerHolder<T>> listeners;
|
||||
private final ArrayDeque<Runnable> flushingEvents;
|
||||
private final ArrayDeque<Runnable> queuedEvents;
|
||||
private final Object releasedLock;
|
||||
|
||||
@GuardedBy("releasedLock")
|
||||
private boolean released;
|
||||
|
||||
private boolean throwsWhenUsingWrongThread;
|
||||
|
||||
/**
|
||||
* Creates a new listener set.
|
||||
*
|
||||
* @param looper A {@link Looper} used to call listeners on. The same {@link Looper} must be used
|
||||
* to call all other methods of this class.
|
||||
* to call all other methods of this class unless indicated otherwise.
|
||||
* @param clock A {@link Clock}.
|
||||
* @param iterationFinishedEvent An {@link IterationFinishedEvent} sent when all other events sent
|
||||
* during one {@link Looper} message queue iteration were handled by the listeners.
|
||||
@ -100,17 +110,21 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
this.clock = clock;
|
||||
this.listeners = listeners;
|
||||
this.iterationFinishedEvent = iterationFinishedEvent;
|
||||
releasedLock = new Object();
|
||||
flushingEvents = new ArrayDeque<>();
|
||||
queuedEvents = new ArrayDeque<>();
|
||||
// It's safe to use "this" because we don't send a message before exiting the constructor.
|
||||
@SuppressWarnings("nullness:methodref.receiver.bound")
|
||||
HandlerWrapper handler = clock.createHandler(looper, this::handleMessage);
|
||||
this.handler = handler;
|
||||
throwsWhenUsingWrongThread = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the listener set.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*
|
||||
* @param looper The new {@link Looper} for the copied listener set.
|
||||
* @param iterationFinishedEvent The new {@link IterationFinishedEvent} sent when all other events
|
||||
* sent during one {@link Looper} message queue iteration were handled by the listeners.
|
||||
@ -124,6 +138,8 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
/**
|
||||
* Copies the listener set.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*
|
||||
* @param looper The new {@link Looper} for the copied listener set.
|
||||
* @param clock The new {@link Clock} for the copied listener set.
|
||||
* @param iterationFinishedEvent The new {@link IterationFinishedEvent} sent when all other events
|
||||
@ -141,15 +157,19 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
*
|
||||
* <p>If a listener is already present, it will not be added again.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*
|
||||
* @param listener The listener to be added.
|
||||
*/
|
||||
public void add(T listener) {
|
||||
Assertions.checkNotNull(listener);
|
||||
synchronized (releasedLock) {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
Assertions.checkNotNull(listener);
|
||||
listeners.add(new ListenerHolder<>(listener));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from the set.
|
||||
@ -159,6 +179,7 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
* @param listener The listener to be removed.
|
||||
*/
|
||||
public void remove(T listener) {
|
||||
verifyCurrentThread();
|
||||
for (ListenerHolder<T> listenerHolder : listeners) {
|
||||
if (listenerHolder.listener.equals(listener)) {
|
||||
listenerHolder.release(iterationFinishedEvent);
|
||||
@ -169,11 +190,13 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
|
||||
/** Removes all listeners from the set. */
|
||||
public void clear() {
|
||||
verifyCurrentThread();
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
/** Returns the number of added listeners. */
|
||||
public int size() {
|
||||
verifyCurrentThread();
|
||||
return listeners.size();
|
||||
}
|
||||
|
||||
@ -185,6 +208,7 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
* @param event The event.
|
||||
*/
|
||||
public void queueEvent(int eventFlag, Event<T> event) {
|
||||
verifyCurrentThread();
|
||||
CopyOnWriteArraySet<ListenerHolder<T>> listenerSnapshot = new CopyOnWriteArraySet<>(listeners);
|
||||
queuedEvents.add(
|
||||
() -> {
|
||||
@ -196,6 +220,7 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
|
||||
/** Notifies listeners of events previously enqueued with {@link #queueEvent(int, Event)}. */
|
||||
public void flushEvents() {
|
||||
verifyCurrentThread();
|
||||
if (queuedEvents.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -234,11 +259,27 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
* <p>This will ensure no events are sent to any listener after this method has been called.
|
||||
*/
|
||||
public void release() {
|
||||
verifyCurrentThread();
|
||||
synchronized (releasedLock) {
|
||||
released = true;
|
||||
}
|
||||
for (ListenerHolder<T> listenerHolder : listeners) {
|
||||
listenerHolder.release(iterationFinishedEvent);
|
||||
}
|
||||
listeners.clear();
|
||||
released = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether methods throw when using the wrong thread.
|
||||
*
|
||||
* <p>Do not use this method unless to support legacy use cases.
|
||||
*
|
||||
* @param throwsWhenUsingWrongThread Whether to throw when using the wrong thread.
|
||||
* @deprecated Do not use this method and ensure all calls are made from the correct thread.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setThrowsWhenUsingWrongThread(boolean throwsWhenUsingWrongThread) {
|
||||
this.throwsWhenUsingWrongThread = throwsWhenUsingWrongThread;
|
||||
}
|
||||
|
||||
private boolean handleMessage(Message message) {
|
||||
@ -254,6 +295,13 @@ public final class ListenerSet<T extends @NonNull Object> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void verifyCurrentThread() {
|
||||
if (!throwsWhenUsingWrongThread) {
|
||||
return;
|
||||
}
|
||||
checkState(Thread.currentThread() == handler.getLooper().getThread());
|
||||
}
|
||||
|
||||
private static final class ListenerHolder<T extends @NonNull Object> {
|
||||
|
||||
public final T listener;
|
||||
|
@ -132,15 +132,15 @@ import java.util.List;
|
||||
* threading model">
|
||||
*
|
||||
* <ul>
|
||||
* <li>ExoPlayer instances must be accessed from a single application thread. For the vast
|
||||
* majority of cases this should be the application's main thread. Using the application's
|
||||
* main thread is also a requirement when using ExoPlayer's UI components or the IMA
|
||||
* extension. The thread on which an ExoPlayer instance must be accessed can be explicitly
|
||||
* specified by passing a `Looper` when creating the player. If no `Looper` is specified, then
|
||||
* the `Looper` of the thread that the player is created on is used, or if that thread does
|
||||
* not have a `Looper`, the `Looper` of the application's main thread is used. In all cases
|
||||
* the `Looper` of the thread from which the player must be accessed can be queried using
|
||||
* {@link #getApplicationLooper()}.
|
||||
* <li>ExoPlayer instances must be accessed from a single application thread unless indicated
|
||||
* otherwise. For the vast majority of cases this should be the application's main thread.
|
||||
* Using the application's main thread is also a requirement when using ExoPlayer's UI
|
||||
* components or the IMA extension. The thread on which an ExoPlayer instance must be accessed
|
||||
* can be explicitly specified by passing a `Looper` when creating the player. If no `Looper`
|
||||
* is specified, then the `Looper` of the thread that the player is created on is used, or if
|
||||
* that thread does not have a `Looper`, the `Looper` of the application's main thread is
|
||||
* used. In all cases the `Looper` of the thread from which the player must be accessed can be
|
||||
* queried using {@link #getApplicationLooper()}.
|
||||
* <li>Registered listeners are called on the thread associated with {@link
|
||||
* #getApplicationLooper()}. Note that this means registered listeners are called on the same
|
||||
* thread which must be used to access the player.
|
||||
@ -1229,6 +1229,8 @@ public interface ExoPlayer extends Player {
|
||||
/**
|
||||
* Adds a listener to receive audio offload events.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
@UnstableApi
|
||||
@ -1249,6 +1251,8 @@ public interface ExoPlayer extends Player {
|
||||
/**
|
||||
* Adds an {@link AnalyticsListener} to receive analytics events.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*
|
||||
* @param listener The listener to be added.
|
||||
*/
|
||||
void addAnalyticsListener(AnalyticsListener listener);
|
||||
@ -1314,11 +1318,19 @@ public interface ExoPlayer extends Player {
|
||||
@Deprecated
|
||||
TrackSelectionArray getCurrentTrackSelections();
|
||||
|
||||
/** Returns the {@link Looper} associated with the playback thread. */
|
||||
/**
|
||||
* Returns the {@link Looper} associated with the playback thread.
|
||||
*
|
||||
* <p>This method may be called from any thread.
|
||||
*/
|
||||
@UnstableApi
|
||||
Looper getPlaybackLooper();
|
||||
|
||||
/** Returns the {@link Clock} used for playback. */
|
||||
/**
|
||||
* Returns the {@link Clock} used for playback.
|
||||
*
|
||||
* <p>This method can be called from any thread.
|
||||
*/
|
||||
@UnstableApi
|
||||
Clock getClock();
|
||||
|
||||
|
@ -89,6 +89,7 @@ import androidx.media3.exoplayer.PlayerMessage.Target;
|
||||
import androidx.media3.exoplayer.Renderer.MessageType;
|
||||
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
|
||||
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
||||
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
|
||||
import androidx.media3.exoplayer.analytics.MediaMetricsListener;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.audio.AudioRendererEventListener;
|
||||
@ -480,7 +481,7 @@ import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Override
|
||||
public void removeAudioOffloadListener(AudioOffloadListener listener) {
|
||||
// Don't verify application thread. We allow calls to this method from any thread.
|
||||
verifyApplicationThread();
|
||||
audioOffloadListeners.remove(listener);
|
||||
}
|
||||
|
||||
@ -1488,7 +1489,7 @@ import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Override
|
||||
public void removeAnalyticsListener(AnalyticsListener listener) {
|
||||
// Don't verify application thread. We allow calls to this method from any thread.
|
||||
verifyApplicationThread();
|
||||
analyticsCollector.removeListener(checkNotNull(listener));
|
||||
}
|
||||
|
||||
@ -1605,9 +1606,8 @@ import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Override
|
||||
public void removeListener(Listener listener) {
|
||||
// Don't verify application thread. We allow calls to this method from any thread.
|
||||
checkNotNull(listener);
|
||||
listeners.remove(listener);
|
||||
verifyApplicationThread();
|
||||
listeners.remove(checkNotNull(listener));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1690,8 +1690,14 @@ import java.util.concurrent.TimeoutException;
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Calling deprecated methods.
|
||||
/* package */ void setThrowsWhenUsingWrongThread(boolean throwsWhenUsingWrongThread) {
|
||||
this.throwsWhenUsingWrongThread = throwsWhenUsingWrongThread;
|
||||
listeners.setThrowsWhenUsingWrongThread(throwsWhenUsingWrongThread);
|
||||
if (analyticsCollector instanceof DefaultAnalyticsCollector) {
|
||||
((DefaultAnalyticsCollector) analyticsCollector)
|
||||
.setThrowsWhenUsingWrongThread(throwsWhenUsingWrongThread);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,6 +96,20 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
|
||||
eventTimes = new SparseArray<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether methods throw when using the wrong thread.
|
||||
*
|
||||
* <p>Do not use this method unless to support legacy use cases.
|
||||
*
|
||||
* @param throwsWhenUsingWrongThread Whether to throw when using the wrong thread.
|
||||
* @deprecated Do not use this method and ensure all calls are made from the correct thread.
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Calling deprecated method.
|
||||
@Deprecated
|
||||
public void setThrowsWhenUsingWrongThread(boolean throwsWhenUsingWrongThread) {
|
||||
listeners.setThrowsWhenUsingWrongThread(throwsWhenUsingWrongThread);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CallSuper
|
||||
public void addListener(AnalyticsListener listener) {
|
||||
|
@ -12006,10 +12006,20 @@ public final class ExoPlayerTest {
|
||||
|
||||
@Test
|
||||
@Config(sdk = Config.ALL_SDKS)
|
||||
public void builder_inBackgroundThread_doesNotThrow() throws Exception {
|
||||
public void builder_inBackgroundThreadWithAllowedAnyThreadMethods_doesNotThrow()
|
||||
throws Exception {
|
||||
Thread builderThread =
|
||||
new Thread(
|
||||
() -> new ExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build());
|
||||
() -> {
|
||||
ExoPlayer player =
|
||||
new ExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||
player.addListener(new Listener() {});
|
||||
player.addAnalyticsListener(new AnalyticsListener() {});
|
||||
player.addAudioOffloadListener(new ExoPlayer.AudioOffloadListener() {});
|
||||
player.getClock();
|
||||
player.getApplicationLooper();
|
||||
player.getPlaybackLooper();
|
||||
});
|
||||
AtomicReference<Throwable> builderThrow = new AtomicReference<>();
|
||||
builderThread.setUncaughtExceptionHandler((thread, throwable) -> builderThrow.set(throwable));
|
||||
|
||||
|
@ -1720,6 +1720,7 @@ public class MediaController implements Player {
|
||||
|
||||
@Override
|
||||
public Looper getApplicationLooper() {
|
||||
// Don't verify application thread. We allow calls to this method from any thread.
|
||||
return applicationHandler.getLooper();
|
||||
}
|
||||
|
||||
@ -1744,12 +1745,14 @@ public class MediaController implements Player {
|
||||
|
||||
@Override
|
||||
public void addListener(Player.Listener listener) {
|
||||
// Don't verify application thread. We allow calls to this method from any thread.
|
||||
checkNotNull(listener, "listener must not be null");
|
||||
impl.addListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(Player.Listener listener) {
|
||||
verifyApplicationThread();
|
||||
checkNotNull(listener, "listener must not be null");
|
||||
impl.removeListener(listener);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import static androidx.media3.test.session.common.CommonConstants.DEFAULT_TEST_N
|
||||
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
@ -26,7 +27,6 @@ import android.view.SurfaceView;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.media3.test.session.common.HandlerThreadTestRule;
|
||||
import androidx.media3.test.session.common.PollingCheck;
|
||||
import androidx.media3.test.session.common.SurfaceActivity;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -37,8 +37,6 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.RuleChain;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Tests for {@link MediaController#setVideoSurface(Surface)}. */
|
||||
@ -47,13 +45,6 @@ import org.junit.runner.RunWith;
|
||||
public class MediaControllerSurfaceTest {
|
||||
private static final String TAG = "MC_SurfaceTest";
|
||||
|
||||
private final HandlerThreadTestRule threadTestRule = new HandlerThreadTestRule(TAG);
|
||||
private final MediaControllerTestRule controllerTestRule =
|
||||
new MediaControllerTestRule(threadTestRule);
|
||||
|
||||
@Rule
|
||||
public final TestRule chain = RuleChain.outerRule(threadTestRule).around(controllerTestRule);
|
||||
|
||||
private SurfaceActivity activity;
|
||||
private RemoteMediaSession remoteSession;
|
||||
|
||||
@ -76,93 +67,97 @@ public class MediaControllerSurfaceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurface() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoSurface() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
Surface testSurface = activity.getFirstSurfaceHolder().getSurface();
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(testSurface));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurface_withNull_clearsSurface() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoSurface_withNull_clearsSurface() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
Surface testSurface = activity.getFirstSurfaceHolder().getSurface();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(testSurface));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(null));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurface_withTheSameSurface() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurface_withTheSameSurface() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
Surface testSurface = activity.getFirstSurfaceHolder().getSurface();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(testSurface));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface(testSurface));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurface_withDifferentSurface_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurface_withDifferentSurface_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
Surface testSurface = activity.getFirstSurfaceHolder().getSurface();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(testSurface));
|
||||
Surface anotherSurface = activity.getSecondSurfaceHolder().getSurface();
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface(anotherSurface));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface(anotherSurface));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurface_withNull_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurface_withNull_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
Surface testSurface = activity.getFirstSurfaceHolder().getSurface();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(testSurface));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface(null));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceHolder() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoSurfaceHolder() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
controller.setVideoSurfaceHolder(testSurfaceHolder);
|
||||
});
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceHolder_withNull_clearsSurfaceHolder() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoSurfaceHolder_withNull_clearsSurfaceHolder() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceHolder(null));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceHolder_whenSurfaceIsDestroyed_surfaceIsClearedFromPlayer()
|
||||
throws Throwable {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
@ -171,15 +166,14 @@ public class MediaControllerSurfaceTest {
|
||||
});
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceHolder_whenSurfaceIsCreated_surfaceIsSetToPlayer() throws Throwable {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
SurfaceView firstSurfaceView = activity.getFirstSurfaceView();
|
||||
@ -193,79 +187,75 @@ public class MediaControllerSurfaceTest {
|
||||
});
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceHolder_withTheSameSurfaceHolder() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceHolder_withTheSameSurfaceHolder() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.clearVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurfaceHolder(testSurfaceHolder));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceHolder_withDifferentSurfaceHolder_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceHolder_withDifferentSurfaceHolder_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
SurfaceHolder anotherTestSurfaceHolder = activity.getSecondSurfaceHolder();
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.clearVideoSurfaceHolder(anotherTestSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurfaceHolder(anotherTestSurfaceHolder));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceHolder_withNull_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceHolder_withNull_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurfaceHolder(null));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurfaceHolder(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoSurfaceView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceView_withNull_clearsSurfaceView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoSurfaceView_withNull_clearsSurfaceView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(null));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceView_whenSurfaceIsDestroyed_surfaceIsClearedFromPlayer()
|
||||
throws Throwable {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
@ -273,13 +263,14 @@ public class MediaControllerSurfaceTest {
|
||||
});
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoSurfaceView_whenSurfaceIsCreated_surfaceIsSetToPlayer() throws Throwable {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
testSurfaceView.setVisibility(View.GONE);
|
||||
@ -291,74 +282,76 @@ public class MediaControllerSurfaceTest {
|
||||
});
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceView_withTheSameSurfaceView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceView_withTheSameSurfaceView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.clearVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurfaceView(testSurfaceView));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceView_withDifferentSurfaceView_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceView_withDifferentSurfaceView_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
SurfaceView anotherTestSurfaceView = activity.getSecondSurfaceView();
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.clearVideoSurfaceView(anotherTestSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurfaceView(anotherTestSurfaceView));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceView_withNull_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceView_withNull_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
SurfaceView anotherTestSurfaceView = activity.getSecondSurfaceView();
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurfaceView(null));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurfaceView(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoTextureView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoTextureView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoTextureView_withNull_clearsTextureView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void setVideoTextureView_withNull_clearsTextureView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(null));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoTextureView_whenSurfaceTextureIsDestroyed_surfaceIsClearedFromPlayer()
|
||||
throws Throwable {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
@ -368,14 +361,15 @@ public class MediaControllerSurfaceTest {
|
||||
});
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVideoTextureView_whenSurfaceTextureIsAvailable_surfaceIsSetToPlayer()
|
||||
throws Throwable {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(
|
||||
() -> {
|
||||
ViewGroup rootViewGroup = activity.getRootViewGroup();
|
||||
@ -391,89 +385,98 @@ public class MediaControllerSurfaceTest {
|
||||
});
|
||||
|
||||
PollingCheck.waitFor(TIMEOUT_MS, () -> remoteSession.getMockPlayer().surfaceExists());
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoTextureView_withTheSameTextureView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoTextureView_withTheSameTextureView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.clearVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoTextureView(testTextureView));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoTextureView_withDifferentTextureView_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoTextureView_withDifferentTextureView_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
TextureView anotherTestTextureView = activity.getSecondTextureView();
|
||||
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.clearVideoTextureView(anotherTestTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoTextureView(anotherTestTextureView));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoTextureView_withNull_doesNothing() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoTextureView_withNull_doesNothing() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoTextureView(null));
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoTextureView(null));
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isTrue();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoSurface() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoSurface() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
Surface testSurface = activity.getFirstSurfaceHolder().getSurface();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurface(testSurface));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurface(testSurface));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface());
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface());
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoSurfaceHolder() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoSurfaceHolder() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceHolder testSurfaceHolder = activity.getFirstSurfaceHolder();
|
||||
threadTestRule
|
||||
.getHandler()
|
||||
.postAndSync(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceHolder(testSurfaceHolder));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface());
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface());
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoSurfaceView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoSurfaceView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
SurfaceView testSurfaceView = activity.getFirstSurfaceView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoSurfaceView(testSurfaceView));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface());
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface());
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoTextureView() throws Exception {
|
||||
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
|
||||
public void clearVideoSurfaceWithNoArguments_afterSetVideoTextureView() throws Throwable {
|
||||
MediaController controller = createController();
|
||||
TextureView testTextureView = activity.getFirstTextureView();
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.setVideoTextureView(testTextureView));
|
||||
activityRule.runOnUiThread(() -> controller.setVideoTextureView(testTextureView));
|
||||
|
||||
threadTestRule.getHandler().postAndSync(() -> controller.clearVideoSurface());
|
||||
activityRule.runOnUiThread(() -> controller.clearVideoSurface());
|
||||
|
||||
assertThat(remoteSession.getMockPlayer().surfaceExists()).isFalse();
|
||||
activityRule.runOnUiThread(controller::release);
|
||||
}
|
||||
|
||||
private MediaController createController() throws Exception {
|
||||
return new MediaController.Builder(activity, remoteSession.getToken())
|
||||
.setApplicationLooper(Looper.getMainLooper())
|
||||
.buildAsync()
|
||||
.get();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user