Start fixing nullness in testutil

PiperOrigin-RevId: 292340530
This commit is contained in:
olly 2020-01-30 15:05:32 +00:00 committed by Oliver Woodman
parent ff822ff9fd
commit 7c8a54c6d0
23 changed files with 175 additions and 112 deletions

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.chunk;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
@ -54,7 +55,7 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
DataSpec dataSpec,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
@Nullable Object trackSelectionData,
long startTimeUs,
long endTimeUs,
long chunkIndex,

View File

@ -821,7 +821,8 @@ public final class ExoPlayerTest {
new FakeMediaSource(timeline, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT);
FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT);
FakeRenderer audioRenderer = new FakeRenderer(Builder.AUDIO_FORMAT);
final FakeTrackSelector trackSelector = new FakeTrackSelector(/* reuse track selection */ true);
final FakeTrackSelector trackSelector =
new FakeTrackSelector(/* mayReuseTrackSelection= */ true);
ActionSchedule disableTrackAction =
new ActionSchedule.Builder("testReuseTrackSelection")
.pause()

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import com.google.android.exoplayer2.util.HandlerWrapper;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* {@link FakeClock} extension which automatically advances time whenever an empty message is
@ -25,7 +26,7 @@ import com.google.android.exoplayer2.util.HandlerWrapper;
*/
public final class AutoAdvancingFakeClock extends FakeClock {
private HandlerWrapper autoAdvancingHandler;
private @MonotonicNonNull HandlerWrapper autoAdvancingHandler;
public AutoAdvancingFakeClock() {
super(/* initialTimeMs= */ 0);

View File

@ -21,6 +21,7 @@ import android.content.Context;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.audio.ForwardingAudioSink;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.File;
import java.io.IOException;
@ -122,7 +123,7 @@ public final class CapturingAudioSink extends ForwardingAudioSink implements Dum
if (WRITE_DUMP) {
File directory = context.getExternalFilesDir(null);
File file = new File(directory, dumpFile);
file.getParentFile().mkdirs();
Assertions.checkStateNotNull(file.getParentFile()).mkdirs();
PrintWriter out = new PrintWriter(file);
out.print(actual);
out.close();

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.testutil;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import java.util.Arrays;
import java.util.Locale;
@ -44,7 +45,7 @@ public final class Dumper {
sb = new StringBuilder();
}
public Dumper add(String field, Object value) {
public Dumper add(String field, @Nullable Object value) {
return addString(field + " = " + value + '\n');
}
@ -53,9 +54,14 @@ public final class Dumper {
return this;
}
public Dumper add(String field, byte[] value) {
String string = String.format(Locale.US, "%s = length %d, hash %X\n", field, value.length,
Arrays.hashCode(value));
public Dumper add(String field, @Nullable byte[] value) {
String string =
String.format(
Locale.US,
"%s = length %d, hash %X\n",
field,
value == null ? 0 : value.length,
Arrays.hashCode(value));
return addString(string);
}

View File

@ -209,7 +209,7 @@ public final class ExtractorAsserts {
}
// If the SeekMap is seekable, test seeking in the stream.
SeekMap seekMap = extractorOutput.seekMap;
SeekMap seekMap = Assertions.checkNotNull(extractorOutput.seekMap);
if (seekMap.isSeekable()) {
long durationUs = seekMap.getDurationUs();
for (int j = 0; j < 4; j++) {
@ -361,7 +361,7 @@ public final class ExtractorAsserts {
int i = fileName.lastIndexOf('/');
String path = i >= 0 ? fileName.substring(0, i) : "";
String file = i >= 0 ? fileName.substring(i + 1) : fileName;
return Arrays.asList(context.getResources().getAssets().list(path)).contains(file);
String[] assets = context.getResources().getAssets().list(path);
return assets != null && Arrays.asList(assets).contains(file);
}
}

View File

@ -23,6 +23,7 @@ import com.google.android.exoplayer2.source.chunk.BaseMediaChunkIterator;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Util;
import java.util.Random;
/**
@ -92,7 +93,7 @@ public final class FakeAdaptiveDataSet extends FakeDataSet {
checkInBounds();
String uri = dataSet.getUri(trackGroupIndex);
int chunkIndex = (int) getCurrentIndex();
Segment fakeDataChunk = dataSet.getData(uri).getSegments().get(chunkIndex);
Segment fakeDataChunk = Util.castNonNull(dataSet.getData(uri)).getSegments().get(chunkIndex);
return new DataSpec(
Uri.parse(uri), fakeDataChunk.byteOffset, fakeDataChunk.length, /* key= */ null);
}

View File

@ -28,9 +28,12 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Fake {@link MediaPeriod} that provides tracks from the given {@link TrackGroupArray}. Selecting a
@ -44,7 +47,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Nullable private final TransferListener transferListener;
private final long durationUs;
private Callback callback;
@MonotonicNonNull private Callback callback;
private ChunkSampleStream<FakeChunkSource>[] sampleStreams;
private SequenceableLoader sequenceableLoader;
@ -81,9 +84,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Override
@SuppressWarnings("unchecked")
public long selectTracks(
TrackSelection[] selections,
@NullableType TrackSelection[] selections,
boolean[] mayRetainStreamFlags,
SampleStream[] streams,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
long positionUs) {
long returnPositionUs = super.selectTracks(selections, mayRetainStreamFlags, streams,
@ -94,7 +97,8 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
validStreams.add((ChunkSampleStream<FakeChunkSource>) stream);
}
}
this.sampleStreams = validStreams.toArray(newSampleStreamArray(validStreams.size()));
sampleStreams = newSampleStreamArray(validStreams.size());
validStreams.toArray(sampleStreams);
this.sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return returnPositionUs;
}
@ -162,7 +166,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Override
public void onContinueLoadingRequested(ChunkSampleStream<FakeChunkSource> source) {
callback.onContinueLoadingRequested(this);
Assertions.checkStateNotNull(callback).onContinueLoadingRequested(this);
}
// We won't assign the array to a variable that erases the generic type, and then write into it.

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
import android.os.Handler.Callback;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.HandlerWrapper;
import java.util.ArrayList;
@ -90,7 +91,7 @@ public class FakeClock implements Clock {
}
@Override
public HandlerWrapper createHandler(Looper looper, Callback callback) {
public HandlerWrapper createHandler(Looper looper, @Nullable Callback callback) {
return new ClockHandler(looper, callback);
}
@ -119,7 +120,7 @@ public class FakeClock implements Clock {
private final long postTime;
private final HandlerWrapper handler;
private final Runnable runnable;
@Nullable private final Runnable runnable;
private final int message;
public HandlerMessageData(long postTime, HandlerWrapper handler, Runnable runnable) {
@ -155,7 +156,7 @@ public class FakeClock implements Clock {
private final android.os.Handler handler;
public ClockHandler(Looper looper, Callback callback) {
public ClockHandler(Looper looper, @Nullable Callback callback) {
handler = new android.os.Handler(looper, callback);
}
@ -170,7 +171,7 @@ public class FakeClock implements Clock {
}
@Override
public Message obtainMessage(int what, Object obj) {
public Message obtainMessage(int what, @Nullable Object obj) {
return handler.obtainMessage(what, obj);
}
@ -180,7 +181,7 @@ public class FakeClock implements Clock {
}
@Override
public Message obtainMessage(int what, int arg1, int arg2, Object obj) {
public Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
return handler.obtainMessage(what, arg1, arg2, obj);
}
@ -200,7 +201,7 @@ public class FakeClock implements Clock {
}
@Override
public void removeCallbacksAndMessages(Object token) {
public void removeCallbacksAndMessages(@Nullable Object token) {
handler.removeCallbacksAndMessages(token);
}

View File

@ -89,24 +89,28 @@ public class FakeDataSet {
public boolean exceptionCleared;
public int bytesRead;
private Segment(byte[] data, Segment previousSegment) {
private Segment(byte[] data, @Nullable Segment previousSegment) {
this(data, data.length, null, null, previousSegment);
}
private Segment(int length, Segment previousSegment) {
private Segment(int length, @Nullable Segment previousSegment) {
this(null, length, null, null, previousSegment);
}
private Segment(IOException exception, Segment previousSegment) {
private Segment(IOException exception, @Nullable Segment previousSegment) {
this(null, 0, exception, null, previousSegment);
}
private Segment(Runnable action, Segment previousSegment) {
private Segment(Runnable action, @Nullable Segment previousSegment) {
this(null, 0, null, action, previousSegment);
}
private Segment(@Nullable byte[] data, int length, @Nullable IOException exception,
@Nullable Runnable action, Segment previousSegment) {
private Segment(
@Nullable byte[] data,
int length,
@Nullable IOException exception,
@Nullable Runnable action,
@Nullable Segment previousSegment) {
this.exception = exception;
this.action = action;
this.data = data;
@ -125,16 +129,17 @@ public class FakeDataSet {
}
/** Uri of the data or null if this is the default FakeData. */
public final Uri uri;
private final ArrayList<Segment> segments;
private final FakeDataSet dataSet;
/** Uri of the data or null if this is the default FakeData. */
@Nullable public final Uri uri;
private final ArrayList<Segment> segments;
private boolean simulateUnknownLength;
private FakeData(FakeDataSet dataSet, Uri uri) {
private FakeData(FakeDataSet dataSet, @Nullable Uri uri) {
this.dataSet = dataSet;
this.uri = uri;
this.segments = new ArrayList<>();
this.dataSet = dataSet;
}
/** Returns the {@link FakeDataSet} this FakeData belongs to. */
@ -157,7 +162,7 @@ public class FakeDataSet {
* Appends to the underlying data.
*/
public FakeData appendReadData(byte[] data) {
Assertions.checkState(data != null && data.length > 0);
Assertions.checkState(data.length > 0);
segments.add(new Segment(data, getLastSegment()));
return this;
}
@ -213,6 +218,7 @@ public class FakeDataSet {
return simulateUnknownLength;
}
@Nullable
private Segment getLastSegment() {
int count = segments.size();
return count > 0 ? segments.get(count - 1) : null;
@ -221,7 +227,7 @@ public class FakeDataSet {
}
private final HashMap<Uri, FakeData> dataMap;
private FakeData defaultData;
@Nullable private FakeData defaultData;
public FakeDataSet() {
dataMap = new HashMap<>();
@ -266,13 +272,15 @@ public class FakeDataSet {
}
/** Returns the data for the given {@code uri}, or {@code defaultData} if no data is set. */
@Nullable
public FakeData getData(String uri) {
return getData(Uri.parse(uri));
}
/** Returns the data for the given {@code uri}, or {@code defaultData} if no data is set. */
@Nullable
public FakeData getData(Uri uri) {
FakeData data = dataMap.get(uri);
@Nullable FakeData data = dataMap.get(uri);
return data != null ? data : defaultData;
}

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import android.net.Uri;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
@ -24,8 +25,10 @@ import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceException;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.ArrayList;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A fake {@link DataSource} capable of simulating various scenarios. It uses a {@link FakeDataSet}
@ -38,7 +41,7 @@ public class FakeDataSource extends BaseDataSource {
*/
public static class Factory implements DataSource.Factory {
protected FakeDataSet fakeDataSet;
protected @MonotonicNonNull FakeDataSet fakeDataSet;
protected boolean isNetwork;
public final Factory setFakeDataSet(FakeDataSet fakeDataSet) {
@ -53,17 +56,17 @@ public class FakeDataSource extends BaseDataSource {
@Override
public FakeDataSource createDataSource() {
return new FakeDataSource(fakeDataSet, isNetwork);
return new FakeDataSource(Assertions.checkStateNotNull(fakeDataSet), isNetwork);
}
}
private final FakeDataSet fakeDataSet;
private final ArrayList<DataSpec> openedDataSpecs;
private Uri uri;
@Nullable private Uri uri;
private boolean openCalled;
private boolean sourceOpened;
private FakeData fakeData;
@Nullable private FakeData fakeData;
private int currentSegmentIndex;
private long bytesRemaining;
@ -96,10 +99,11 @@ public class FakeDataSource extends BaseDataSource {
openedDataSpecs.add(dataSpec);
transferInitializing(dataSpec);
fakeData = fakeDataSet.getData(uri.toString());
FakeData fakeData = fakeDataSet.getData(dataSpec.uri.toString());
if (fakeData == null) {
throw new IOException("Data not found: " + dataSpec.uri);
}
this.fakeData = fakeData;
long totalLength = 0;
for (Segment segment : fakeData.getSegments()) {
@ -145,6 +149,7 @@ public class FakeDataSource extends BaseDataSource {
public final int read(byte[] buffer, int offset, int readLength) throws IOException {
Assertions.checkState(sourceOpened);
while (true) {
FakeData fakeData = Util.castNonNull(this.fakeData);
if (currentSegmentIndex == fakeData.getSegments().size() || bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
@ -152,13 +157,13 @@ public class FakeDataSource extends BaseDataSource {
if (current.isErrorSegment()) {
if (!current.exceptionCleared) {
current.exceptionThrown = true;
throw (IOException) current.exception.fillInStackTrace();
throw (IOException) Util.castNonNull(current.exception).fillInStackTrace();
} else {
currentSegmentIndex++;
}
} else if (current.isActionSegment()) {
currentSegmentIndex++;
current.action.run();
Util.castNonNull(current.action).run();
} else {
// Read at most bytesRemaining.
readLength = (int) Math.min(readLength, bytesRemaining);
@ -181,13 +186,14 @@ public class FakeDataSource extends BaseDataSource {
}
}
@Nullable
@Override
public final Uri getUri() {
return uri;
}
@Override
public final void close() throws IOException {
public final void close() {
Assertions.checkState(openCalled);
openCalled = false;
uri = null;

View File

@ -20,12 +20,15 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.content.Context;
import android.util.SparseArray;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.util.Assertions;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A fake {@link ExtractorOutput}.
@ -45,7 +48,7 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
public int numberOfTracks;
public boolean tracksEnded;
public SeekMap seekMap;
public @MonotonicNonNull SeekMap seekMap;
public FakeExtractorOutput() {
trackOutputs = new SparseArray<>();
@ -53,7 +56,7 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
@Override
public FakeTrackOutput track(int id, int type) {
FakeTrackOutput output = trackOutputs.get(id);
@Nullable FakeTrackOutput output = trackOutputs.get(id);
if (output == null) {
assertThat(tracksEnded).isFalse();
numberOfTracks++;
@ -99,10 +102,11 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
assertThat(seekMap).isNull();
} else {
// TODO: Bulk up this check if possible.
assertThat(seekMap).isNotNull();
assertThat(seekMap.getClass()).isEqualTo(expected.seekMap.getClass());
assertThat(seekMap.isSeekable()).isEqualTo(expected.seekMap.isSeekable());
assertThat(seekMap.getSeekPoints(0)).isEqualTo(expected.seekMap.getSeekPoints(0));
SeekMap expectedSeekMap = Assertions.checkNotNull(expected.seekMap);
SeekMap seekMap = Assertions.checkNotNull(this.seekMap);
assertThat(seekMap.getClass()).isEqualTo(expectedSeekMap.getClass());
assertThat(seekMap.isSeekable()).isEqualTo(expectedSeekMap.isSeekable());
assertThat(seekMap.getSeekPoints(0)).isEqualTo(expectedSeekMap.getSeekPoints(0));
}
for (int i = 0; i < numberOfTracks; i++) {
assertThat(trackOutputs.keyAt(i)).isEqualTo(expected.trackOutputs.keyAt(i));
@ -125,7 +129,7 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
if (WRITE_DUMP) {
File file = new File(System.getProperty("user.dir"), "src/test/assets");
file = new File(file, dumpFile);
file.getParentFile().mkdirs();
Assertions.checkStateNotNull(file.getParentFile()).mkdirs();
PrintWriter out = new PrintWriter(file);
out.print(actual);
out.close();

View File

@ -22,7 +22,6 @@ import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import java.io.IOException;
/** Fake {@link MediaChunk}. */
public final class FakeMediaChunk extends MediaChunk {
@ -51,7 +50,7 @@ public final class FakeMediaChunk extends MediaChunk {
}
@Override
public void load() throws IOException, InterruptedException {
public void load() {
// Do nothing.
}

View File

@ -35,6 +35,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* Fake {@link MediaPeriod} that provides tracks from the given {@link TrackGroupArray}. Selecting
@ -149,8 +150,12 @@ public class FakeMediaPeriod implements MediaPeriod {
}
@Override
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
public long selectTracks(
@NullableType TrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
long positionUs) {
assertThat(prepared).isTrue();
sampleStreams.clear();
int rendererCount = selections.length;

View File

@ -84,7 +84,7 @@ public class FakeRenderer extends BaseRenderer {
if (result == C.RESULT_FORMAT_READ) {
formatReadCount++;
assertThat(expectedFormats).contains(formatHolder.format);
onFormatChanged(formatHolder.format);
onFormatChanged(Assertions.checkNotNull(formatHolder.format));
} else if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) {
isEnded = true;

View File

@ -24,9 +24,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
/**
* Fake {@link Timeline} which can be setup to return custom {@link TimelineWindowDefinition}s.
*/
/** Fake {@link Timeline} which can be setup to return custom {@link TimelineWindowDefinition}s. */
public final class FakeTimeline extends Timeline {
/**

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.ExtractorInput;
@ -29,6 +30,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A fake {@link TrackOutput}.
@ -39,10 +42,10 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
private final ArrayList<Integer> sampleFlags;
private final ArrayList<Integer> sampleStartOffsets;
private final ArrayList<Integer> sampleEndOffsets;
private final ArrayList<CryptoData> cryptoDatas;
private final ArrayList<@NullableType CryptoData> cryptoDatas;
private byte[] sampleData;
public Format format;
public @MonotonicNonNull Format format;
public FakeTrackOutput() {
sampleData = Util.EMPTY_BYTE_ARRAY;
@ -64,6 +67,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
@Override
public void format(Format format) {
// TODO: Capture and assert all formats (interleaved with the samples).
this.format = format;
}
@ -91,8 +95,12 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
}
@Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset,
CryptoData cryptoData) {
public void sampleMetadata(
long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData cryptoData) {
if (format == null) {
throw new IllegalStateException("TrackOutput must receive format before sampleMetadata");
}
@ -110,7 +118,8 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
assertThat(sampleTimesUs).hasSize(count);
}
public void assertSample(int index, byte[] data, long timeUs, int flags, CryptoData cryptoData) {
public void assertSample(
int index, byte[] data, long timeUs, int flags, @Nullable CryptoData cryptoData) {
byte[] actualData = getSampleData(index);
assertThat(actualData).isEqualTo(data);
assertThat(sampleTimesUs.get(index)).isEqualTo(timeUs);
@ -131,6 +140,7 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
return sampleFlags.get(index);
}
@Nullable
public CryptoData getSampleCryptoData(int index) {
return cryptoDatas.get(index);
}
@ -162,34 +172,36 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
@Override
public void dump(Dumper dumper) {
dumper
.startBlock("format")
.add("bitrate", format.bitrate)
.add("id", format.id)
.add("containerMimeType", format.containerMimeType)
.add("sampleMimeType", format.sampleMimeType)
.add("maxInputSize", format.maxInputSize)
.add("width", format.width)
.add("height", format.height)
.add("frameRate", format.frameRate)
.add("rotationDegrees", format.rotationDegrees)
.add("pixelWidthHeightRatio", format.pixelWidthHeightRatio)
.add("channelCount", format.channelCount)
.add("sampleRate", format.sampleRate)
.add("pcmEncoding", format.pcmEncoding)
.add("encoderDelay", format.encoderDelay)
.add("encoderPadding", format.encoderPadding)
.add("subsampleOffsetUs", format.subsampleOffsetUs)
.add("selectionFlags", format.selectionFlags)
.add("language", format.language)
.add("drmInitData", format.drmInitData != null ? format.drmInitData.hashCode() : "-")
.add("metadata", format.metadata);
if (format != null) {
dumper
.startBlock("format")
.add("bitrate", format.bitrate)
.add("id", format.id)
.add("containerMimeType", format.containerMimeType)
.add("sampleMimeType", format.sampleMimeType)
.add("maxInputSize", format.maxInputSize)
.add("width", format.width)
.add("height", format.height)
.add("frameRate", format.frameRate)
.add("rotationDegrees", format.rotationDegrees)
.add("pixelWidthHeightRatio", format.pixelWidthHeightRatio)
.add("channelCount", format.channelCount)
.add("sampleRate", format.sampleRate)
.add("pcmEncoding", format.pcmEncoding)
.add("encoderDelay", format.encoderDelay)
.add("encoderPadding", format.encoderPadding)
.add("subsampleOffsetUs", format.subsampleOffsetUs)
.add("selectionFlags", format.selectionFlags)
.add("language", format.language)
.add("drmInitData", format.drmInitData != null ? format.drmInitData.hashCode() : "-")
.add("metadata", format.metadata);
dumper.startBlock("initializationData");
for (int i = 0; i < format.initializationData.size(); i++) {
dumper.add("data", format.initializationData.get(i));
dumper.startBlock("initializationData");
for (int i = 0; i < format.initializationData.size(); i++) {
dumper.add("data", format.initializationData.get(i));
}
dumper.endBlock().endBlock();
}
dumper.endBlock().endBlock();
dumper.add("total output bytes", sampleData.length);
dumper.add("sample count", sampleTimesUs.size());

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.TrackGroup;
@ -109,6 +110,7 @@ public final class FakeTrackSelection implements TrackSelection {
}
@Override
@Nullable
public Object getSelectionData() {
return null;
}

View File

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.testutil;
import com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport;
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
@ -23,6 +25,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** A fake {@link MappingTrackSelector} that returns {@link FakeTrackSelection}s. */
public class FakeTrackSelector extends DefaultTrackSelector {
@ -30,7 +33,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
private final FakeTrackSelectionFactory fakeTrackSelectionFactory;
public FakeTrackSelector() {
this(false);
this(/* mayReuseTrackSelection= */ false);
}
/**
@ -48,13 +51,14 @@ public class FakeTrackSelector extends DefaultTrackSelector {
}
@Override
protected TrackSelection.Definition[] selectAllTracks(
protected TrackSelection.@NullableType Definition[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
int[][][] rendererFormatSupports,
int[] rendererMixedMimeTypeAdaptationSupports,
@Capabilities int[][][] rendererFormatSupports,
@AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports,
Parameters params) {
int rendererCount = mappedTrackInfo.getRendererCount();
TrackSelection.Definition[] definitions = new TrackSelection.Definition[rendererCount];
TrackSelection.@NullableType Definition[] definitions =
new TrackSelection.Definition[rendererCount];
for (int i = 0; i < rendererCount; i++) {
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(i);
boolean hasTracks = trackGroupArray.length > 0;
@ -80,7 +84,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
@Override
public TrackSelection[] createTrackSelections(
TrackSelection.Definition[] definitions, BandwidthMeter bandwidthMeter) {
@NullableType TrackSelection.Definition[] definitions, BandwidthMeter bandwidthMeter) {
TrackSelection[] selections = new TrackSelection[definitions.length];
for (int i = 0; i < definitions.length; i++) {
TrackSelection.Definition definition = definitions[i];

View File

@ -33,9 +33,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
/**
* A host activity for performing playback tests.
*/
/** A host activity for performing playback tests. */
public final class HostActivity extends Activity implements SurfaceHolder.Callback {
/**

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import android.os.Looper;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.BasePlayer;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
@ -250,7 +251,7 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
}
@Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) {
public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) {
throw new UnsupportedOperationException();
}
@ -260,7 +261,7 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
}
@Override
public void setSeekParameters(SeekParameters seekParameters) {
public void setSeekParameters(@Nullable SeekParameters seekParameters) {
throw new UnsupportedOperationException();
}

View File

@ -18,13 +18,16 @@ package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.offline.Download.State;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.util.Util;
import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** A {@link DownloadManager.Listener} for testing. */
public final class TestDownloadManagerListener implements DownloadManager.Listener {
@ -39,7 +42,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private final CountDownLatch initializedCondition;
private final int timeoutMs;
private CountDownLatch downloadFinishedCondition;
private @MonotonicNonNull CountDownLatch downloadFinishedCondition;
@Download.FailureReason private int failureReason;
public TestDownloadManagerListener(
@ -57,6 +60,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
downloadManager.addListener(this);
}
@Nullable
public Integer pollStateChange(String taskId, long timeoutMs) throws InterruptedException {
return getStateQueue(taskId).poll(timeoutMs, TimeUnit.MILLISECONDS);
}
@ -112,7 +116,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
dummyMainThread.runOnMainThread(
() -> {
if (downloadManager.isIdle()) {
downloadFinishedCondition.countDown();
Util.castNonNull(downloadFinishedCondition).countDown();
}
});
assertThat(downloadFinishedCondition.await(timeoutMs, TimeUnit.MILLISECONDS)).isTrue();
@ -120,10 +124,12 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private ArrayBlockingQueue<Integer> getStateQueue(String taskId) {
synchronized (downloadStates) {
if (!downloadStates.containsKey(taskId)) {
downloadStates.put(taskId, new ArrayBlockingQueue<>(10));
@Nullable ArrayBlockingQueue<Integer> stateQueue = downloadStates.get(taskId);
if (stateQueue == null) {
stateQueue = new ArrayBlockingQueue<>(10);
downloadStates.put(taskId, stateQueue);
}
return downloadStates.get(taskId);
return stateQueue;
}
}
@ -137,11 +143,11 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private void assertStateInternal(String taskId, int expectedState, int timeoutMs) {
while (true) {
Integer state = null;
@Nullable Integer state = null;
try {
state = pollStateChange(taskId, timeoutMs);
} catch (InterruptedException e) {
fail(e.getMessage());
fail("Interrupted: " + e.getMessage());
}
if (state != null) {
if (expectedState == state) {

View File

@ -22,6 +22,8 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.util.Assertions;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Unit test for {@link Timeline}. */
public final class TimelineAsserts {
@ -48,7 +50,8 @@ public final class TimelineAsserts {
* @param expectedWindowTags A list of expected window tags. If a tag is unknown or not important
* {@code null} can be passed to skip this window.
*/
public static void assertWindowTags(Timeline timeline, Object... expectedWindowTags) {
public static void assertWindowTags(
Timeline timeline, @NullableType Object... expectedWindowTags) {
Window window = new Window();
assertThat(timeline.getWindowCount()).isEqualTo(expectedWindowTags.length);
for (int i = 0; i < timeline.getWindowCount(); i++) {
@ -140,8 +143,9 @@ public final class TimelineAsserts {
expectedWindowIndex++;
}
assertThat(period.windowIndex).isEqualTo(expectedWindowIndex);
assertThat(timeline.getIndexOfPeriod(period.uid)).isEqualTo(i);
assertThat(timeline.getUidOfPeriod(i)).isEqualTo(period.uid);
Object periodUid = Assertions.checkNotNull(period.uid);
assertThat(timeline.getIndexOfPeriod(periodUid)).isEqualTo(i);
assertThat(timeline.getUidOfPeriod(i)).isEqualTo(periodUid);
for (int repeatMode : REPEAT_MODES) {
if (i < accumulatedPeriodCounts[expectedWindowIndex + 1] - 1) {
assertThat(timeline.getNextPeriodIndex(i, period, window, repeatMode, false))