diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java index e182e802fc..60aa19e364 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.ext.okhttp; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.net.Uri; import android.support.annotation.Nullable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java index 34cc88e794..0095001299 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.audio; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.media.AudioTimestamp; import android.media.AudioTrack; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java index a4a3b36e43..7d70d9de1c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.emsg; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java index 7f5b8dca12..53976da0d1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java index 449165fe07..c48829ae54 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java index a5f99de0fe..7ffb6d028c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.support.annotation.Nullable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java index 5797f7a237..c4a7c06e49 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.support.annotation.Nullable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java index ceba88f83f..5666e48939 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java index 2c4befcc12..990d8f2e48 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java index 5a8e2d64d5..c191676ce2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.support.annotation.Nullable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java index 7b8504229f..a10ce229d9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java index b7f83d5269..62175ee90c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java index c3c5d9b16d..4b35131bea 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java b/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java index 53c196a14f..c6ad5dfe52 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/Assertions.java @@ -104,6 +104,7 @@ public final class Assertions { * @return The non-null reference that was validated. * @throws NullPointerException If {@code reference} is null. */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) @EnsuresNonNull({"#1"}) public static T checkNotNull(@Nullable T reference) { if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) { @@ -122,6 +123,7 @@ public final class Assertions { * @return The non-null reference that was validated. * @throws NullPointerException If {@code reference} is null. */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) @EnsuresNonNull({"#1"}) public static T checkNotNull(@Nullable T reference, Object errorMessage) { if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && reference == null) { @@ -137,6 +139,7 @@ public final class Assertions { * @return The non-null, non-empty string that was validated. * @throws IllegalArgumentException If {@code string} is null or 0-length. */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) @EnsuresNonNull({"#1"}) public static String checkNotEmpty(@Nullable String string) { if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) { @@ -154,6 +157,7 @@ public final class Assertions { * @return The non-null, non-empty string that was validated. * @throws IllegalArgumentException If {@code string} is null or 0-length. */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) @EnsuresNonNull({"#1"}) public static String checkNotEmpty(@Nullable String string, Object errorMessage) { if (ExoPlayerLibraryInfo.ASSERTIONS_ENABLED && TextUtils.isEmpty(string)) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java index 5a492fe987..2099645690 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -69,6 +69,7 @@ import java.util.concurrent.ThreadFactory; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.checkerframework.checker.initialization.qual.UnknownInitialization; +import org.checkerframework.checker.nullness.qual.EnsuresNonNull; import org.checkerframework.checker.nullness.qual.PolyNull; /** @@ -232,6 +233,17 @@ public final class Util { list.subList(fromIndex, toIndex).clear(); } + /** + * Casts a nullable variable to a non-null variable without runtime null check. + * + *

Use {@link Assertions#checkNotNull(Object)} to throw if the value is null. + */ + @SuppressWarnings({"contracts.postcondition.not.satisfied", "return.type.incompatible"}) + @EnsuresNonNull("#1") + public static T castNonNull(@Nullable T value) { + return value; + } + /** * Copies and optionally truncates an array. Prevents null array elements created by {@link * Arrays#copyOf(Object[], int)} by ensuring the new length does not exceed the current length. @@ -627,10 +639,10 @@ public final class Util { /** * Returns the index of the largest element in {@code list} that is less than (or optionally equal * to) a specified {@code value}. - *

- * The search is performed using a binary search algorithm, so the list must be sorted. If the - * list contains multiple elements equal to {@code value} and {@code inclusive} is true, the - * index of the first one will be returned. + * + *

The search is performed using a binary search algorithm, so the list must be sorted. If the + * list contains multiple elements equal to {@code value} and {@code inclusive} is true, the index + * of the first one will be returned. * * @param The type of values being searched. * @param list The list to search. @@ -643,8 +655,11 @@ public final class Util { * @return The index of the largest element in {@code list} that is less than (or optionally equal * to) {@code value}. */ - public static int binarySearchFloor(List> list, T value, - boolean inclusive, boolean stayInBounds) { + public static > int binarySearchFloor( + List> list, + T value, + boolean inclusive, + boolean stayInBounds) { int index = Collections.binarySearch(list, value); if (index < 0) { index = -(index + 2); @@ -693,10 +708,10 @@ public final class Util { /** * Returns the index of the smallest element in {@code list} that is greater than (or optionally * equal to) a specified value. - *

- * The search is performed using a binary search algorithm, so the list must be sorted. If the - * list contains multiple elements equal to {@code value} and {@code inclusive} is true, the - * index of the last one will be returned. + * + *

The search is performed using a binary search algorithm, so the list must be sorted. If the + * list contains multiple elements equal to {@code value} and {@code inclusive} is true, the index + * of the last one will be returned. * * @param The type of values being searched. * @param list The list to search. @@ -705,13 +720,16 @@ public final class Util { * index. If false then the returned index corresponds to the smallest element strictly * greater than the value. * @param stayInBounds If true, then {@code (list.size() - 1)} will be returned in the case that - * the value is greater than the largest element in the list. If false then - * {@code list.size()} will be returned. + * the value is greater than the largest element in the list. If false then {@code + * list.size()} will be returned. * @return The index of the smallest element in {@code list} that is greater than (or optionally * equal to) {@code value}. */ - public static int binarySearchCeil(List> list, T value, - boolean inclusive, boolean stayInBounds) { + public static > int binarySearchCeil( + List> list, + T value, + boolean inclusive, + boolean stayInBounds) { int index = Collections.binarySearch(list, value); if (index < 0) { index = ~index; @@ -970,7 +988,7 @@ public final class Util { * @param list A list of integers. * @return The list in array form, or null if the input list was null. */ - public static int[] toArray(List list) { + public static int @PolyNull [] toArray(@PolyNull List list) { if (list == null) { return null; } @@ -1053,15 +1071,15 @@ public final class Util { } /** - * Returns a copy of {@code codecs} without the codecs whose track type doesn't match - * {@code trackType}. + * Returns a copy of {@code codecs} without the codecs whose track type doesn't match {@code + * trackType}. * * @param codecs A codec sequence string, as defined in RFC 6381. * @param trackType One of {@link C}{@code .TRACK_TYPE_*}. - * @return A copy of {@code codecs} without the codecs whose track type doesn't match - * {@code trackType}. + * @return A copy of {@code codecs} without the codecs whose track type doesn't match {@code + * trackType}. */ - public static String getCodecsOfType(String codecs, int trackType) { + public static @Nullable String getCodecsOfType(String codecs, int trackType) { String[] codecArray = splitCodecs(codecs); if (codecArray.length == 0) { return null; @@ -1251,7 +1269,7 @@ public final class Util { * "clearkey"}. * @return The derived {@link UUID}, or {@code null} if one could not be derived. */ - public static UUID getDrmUuid(String drmScheme) { + public static @Nullable UUID getDrmUuid(String drmScheme) { switch (Util.toLowerInvariant(drmScheme)) { case "widevine": return C.WIDEVINE_UUID; @@ -1427,7 +1445,7 @@ public final class Util { * @return The original value of the file name before it was escaped, or null if the escaped * fileName seems invalid. */ - public static String unescapeFileName(String fileName) { + public static @Nullable String unescapeFileName(String fileName) { int length = fileName.length(); int percentCharacterCount = 0; for (int i = 0; i < length; i++) { @@ -1473,8 +1491,9 @@ public final class Util { /** Recursively deletes a directory and its content. */ public static void recursiveDelete(File fileOrDirectory) { - if (fileOrDirectory.isDirectory()) { - for (File child : fileOrDirectory.listFiles()) { + File[] directoryFiles = fileOrDirectory.listFiles(); + if (directoryFiles != null) { + for (File child : directoryFiles) { recursiveDelete(child); } }