From 7c8a54c6d0abfd998101efb0608a9117e01a6bf1 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 30 Jan 2020 15:05:32 +0000 Subject: [PATCH] Start fixing nullness in testutil PiperOrigin-RevId: 292340530 --- .../source/chunk/SingleSampleMediaChunk.java | 3 +- .../android/exoplayer2/ExoPlayerTest.java | 3 +- .../testutil/AutoAdvancingFakeClock.java | 3 +- .../testutil/CapturingAudioSink.java | 3 +- .../android/exoplayer2/testutil/Dumper.java | 14 +++- .../exoplayer2/testutil/ExtractorAsserts.java | 6 +- .../testutil/FakeAdaptiveDataSet.java | 3 +- .../testutil/FakeAdaptiveMediaPeriod.java | 14 ++-- .../exoplayer2/testutil/FakeClock.java | 13 ++-- .../exoplayer2/testutil/FakeDataSet.java | 36 +++++---- .../exoplayer2/testutil/FakeDataSource.java | 22 ++++-- .../testutil/FakeExtractorOutput.java | 18 +++-- .../exoplayer2/testutil/FakeMediaChunk.java | 3 +- .../exoplayer2/testutil/FakeMediaPeriod.java | 9 ++- .../exoplayer2/testutil/FakeRenderer.java | 2 +- .../exoplayer2/testutil/FakeTimeline.java | 4 +- .../exoplayer2/testutil/FakeTrackOutput.java | 74 +++++++++++-------- .../testutil/FakeTrackSelection.java | 2 + .../testutil/FakeTrackSelector.java | 16 ++-- .../exoplayer2/testutil/HostActivity.java | 4 +- .../exoplayer2/testutil/StubExoPlayer.java | 5 +- .../testutil/TestDownloadManagerListener.java | 20 +++-- .../exoplayer2/testutil/TimelineAsserts.java | 10 ++- 23 files changed, 175 insertions(+), 112 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java index 00d841eee0..c275c8dc2e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java @@ -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, diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java index ced29798db..640c8601ac 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -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() diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/AutoAdvancingFakeClock.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/AutoAdvancingFakeClock.java index 1d25429a67..a7d5e132d5 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/AutoAdvancingFakeClock.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/AutoAdvancingFakeClock.java @@ -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); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java index 7a766e225f..29645ca327 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CapturingAudioSink.java @@ -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(); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/Dumper.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/Dumper.java index e3461224c2..8175c9032d 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/Dumper.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/Dumper.java @@ -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); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java index 050898a20e..135515c245 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExtractorAsserts.java @@ -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); } - } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveDataSet.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveDataSet.java index 0fef8db78e..219fa1cf57 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveDataSet.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveDataSet.java @@ -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); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java index 21f2a045d9..d930b2a9a4 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java @@ -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[] 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) 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 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. diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java index a591546613..c3c4d5c97f 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeClock.java @@ -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); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java index 286ef15b15..13cc6b6ae0 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java @@ -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 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 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 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; } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java index ab7c5be5b2..2c21c8866c 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java @@ -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 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; diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java index 74a554df76..b3d7e7469a 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java @@ -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(); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java index fd7be241df..0286531fc8 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java @@ -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. } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java index ed71c4e2da..e9cf33c03a 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java @@ -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; diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java index 987a9e33c1..2be7e89e47 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java @@ -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; diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java index ce58aa5ca8..5b882dd9a5 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java @@ -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 { /** diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java index 0389569a49..bab60c3764 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java @@ -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 sampleFlags; private final ArrayList sampleStartOffsets; private final ArrayList sampleEndOffsets; - private final ArrayList 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()); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelection.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelection.java index b479ebed29..5e034058a0 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelection.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelection.java @@ -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; } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelector.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelector.java index ac39ba8de6..2d5160eeef 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelector.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackSelector.java @@ -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]; diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/HostActivity.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/HostActivity.java index 39429a8fa1..89d7b3b638 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/HostActivity.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/HostActivity.java @@ -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 { /** diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java index 62666eac09..12f1ed55cf 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java @@ -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(); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java index c42071d0a2..48e85427b1 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java @@ -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 getStateQueue(String taskId) { synchronized (downloadStates) { - if (!downloadStates.containsKey(taskId)) { - downloadStates.put(taskId, new ArrayBlockingQueue<>(10)); + @Nullable ArrayBlockingQueue 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) { diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TimelineAsserts.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TimelineAsserts.java index f3ec47a88b..7d31bc7ee3 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TimelineAsserts.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TimelineAsserts.java @@ -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))