Add NonNull annotations to upstream.cache and upstream.crypto

PiperOrigin-RevId: 284548019
This commit is contained in:
olly 2019-12-09 15:22:11 +00:00 committed by Oliver Woodman
parent 0b7f93a5d4
commit c90c10c981
14 changed files with 97 additions and 52 deletions

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.upstream.cache;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSink;
import com.google.android.exoplayer2.upstream.DataSpec;
@ -27,6 +28,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Writes data into a cache.
@ -49,13 +51,13 @@ public final class CacheDataSink implements DataSink {
private final long fragmentSize;
private final int bufferSize;
private DataSpec dataSpec;
@Nullable private DataSpec dataSpec;
private long dataSpecFragmentSize;
private File file;
private OutputStream outputStream;
@Nullable private File file;
@Nullable private OutputStream outputStream;
private long outputStreamBytesWritten;
private long dataSpecBytesWritten;
private ReusableBufferedOutputStream bufferedOutputStream;
@MonotonicNonNull private ReusableBufferedOutputStream bufferedOutputStream;
/**
* Thrown when IOException is encountered when writing data into sink.

View File

@ -377,7 +377,7 @@ public final class CacheDataSource implements DataSource {
* reading from {@link #upstreamDataSource}, which is the currently open source.
*/
private void openNextSource(boolean checkCache) throws IOException {
CacheSpan nextSpan;
@Nullable CacheSpan nextSpan;
if (currentRequestIgnoresCache) {
nextSpan = null;
} else if (blockOnCache) {
@ -487,7 +487,7 @@ public final class CacheDataSource implements DataSource {
}
private static Uri getRedirectedUriOrDefault(Cache cache, String key, Uri defaultUri) {
Uri redirectedUri = ContentMetadata.getRedirectedUri(cache.getContentMetadata(key));
@Nullable Uri redirectedUri = ContentMetadata.getRedirectedUri(cache.getContentMetadata(key));
return redirectedUri != null ? redirectedUri : defaultUri;
}

View File

@ -60,7 +60,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final DatabaseProvider databaseProvider;
private @MonotonicNonNull String tableName;
@MonotonicNonNull private String tableName;
/**
* Deletes index data for the specified cache.

View File

@ -24,6 +24,7 @@ public interface CacheKeyFactory {
* Returns a cache key for the given {@link DataSpec}.
*
* @param dataSpec The data being cached.
* @return The cache key.
*/
String buildCacheKey(DataSpec dataSpec);
}

View File

@ -183,7 +183,7 @@ public final class CacheUtil {
String key = buildCacheKey(dataSpec, cacheKeyFactory);
long bytesLeft;
ProgressNotifier progressNotifier = null;
@Nullable ProgressNotifier progressNotifier = null;
if (progressListener != null) {
progressNotifier = new ProgressNotifier(progressListener);
Pair<Long, Long> lengthAndBytesAlreadyCached = getCached(dataSpec, cache, cacheKeyFactory);
@ -373,7 +373,7 @@ public final class CacheUtil {
}
/* package */ static boolean isCausedByPositionOutOfRange(IOException e) {
Throwable cause = e;
@Nullable Throwable cause = e;
while (cause != null) {
if (cause instanceof DataSourceException) {
int reason = ((DataSourceException) cause).reason;

View File

@ -229,11 +229,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* @return A new or existing CachedContent instance with the given key.
*/
public CachedContent getOrAdd(String key) {
CachedContent cachedContent = keyToContent.get(key);
@Nullable CachedContent cachedContent = keyToContent.get(key);
return cachedContent == null ? addNew(key) : cachedContent;
}
/** Returns a CachedContent instance with the given key or null if there isn't one. */
@Nullable
public CachedContent get(String key) {
return keyToContent.get(key);
}
@ -254,14 +255,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return getOrAdd(key).id;
}
/** Returns the key which has the given id assigned. */
/** Returns the key which has the given id assigned, or {@code null} if no such key exists. */
@Nullable
public String getKeyForId(int id) {
return idToKey.get(id);
}
/** Removes {@link CachedContent} with the given key from index if it's empty and not locked. */
public void maybeRemove(String key) {
CachedContent cachedContent = keyToContent.get(key);
@Nullable CachedContent cachedContent = keyToContent.get(key);
if (cachedContent != null && cachedContent.isEmpty() && !cachedContent.isLocked()) {
keyToContent.remove(key);
int id = cachedContent.id;
@ -626,7 +628,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
private void writeFile(HashMap<String, CachedContent> content) throws IOException {
DataOutputStream output = null;
@Nullable DataOutputStream output = null;
try {
OutputStream outputStream = atomicFile.startWrite();
if (bufferedOutputStream == null) {

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.upstream.cache;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.extractor.ChunkIndex;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
@ -77,7 +78,7 @@ public final class CachedRegionTracker implements Cache.Listener {
*/
public synchronized int getRegionEndTimeMs(long byteOffset) {
lookupRegion.startOffset = byteOffset;
Region floorRegion = regions.floor(lookupRegion);
@Nullable Region floorRegion = regions.floor(lookupRegion);
if (floorRegion == null || byteOffset > floorRegion.endOffset
|| floorRegion.endOffsetIndex == -1) {
return NOT_CACHED;
@ -102,7 +103,7 @@ public final class CachedRegionTracker implements Cache.Listener {
Region removedRegion = new Region(span.position, span.position + span.length);
// Look up a region this span falls into.
Region floorRegion = regions.floor(removedRegion);
@Nullable Region floorRegion = regions.floor(removedRegion);
if (floorRegion == null) {
Log.e(TAG, "Removed a span we were not aware of");
return;
@ -134,8 +135,8 @@ public final class CachedRegionTracker implements Cache.Listener {
private void mergeSpan(CacheSpan span) {
Region newRegion = new Region(span.position, span.position + span.length);
Region floorRegion = regions.floor(newRegion);
Region ceilingRegion = regions.ceiling(newRegion);
@Nullable Region floorRegion = regions.floor(newRegion);
@Nullable Region ceilingRegion = regions.ceiling(newRegion);
boolean floorConnects = regionsConnect(floorRegion, newRegion);
boolean ceilingConnects = regionsConnect(newRegion, ceilingRegion);
@ -168,7 +169,7 @@ public final class CachedRegionTracker implements Cache.Listener {
}
}
private boolean regionsConnect(Region lower, Region upper) {
private boolean regionsConnect(@Nullable Region lower, @Nullable Region upper) {
return lower != null && upper != null && lower.endOffset == upper.startOffset;
}

View File

@ -81,7 +81,7 @@ public interface ContentMetadata {
*/
@Nullable
static Uri getRedirectedUri(ContentMetadata contentMetadata) {
String redirectedUri = contentMetadata.get(KEY_REDIRECTED_URI, (String) null);
@Nullable String redirectedUri = contentMetadata.get(KEY_REDIRECTED_URI, (String) null);
return redirectedUri == null ? null : Uri.parse(redirectedUri);
}
}

View File

@ -73,8 +73,7 @@ public class ContentMetadataMutations {
}
/**
* Adds a mutation to set a metadata value. Passing {@code null} as {@code name} or {@code value}
* isn't allowed.
* Adds a mutation to set a metadata value.
*
* @param name The name of the metadata value.
* @param value The value to be set.
@ -85,7 +84,7 @@ public class ContentMetadataMutations {
}
/**
* Adds a mutation to set a metadata value. Passing {@code null} as {@code name} isn't allowed.
* Adds a mutation to set a metadata value.
*
* @param name The name of the metadata value.
* @param value The value to be set.
@ -96,8 +95,7 @@ public class ContentMetadataMutations {
}
/**
* Adds a mutation to set a metadata value. Passing {@code null} as {@code name} or {@code value}
* isn't allowed.
* Adds a mutation to set a metadata value.
*
* @param name The name of the metadata value.
* @param value The value to be set.

View File

@ -67,8 +67,8 @@ public final class DefaultContentMetadata implements ContentMetadata {
@Override
@Nullable
public final byte[] get(String name, @Nullable byte[] defaultValue) {
if (metadata.containsKey(name)) {
byte[] bytes = metadata.get(name);
@Nullable byte[] bytes = metadata.get(name);
if (bytes != null) {
return Arrays.copyOf(bytes, bytes.length);
} else {
return defaultValue;
@ -78,8 +78,8 @@ public final class DefaultContentMetadata implements ContentMetadata {
@Override
@Nullable
public final String get(String name, @Nullable String defaultValue) {
if (metadata.containsKey(name)) {
byte[] bytes = metadata.get(name);
@Nullable byte[] bytes = metadata.get(name);
if (bytes != null) {
return new String(bytes, Charset.forName(C.UTF8_NAME));
} else {
return defaultValue;
@ -88,8 +88,8 @@ public final class DefaultContentMetadata implements ContentMetadata {
@Override
public final long get(String name, long defaultValue) {
if (metadata.containsKey(name)) {
byte[] bytes = metadata.get(name);
@Nullable byte[] bytes = metadata.get(name);
if (bytes != null) {
return ByteBuffer.wrap(bytes).getLong();
} else {
return defaultValue;
@ -130,7 +130,7 @@ public final class DefaultContentMetadata implements ContentMetadata {
}
for (Entry<String, byte[]> entry : first.entrySet()) {
byte[] value = entry.getValue();
byte[] otherValue = second.get(entry.getKey());
@Nullable byte[] otherValue = second.get(entry.getKey());
if (!Arrays.equals(value, otherValue)) {
return false;
}
@ -153,8 +153,8 @@ public final class DefaultContentMetadata implements ContentMetadata {
}
private static void addValues(HashMap<String, byte[]> metadata, Map<String, Object> values) {
for (String name : values.keySet()) {
metadata.put(name, getBytes(values.get(name)));
for (Entry<String, Object> entry : values.entrySet()) {
metadata.put(entry.getKey(), getBytes(entry.getValue()));
}
}

View File

@ -465,8 +465,7 @@ public final class SimpleCache implements Cache {
@Override
public synchronized void releaseHoleSpan(CacheSpan holeSpan) {
Assertions.checkState(!released);
CachedContent cachedContent = contentIndex.get(holeSpan.key);
Assertions.checkNotNull(cachedContent);
CachedContent cachedContent = Assertions.checkNotNull(contentIndex.get(holeSpan.key));
Assertions.checkState(cachedContent.isLocked());
cachedContent.setLocked(false);
contentIndex.maybeRemove(cachedContent.key);
@ -482,14 +481,14 @@ public final class SimpleCache implements Cache {
@Override
public synchronized boolean isCached(String key, long position, long length) {
Assertions.checkState(!released);
CachedContent cachedContent = contentIndex.get(key);
@Nullable CachedContent cachedContent = contentIndex.get(key);
return cachedContent != null && cachedContent.getCachedBytesLength(position, length) >= length;
}
@Override
public synchronized long getCachedLength(String key, long position, long length) {
Assertions.checkState(!released);
CachedContent cachedContent = contentIndex.get(key);
@Nullable CachedContent cachedContent = contentIndex.get(key);
return cachedContent != null ? cachedContent.getCachedBytesLength(position, length) : -length;
}
@ -524,7 +523,7 @@ public final class SimpleCache implements Cache {
}
}
File[] files = cacheDir.listFiles();
@Nullable File[] files = cacheDir.listFiles();
if (files == null) {
String message = "Failed to list cache directory files: " + cacheDir;
Log.e(TAG, message);
@ -605,11 +604,13 @@ public final class SimpleCache implements Cache {
}
long length = C.LENGTH_UNSET;
long lastTouchTimestamp = C.TIME_UNSET;
@Nullable
CacheFileMetadata metadata = fileMetadata != null ? fileMetadata.remove(fileName) : null;
if (metadata != null) {
length = metadata.length;
lastTouchTimestamp = metadata.lastTouchTimestamp;
}
@Nullable
SimpleCacheSpan span =
SimpleCacheSpan.createCacheEntry(file, length, lastTouchTimestamp, contentIndex);
if (span != null) {
@ -666,7 +667,7 @@ public final class SimpleCache implements Cache {
* @return The corresponding cache {@link SimpleCacheSpan}.
*/
private SimpleCacheSpan getSpan(String key, long position) {
CachedContent cachedContent = contentIndex.get(key);
@Nullable CachedContent cachedContent = contentIndex.get(key);
if (cachedContent == null) {
return SimpleCacheSpan.createOpenHole(key, position);
}
@ -694,7 +695,7 @@ public final class SimpleCache implements Cache {
}
private void removeSpanInternal(CacheSpan span) {
CachedContent cachedContent = contentIndex.get(span.key);
@Nullable CachedContent cachedContent = contentIndex.get(span.key);
if (cachedContent == null || !cachedContent.removeSpan(span)) {
return;
}
@ -732,7 +733,7 @@ public final class SimpleCache implements Cache {
}
private void notifySpanRemoved(CacheSpan span) {
ArrayList<Listener> keyListeners = listeners.get(span.key);
@Nullable ArrayList<Listener> keyListeners = listeners.get(span.key);
if (keyListeners != null) {
for (int i = keyListeners.size() - 1; i >= 0; i--) {
keyListeners.get(i).onSpanRemoved(this, span);
@ -742,7 +743,7 @@ public final class SimpleCache implements Cache {
}
private void notifySpanAdded(SimpleCacheSpan span) {
ArrayList<Listener> keyListeners = listeners.get(span.key);
@Nullable ArrayList<Listener> keyListeners = listeners.get(span.key);
if (keyListeners != null) {
for (int i = keyListeners.size() - 1; i >= 0; i--) {
keyListeners.get(i).onSpanAdded(this, span);
@ -752,7 +753,7 @@ public final class SimpleCache implements Cache {
}
private void notifySpanTouched(SimpleCacheSpan oldSpan, CacheSpan newSpan) {
ArrayList<Listener> keyListeners = listeners.get(oldSpan.key);
@Nullable ArrayList<Listener> keyListeners = listeners.get(oldSpan.key);
if (keyListeners != null) {
for (int i = keyListeners.size() - 1; i >= 0; i--) {
keyListeners.get(i).onSpanTouched(this, oldSpan, newSpan);

View File

@ -91,6 +91,7 @@ import java.util.regex.Pattern;
* @param length The length of the cache file in bytes, or {@link C#LENGTH_UNSET} to query the
* underlying file system. Querying the underlying file system can be expensive, so callers
* that already know the length of the file should pass it explicitly.
* @param index The cached content index.
* @return The span, or null if the file name is not correctly formatted, or if the id is not
* present in the content index, or if the length is 0.
*/
@ -108,6 +109,7 @@ import java.util.regex.Pattern;
* that already know the length of the file should pass it explicitly.
* @param lastTouchTimestamp The last touch timestamp, or {@link C#TIME_UNSET} to use the file
* timestamp.
* @param index The cached content index.
* @return The span, or null if the file name is not correctly formatted, or if the id is not
* present in the content index, or if the length is 0.
*/
@ -130,7 +132,7 @@ import java.util.regex.Pattern;
}
int id = Integer.parseInt(matcher.group(1));
String key = index.getKeyForId(id);
@Nullable String key = index.getKeyForId(id);
if (key == null) {
return null;
}
@ -153,26 +155,26 @@ import java.util.regex.Pattern;
* Upgrades the cache file if it is created by an earlier version of {@link SimpleCache}.
*
* @param file The cache file.
* @param index Cached content index.
* @param index The cached content index.
* @return Upgraded cache file or {@code null} if the file name is not correctly formatted or the
* file can not be renamed.
*/
@Nullable
private static File upgradeFile(File file, CachedContentIndex index) {
String key;
@Nullable String key = null;
String filename = file.getName();
Matcher matcher = CACHE_FILE_PATTERN_V2.matcher(filename);
if (matcher.matches()) {
key = Util.unescapeFileName(matcher.group(1));
if (key == null) {
return null;
}
} else {
matcher = CACHE_FILE_PATTERN_V1.matcher(filename);
if (!matcher.matches()) {
return null;
if (matcher.matches()) {
key = matcher.group(1); // Keys were not escaped in version 1.
}
key = matcher.group(1); // Keys were not escaped in version 1.
}
if (key == null) {
return null;
}
File newCacheFile =

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package com.google.android.exoplayer2.upstream.cache;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package com.google.android.exoplayer2.upstream.crypto;
import com.google.android.exoplayer2.util.NonNullApi;