Commit cda6cba5 by olly Committed by Oliver Woodman

More nullness fixes in testutil

PiperOrigin-RevId: 292907271
parent ad115a5a
......@@ -484,7 +484,7 @@ public final class ExoPlayerTest {
new ActionSchedule.Builder("testAdGroupWithLoadErrorIsSkipped")
.pause()
.waitForPlaybackState(Player.STATE_READY)
.executeRunnable(() -> fakeMediaSource.setNewSourceInfo(adErrorTimeline, null))
.executeRunnable(() -> fakeMediaSource.setNewSourceInfo(adErrorTimeline))
.waitForTimelineChanged(
adErrorTimeline, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.play()
......@@ -864,7 +864,7 @@ public final class ExoPlayerTest {
.pause()
.waitForTimelineChanged(
timeline, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline2, null))
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline2))
.waitForTimelineChanged(
timeline2, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.play()
......@@ -2061,7 +2061,7 @@ public final class ExoPlayerTest {
.waitForTimelineChanged(
timeline, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.sendMessage(target, /* positionMs= */ 50)
.executeRunnable(() -> mediaSource.setNewSourceInfo(secondTimeline, null))
.executeRunnable(() -> mediaSource.setNewSourceInfo(secondTimeline))
.waitForTimelineChanged(
secondTimeline, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.play()
......@@ -2137,7 +2137,7 @@ public final class ExoPlayerTest {
.waitForTimelineChanged(
timeline, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.sendMessage(target, /* windowIndex = */ 1, /* positionMs= */ 50)
.executeRunnable(() -> mediaSource.setNewSourceInfo(secondTimeline, null))
.executeRunnable(() -> mediaSource.setNewSourceInfo(secondTimeline))
.waitForTimelineChanged(
secondTimeline, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.seek(/* windowIndex= */ 0, /* positionMs= */ 0)
......@@ -2223,7 +2223,7 @@ public final class ExoPlayerTest {
@Test
public void testCancelRepeatedMessageAfterDelivery() throws Exception {
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
final PositionGrabbingMessageTarget target = new PositionGrabbingMessageTarget();
final CountingMessageTarget target = new CountingMessageTarget();
final AtomicReference<PlayerMessage> message = new AtomicReference<>();
ActionSchedule actionSchedule =
new ActionSchedule.Builder("testCancelMessage")
......@@ -2315,7 +2315,7 @@ public final class ExoPlayerTest {
.playUntilPosition(
/* windowIndex= */ 0,
/* positionMs= */ C.usToMs(TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US))
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline2, /* newManifest= */ null))
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline2))
.waitForTimelineChanged(
timeline2, /* expectedReason */ Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)
.play()
......@@ -2844,7 +2844,7 @@ public final class ExoPlayerTest {
.waitForPlaybackState(Player.STATE_BUFFERING)
.seek(/* positionMs= */ 10)
.waitForSeekProcessed()
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline, /* newManifest= */ null))
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline))
.waitForTimelineChanged()
.waitForPlaybackState(Player.STATE_READY)
.executeRunnable(
......@@ -2889,7 +2889,7 @@ public final class ExoPlayerTest {
// Seek 10ms into the second period.
.seek(/* positionMs= */ periodDurationMs + 10)
.waitForSeekProcessed()
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline, /* newManifest= */ null))
.executeRunnable(() -> mediaSource.setNewSourceInfo(timeline))
.waitForTimelineChanged()
.waitForPlaybackState(Player.STATE_READY)
.executeRunnable(
......@@ -5682,6 +5682,16 @@ public final class ExoPlayerTest {
// Internal classes.
private static final class CountingMessageTarget implements PlayerMessage.Target {
public int messageCount;
@Override
public void handleMessage(int x, @Nullable Object message) {
messageCount++;
}
}
private static final class PositionGrabbingMessageTarget extends PlayerTarget {
public int windowIndex;
......@@ -5695,10 +5705,8 @@ public final class ExoPlayerTest {
@Override
public void handleMessage(SimpleExoPlayer player, int messageType, @Nullable Object message) {
if (player != null) {
windowIndex = player.getCurrentWindowIndex();
positionMs = player.getCurrentPosition();
}
windowIndex = player.getCurrentWindowIndex();
positionMs = player.getCurrentPosition();
messageCount++;
}
}
......
......@@ -374,7 +374,7 @@ public final class MediaPeriodQueueTest {
private void updateTimeline() {
SinglePeriodAdTimeline adTimeline =
new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState);
fakeMediaSource.setNewSourceInfo(adTimeline, /* manifest */ null);
fakeMediaSource.setNewSourceInfo(adTimeline);
playbackInfo = playbackInfo.copyWithTimeline(createPlaylistTimeline());
}
......
......@@ -785,8 +785,7 @@ public final class AnalyticsCollectorTest {
/* isSeekable= */ true,
/* isDynamic= */ false,
/* durationUs =*/ 10 * C.MICROS_PER_SECOND,
adPlaybackState.get())),
/* newManifest= */ null);
adPlaybackState.get())));
}
}
});
......
......@@ -635,7 +635,7 @@ public final class ClippingMediaSourceTest {
clippedTimelines[0].getUidOfPeriod(/* periodIndex= */ 0),
/* windowSequenceNumber= */ 0));
for (int i = 0; i < additionalTimelines.length; i++) {
fakeMediaSource.setNewSourceInfo(additionalTimelines[i], /* newManifest= */ null);
fakeMediaSource.setNewSourceInfo(additionalTimelines[i]);
clippedTimelines[i + 1] = testRunner.assertTimelineChangeBlocking();
}
testRunner.releasePeriod(mediaPeriod);
......
......@@ -246,8 +246,7 @@ public final class ConcatenatingMediaSourceTest {
// Trigger source info refresh for lazy source and check that the timeline now contains all
// information for all windows.
testRunner.runOnPlaybackThread(
() -> lazySources[1].setNewSourceInfo(createFakeTimeline(8), null));
testRunner.runOnPlaybackThread(() -> lazySources[1].setNewSourceInfo(createFakeTimeline(8)));
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1, 9);
TimelineAsserts.assertWindowTags(timeline, 111, 999);
......@@ -281,8 +280,7 @@ public final class ConcatenatingMediaSourceTest {
// Trigger source info refresh for lazy media source. Assert that now all information is
// available again and the previously created period now also finished preparing.
testRunner.runOnPlaybackThread(
() -> lazySources[3].setNewSourceInfo(createFakeTimeline(7), null));
testRunner.runOnPlaybackThread(() -> lazySources[3].setNewSourceInfo(createFakeTimeline(7)));
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 8, 1, 2, 9);
TimelineAsserts.assertWindowTags(timeline, 888, 111, 222, 999);
......@@ -372,15 +370,15 @@ public final class ConcatenatingMediaSourceTest {
Timeline timeline = testRunner.prepareSource();
TimelineAsserts.assertEmpty(timeline);
childSources[0].setNewSourceInfo(nonEmptyTimeline, /* newManifest== */ null);
childSources[0].setNewSourceInfo(nonEmptyTimeline);
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1);
childSources[2].setNewSourceInfo(nonEmptyTimeline, /* newManifest== */ null);
childSources[2].setNewSourceInfo(nonEmptyTimeline);
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1, 1);
childSources[1].setNewSourceInfo(nonEmptyTimeline, /* newManifest== */ null);
childSources[1].setNewSourceInfo(nonEmptyTimeline);
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1, 1, 1);
}
......
......@@ -54,6 +54,7 @@ import com.google.android.exoplayer2.testutil.Action.WaitForTimelineChanged;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.HandlerWrapper;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Schedules a sequence of {@link Action}s for execution during a test.
......@@ -89,7 +90,8 @@ public final class ActionSchedule {
*
* @param player The player to which actions should be applied.
* @param trackSelector The track selector to which actions should be applied.
* @param surface The surface to use when applying actions.
* @param surface The surface to use when applying actions, or {@code null} if no surface is
* needed.
* @param mainHandler A handler associated with the main thread of the host activity.
* @param callback A {@link Callback} to notify when the action schedule finishes, or null if no
* notification is needed.
......@@ -97,7 +99,7 @@ public final class ActionSchedule {
/* package */ void start(
SimpleExoPlayer player,
DefaultTrackSelector trackSelector,
Surface surface,
@Nullable Surface surface,
HandlerWrapper mainHandler,
@Nullable Callback callback) {
callbackAction.setCallback(callback);
......@@ -607,9 +609,9 @@ public final class ActionSchedule {
void onMessageArrived();
}
private SimpleExoPlayer player;
@Nullable private SimpleExoPlayer player;
private boolean hasArrived;
private Callback callback;
@Nullable private Callback callback;
public void setCallback(Callback callback) {
this.callback = callback;
......@@ -629,7 +631,7 @@ public final class ActionSchedule {
@Override
public final void handleMessage(int messageType, @Nullable Object message) {
handleMessage(player, messageType, message);
handleMessage(Assertions.checkStateNotNull(player), messageType, message);
if (callback != null) {
hasArrived = true;
callback.onMessageArrived();
......@@ -643,7 +645,7 @@ public final class ActionSchedule {
*/
public abstract static class PlayerRunnable implements Runnable {
private SimpleExoPlayer player;
@Nullable private SimpleExoPlayer player;
/** Executes Runnable with reference to player. */
public abstract void run(SimpleExoPlayer player);
......@@ -655,7 +657,7 @@ public final class ActionSchedule {
@Override
public final void run() {
run(player);
run(Assertions.checkStateNotNull(player));
}
}
......@@ -666,12 +668,12 @@ public final class ActionSchedule {
private final long delayMs;
private final long repeatIntervalMs;
private ActionNode next;
@Nullable private ActionNode next;
private SimpleExoPlayer player;
private DefaultTrackSelector trackSelector;
private Surface surface;
private HandlerWrapper mainHandler;
private @MonotonicNonNull SimpleExoPlayer player;
private @MonotonicNonNull DefaultTrackSelector trackSelector;
@Nullable private Surface surface;
private @MonotonicNonNull HandlerWrapper mainHandler;
/**
* @param action The wrapped action.
......@@ -708,13 +710,13 @@ public final class ActionSchedule {
*
* @param player The player to which actions should be applied.
* @param trackSelector The track selector to which actions should be applied.
* @param surface The surface to use when applying actions.
* @param surface The surface to use when applying actions, or {@code null}.
* @param mainHandler A handler associated with the main thread of the host activity.
*/
public void schedule(
SimpleExoPlayer player,
DefaultTrackSelector trackSelector,
Surface surface,
@Nullable Surface surface,
HandlerWrapper mainHandler) {
this.player = player;
this.trackSelector = trackSelector;
......@@ -729,14 +731,20 @@ public final class ActionSchedule {
@Override
public void run() {
action.doActionAndScheduleNext(player, trackSelector, surface, mainHandler, next);
action.doActionAndScheduleNext(
Assertions.checkStateNotNull(player),
Assertions.checkStateNotNull(trackSelector),
surface,
Assertions.checkStateNotNull(mainHandler),
next);
if (repeatIntervalMs != C.TIME_UNSET) {
mainHandler.postDelayed(
new Runnable() {
@Override
public void run() {
action.doActionAndScheduleNext(player, trackSelector, surface, mainHandler, null);
mainHandler.postDelayed(this, repeatIntervalMs);
action.doActionAndScheduleNext(
player, trackSelector, surface, mainHandler, /* nextAction= */ null);
mainHandler.postDelayed(/* runnable= */ this, repeatIntervalMs);
}
},
repeatIntervalMs);
......@@ -756,7 +764,7 @@ public final class ActionSchedule {
@Override
protected void doActionImpl(
SimpleExoPlayer player, DefaultTrackSelector trackSelector, Surface surface) {
SimpleExoPlayer player, DefaultTrackSelector trackSelector, @Nullable Surface surface) {
// Do nothing.
}
}
......@@ -780,18 +788,19 @@ public final class ActionSchedule {
protected void doActionAndScheduleNextImpl(
SimpleExoPlayer player,
DefaultTrackSelector trackSelector,
Surface surface,
@Nullable Surface surface,
HandlerWrapper handler,
ActionNode nextAction) {
@Nullable ActionNode nextAction) {
Assertions.checkArgument(nextAction == null);
@Nullable Callback callback = this.callback;
if (callback != null) {
handler.post(() -> callback.onActionScheduleFinished());
handler.post(callback::onActionScheduleFinished);
}
}
@Override
protected void doActionImpl(
SimpleExoPlayer player, DefaultTrackSelector trackSelector, Surface surface) {
SimpleExoPlayer player, DefaultTrackSelector trackSelector, @Nullable Surface surface) {
// Not triggered.
}
}
......
......@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DummyDataSource;
import com.google.android.exoplayer2.upstream.cache.Cache;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.ArrayList;
......@@ -44,7 +45,7 @@ public final class CacheAsserts {
ArrayList<FakeData> allData = fakeDataSet.getAllData();
dataSpecs = new DataSpec[allData.size()];
for (int i = 0; i < dataSpecs.length; i++) {
dataSpecs[i] = new DataSpec(allData.get(i).uri);
dataSpecs[i] = new DataSpec(Assertions.checkNotNull(allData.get(i).uri));
}
}
......@@ -74,7 +75,7 @@ public final class CacheAsserts {
}
public byte[] getData(int i) {
return fakeDataSet.getData(dataSpecs[i].uri).getData();
return Assertions.checkNotNull(fakeDataSet.getData(dataSpecs[i].uri)).getData();
}
public DataSpec getDataSpec(int i) {
......@@ -82,10 +83,10 @@ public final class CacheAsserts {
}
public RequestSet useBoundedDataSpecFor(String uriString) {
FakeData data = fakeDataSet.getData(uriString);
FakeData data = Assertions.checkStateNotNull(fakeDataSet.getData(uriString));
for (int i = 0; i < dataSpecs.length; i++) {
DataSpec spec = dataSpecs[i];
if (spec.uri.getPath().equals(uriString)) {
if (Assertions.checkNotNull(spec.uri.getPath()).equals(uriString)) {
dataSpecs[i] = spec.subrange(0, data.getData().length);
return this;
}
......@@ -148,13 +149,10 @@ public final class CacheAsserts {
*/
public static void assertReadData(DataSource dataSource, DataSpec dataSpec, byte[] expected)
throws IOException {
byte[] bytes = null;
try (DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec)) {
bytes = Util.toByteArray(inputStream);
} catch (IOException e) {
// Ignore
byte[] bytes = Util.toByteArray(inputStream);
assertThat(bytes).isEqualTo(expected);
}
assertThat(bytes).isEqualTo(expected);
}
/** Asserts that the cache is empty. */
......
......@@ -18,9 +18,9 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertWithMessage;
import android.os.ConditionVariable;
import android.os.Looper;
import android.os.SystemClock;
import android.view.Surface;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
......@@ -41,6 +41,8 @@ import com.google.android.exoplayer2.util.EventLogger;
import com.google.android.exoplayer2.util.HandlerWrapper;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** A {@link HostedTest} for {@link ExoPlayer} playback tests. */
public abstract class ExoHostedTest implements AnalyticsListener, HostedTest {
......@@ -64,12 +66,12 @@ public abstract class ExoHostedTest implements AnalyticsListener, HostedTest {
private final DecoderCounters audioDecoderCounters;
private final ConditionVariable testFinished;
private ActionSchedule pendingSchedule;
private HandlerWrapper actionHandler;
private DefaultTrackSelector trackSelector;
private SimpleExoPlayer player;
private Surface surface;
private ExoPlaybackException playerError;
@Nullable private ActionSchedule pendingSchedule;
private @MonotonicNonNull SimpleExoPlayer player;
private @MonotonicNonNull HandlerWrapper actionHandler;
private @MonotonicNonNull DefaultTrackSelector trackSelector;
private @MonotonicNonNull Surface surface;
private @MonotonicNonNull ExoPlaybackException playerError;
private boolean playerWasPrepared;
private boolean playing;
......@@ -115,7 +117,7 @@ public abstract class ExoHostedTest implements AnalyticsListener, HostedTest {
* @param schedule The schedule.
*/
public final void setSchedule(ActionSchedule schedule) {
if (player == null) {
if (!isStarted()) {
pendingSchedule = schedule;
} else {
schedule.start(player, trackSelector, surface, actionHandler, /* callback= */ null);
......@@ -135,7 +137,7 @@ public abstract class ExoHostedTest implements AnalyticsListener, HostedTest {
player.addAnalyticsListener(this);
player.addAnalyticsListener(new EventLogger(trackSelector, tag));
// Schedule any pending actions.
actionHandler = Clock.DEFAULT.createHandler(Looper.myLooper(), /* callback= */ null);
actionHandler = Clock.DEFAULT.createHandler(Util.getLooper(), /* callback= */ null);
if (pendingSchedule != null) {
pendingSchedule.start(player, trackSelector, surface, actionHandler, /* callback= */ null);
pendingSchedule = null;
......@@ -216,13 +218,12 @@ public abstract class ExoHostedTest implements AnalyticsListener, HostedTest {
// Internal logic
private boolean stopTest() {
if (player == null) {
if (!isStarted()) {
return false;
}
actionHandler.removeCallbacksAndMessages(null);
sourceDurationMs = player.getDuration();
player.release();
player = null;
// We post opening of the finished condition so that any events posted to the main thread as a
// result of player.release() are guaranteed to be handled before the test returns.
actionHandler.post(testFinished::open);
......@@ -261,4 +262,17 @@ public abstract class ExoHostedTest implements AnalyticsListener, HostedTest {
protected void onTestFinished(DecoderCounters audioCounters, DecoderCounters videoCounters) {
// Do nothing. Subclasses may override to add clean-up and assertions.
}
@EnsuresNonNullIf(
result = true,
expression = {"player", "actionHandler", "trackSelector", "surface"})
private boolean isStarted() {
if (player == null) {
return false;
}
Util.castNonNull(actionHandler);
Util.castNonNull(trackSelector);
Util.castNonNull(surface);
return true;
}
}
......@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispat
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Util;
/**
* Fake {@link MediaSource} that provides a given timeline. Creating the period returns a
......@@ -47,7 +48,7 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
Allocator allocator,
EventDispatcher eventDispatcher,
@Nullable TransferListener transferListener) {
Period period = timeline.getPeriodByUid(id.periodUid, new Period());
Period period = Util.castNonNull(getTimeline()).getPeriodByUid(id.periodUid, new Period());
return new FakeAdaptiveMediaPeriod(
trackGroupArray,
eventDispatcher,
......
......@@ -31,8 +31,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import java.util.List;
/**
......@@ -93,7 +93,7 @@ public final class FakeChunkSource implements ChunkSource {
}
@Override
public void maybeThrowError() throws IOException {
public void maybeThrowError() {
// Do nothing.
}
......@@ -128,7 +128,8 @@ public final class FakeChunkSource implements ChunkSource {
long endTimeUs = startTimeUs + dataSet.getChunkDuration(chunkIndex);
int trackGroupIndex = trackSelection.getIndexInTrackGroup(trackSelection.getSelectedIndex());
String uri = dataSet.getUri(trackGroupIndex);
Segment fakeDataChunk = dataSet.getData(uri).getSegments().get(chunkIndex);
Segment fakeDataChunk =
Assertions.checkStateNotNull(dataSet.getData(uri)).getSegments().get(chunkIndex);
DataSpec dataSpec = new DataSpec(Uri.parse(uri), fakeDataChunk.byteOffset,
fakeDataChunk.length, null);
int trackType = MimeTypes.getTrackType(selectedFormat.sampleMimeType);
......
......@@ -272,7 +272,7 @@ public class FakeMediaPeriod implements MediaPeriod {
private void finishPreparation() {
prepared = true;
prepareCallback.onPrepared(this);
Util.castNonNull(prepareCallback).onPrepared(this);
eventDispatcher.loadCompleted(
FAKE_DATA_SPEC,
FAKE_DATA_SPEC.uri,
......
......@@ -43,6 +43,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Fake {@link MediaSource} that provides a given timeline. Creating the period will return a {@link
......@@ -73,17 +74,17 @@ public class FakeMediaSource extends BaseMediaSource {
private final ArrayList<FakeMediaPeriod> activeMediaPeriods;
private final ArrayList<MediaPeriodId> createdMediaPeriods;
protected Timeline timeline;
private @MonotonicNonNull Timeline timeline;
private boolean preparedSource;
private boolean releasedSource;
private Handler sourceInfoRefreshHandler;
@Nullable private Handler sourceInfoRefreshHandler;
@Nullable private TransferListener transferListener;
/**
* Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with a
* {@link TrackGroupArray} using the given {@link Format}s. The provided {@link Timeline} may be
* null to prevent an immediate source info refresh message when preparing the media source. It
* can be manually set later using {@link #setNewSourceInfo(Timeline, Object)}.
* can be manually set later using {@link #setNewSourceInfo(Timeline)}.
*/
public FakeMediaSource(@Nullable Timeline timeline, Format... formats) {
this(timeline, buildTrackGroupArray(formats));
......@@ -93,20 +94,29 @@ public class FakeMediaSource extends BaseMediaSource {
* Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with the
* given {@link TrackGroupArray}. The provided {@link Timeline} may be null to prevent an
* immediate source info refresh message when preparing the media source. It can be manually set
* later using {@link #setNewSourceInfo(Timeline, Object)}.
* later using {@link #setNewSourceInfo(Timeline)}.
*/
public FakeMediaSource(@Nullable Timeline timeline, TrackGroupArray trackGroupArray) {
this.timeline = timeline;
if (timeline != null) {
this.timeline = timeline;
}
this.trackGroupArray = trackGroupArray;
this.activeMediaPeriods = new ArrayList<>();
this.createdMediaPeriods = new ArrayList<>();
this.trackGroupArray = trackGroupArray;
}
@Nullable
protected Timeline getTimeline() {
return timeline;
}
@Override
@Nullable
public Object getTag() {
boolean hasTimeline = timeline != null && !timeline.isEmpty();
return hasTimeline ? timeline.getWindow(0, new Timeline.Window()).tag : null;
if (timeline == null || timeline.isEmpty()) {
return null;
}
return timeline.getWindow(0, new Timeline.Window()).tag;
}
@Nullable
......@@ -143,7 +153,7 @@ public class FakeMediaSource extends BaseMediaSource {
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
assertThat(preparedSource).isTrue();
assertThat(releasedSource).isFalse();
int periodIndex = timeline.getIndexOfPeriod(id.periodUid);
int periodIndex = Util.castNonNull(timeline).getIndexOfPeriod(id.periodUid);
Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period());
EventDispatcher eventDispatcher =
......@@ -171,15 +181,15 @@ public class FakeMediaSource extends BaseMediaSource {
assertThat(activeMediaPeriods.isEmpty()).isTrue();
releasedSource = true;
preparedSource = false;
sourceInfoRefreshHandler.removeCallbacksAndMessages(null);
Util.castNonNull(sourceInfoRefreshHandler).removeCallbacksAndMessages(null);
sourceInfoRefreshHandler = null;
}
/**
* Sets a new timeline and manifest. If the source is already prepared, this triggers a source
* info refresh message being sent to the listener.
* Sets a new timeline. If the source is already prepared, this triggers a source info refresh
* message being sent to the listener.
*/
public synchronized void setNewSourceInfo(final Timeline newTimeline, final Object newManifest) {
public synchronized void setNewSourceInfo(final Timeline newTimeline) {
if (sourceInfoRefreshHandler != null) {
sourceInfoRefreshHandler.post(
() -> {
......@@ -238,7 +248,7 @@ public class FakeMediaSource extends BaseMediaSource {
}
private void finishSourcePreparation() {
refreshSourceInfo(timeline);
refreshSourceInfo(Assertions.checkStateNotNull(timeline));
if (!timeline.isEmpty()) {
MediaLoadData mediaLoadData =
new MediaLoadData(
......
......@@ -29,9 +29,11 @@ import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** A host activity for performing playback tests. */
public final class HostActivity extends Activity implements SurfaceHolder.Callback {
......@@ -81,13 +83,13 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
private static final String LOCK_TAG = "ExoPlayerTestUtil:" + TAG;
private static final long START_TIMEOUT_MS = 5000;
private WakeLock wakeLock;
private WifiLock wifiLock;
private SurfaceView surfaceView;
@Nullable private WakeLock wakeLock;
@Nullable private WifiLock wifiLock;
private @MonotonicNonNull SurfaceView surfaceView;
private HostedTest hostedTest;
@Nullable private HostedTest hostedTest;
private boolean hostedTestStarted;
private ConditionVariable hostedTestStartedCondition;
private @MonotonicNonNull ConditionVariable hostedTestStartedCondition;
private boolean forcedStopped;
/**
......@@ -161,7 +163,7 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
// Activity lifecycle
@Override
public void onCreate(Bundle savedInstanceState) {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(
......@@ -174,10 +176,14 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
@Override
public void onStart() {
Context appContext = getApplicationContext();
WifiManager wifiManager = (WifiManager) appContext.getSystemService(Context.WIFI_SERVICE);
WifiManager wifiManager =
Assertions.checkStateNotNull(
(WifiManager) appContext.getSystemService(Context.WIFI_SERVICE));
wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, LOCK_TAG);
wifiLock.acquire();
PowerManager powerManager = (PowerManager) appContext.getSystemService(Context.POWER_SERVICE);
PowerManager powerManager =
Assertions.checkStateNotNull(
(PowerManager) appContext.getSystemService(Context.POWER_SERVICE));
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOCK_TAG);
wakeLock.acquire();
super.onStart();
......@@ -197,10 +203,14 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
if (Util.SDK_INT > 23) {
maybeStopHostedTest();
}
wakeLock.release();
wakeLock = null;
wifiLock.release();
wifiLock = null;
if (wakeLock != null) {
wakeLock.release();
wakeLock = null;
}
if (wifiLock != null) {
wifiLock.release();
wifiLock = null;
}
}
// SurfaceHolder.Callback
......@@ -226,12 +236,12 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
if (hostedTest == null || hostedTestStarted) {
return;
}
Surface surface = surfaceView.getHolder().getSurface();
@Nullable Surface surface = Util.castNonNull(surfaceView).getHolder().getSurface();
if (surface != null && surface.isValid()) {
hostedTestStarted = true;
Log.d(TAG, "Starting test.");
hostedTest.onStart(this, surface);
hostedTestStartedCondition.open();
Util.castNonNull(hostedTest).onStart(this, surface);
Util.castNonNull(hostedTestStartedCondition).open();
}
}
......
......@@ -187,7 +187,7 @@ public final class MediaPeriodAsserts {
}
private static TrackGroupArray getTrackGroups(MediaPeriod mediaPeriod) {
AtomicReference<TrackGroupArray> trackGroupArray = new AtomicReference<>(null);
AtomicReference<TrackGroupArray> trackGroupArray = new AtomicReference<>();
DummyMainThread dummyMainThread = new DummyMainThread();
ConditionVariable preparedCondition = new ConditionVariable();
dummyMainThread.runOnMainThread(
......
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package com.google.android.exoplayer2.testutil;
import com.google.android.exoplayer2.util.NonNullApi;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment