diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java index 76481bbdf727ed083acbd8c8920ed133e72bb311..171aa0878a3fce31fdfb78fd7e80580b6884da3d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java @@ -127,23 +127,24 @@ public interface Cache { /** * A caller should invoke this method when they require data from a given position for a given * key. - *
- * If there is a cache entry that overlaps the position, then the returned {@link CacheSpan} + * + *
If there is a cache entry that overlaps the position, then the returned {@link CacheSpan} * defines the file in which the data is stored. {@link CacheSpan#isCached} is true. The caller * may read from the cache file, but does not acquire any locks. - *
- * If there is no cache entry overlapping {@code offset}, then the returned {@link CacheSpan} + * + *
If there is no cache entry overlapping {@code offset}, then the returned {@link CacheSpan} * defines a hole in the cache starting at {@code position} into which the caller may write as it * obtains the data from some other source. The returned {@link CacheSpan} serves as a lock. * Whilst the caller holds the lock it may write data into the hole. It may split data into - * multiple files. When the caller has finished writing a file it should commit it to the cache - * by calling {@link #commitFile(File)}. When the caller has finished writing, it must release - * the lock by calling {@link #releaseHoleSpan}. + * multiple files. When the caller has finished writing a file it should commit it to the cache by + * calling {@link #commitFile(File)}. When the caller has finished writing, it must release the + * lock by calling {@link #releaseHoleSpan}. * * @param key The key of the data being requested. * @param position The position of the data being requested. * @return The {@link CacheSpan}. * @throws InterruptedException If the thread was interrupted. + * @throws CacheException If an error is encountered. */ CacheSpan startReadWrite(String key, long position) throws InterruptedException, CacheException; @@ -154,8 +155,10 @@ public interface Cache { * @param key The key of the data being requested. * @param position The position of the data being requested. * @return The {@link CacheSpan}. Or null if the cache entry is locked. + * @throws CacheException If an error is encountered. */ - @Nullable CacheSpan startReadWriteNonBlocking(String key, long position) throws CacheException; + @Nullable + CacheSpan startReadWriteNonBlocking(String key, long position) throws CacheException; /** * Obtains a cache file into which data can be written. Must only be called when holding a @@ -166,14 +169,16 @@ public interface Cache { * @param maxLength The maximum length of the data to be written. Used only to ensure that there * is enough space in the cache. * @return The file into which data should be written. + * @throws CacheException If an error is encountered. */ File startFile(String key, long position, long maxLength) throws CacheException; /** - * Commits a file into the cache. Must only be called when holding a corresponding hole - * {@link CacheSpan} obtained from {@link #startReadWrite(String, long)} + * Commits a file into the cache. Must only be called when holding a corresponding hole {@link + * CacheSpan} obtained from {@link #startReadWrite(String, long)} * * @param file A newly written cache file. + * @throws CacheException If an error is encountered. */ void commitFile(File file) throws CacheException; @@ -189,6 +194,7 @@ public interface Cache { * Removes a cached {@link CacheSpan} from the cache, deleting the underlying file. * * @param span The {@link CacheSpan} to remove. + * @throws CacheException If an error is encountered. */ void removeSpan(CacheSpan span) throws CacheException; @@ -210,15 +216,16 @@ public interface Cache { * @param key The cache key for the data. * @param position The starting position of the data. * @param length The maximum length of the data to be returned. - * @return the length of the cached or not cached data block length. + * @return The length of the cached or not cached data block length. */ - long getCachedBytes(String key, long position, long length); + long getCachedLength(String key, long position, long length); /** * Sets the content length for the given key. * * @param key The cache key for the data. * @param length The length of the data. + * @throws CacheException If an error is encountered. */ void setContentLength(String key, long length) throws CacheException; @@ -227,7 +234,8 @@ public interface Cache { * com.google.android.exoplayer2.C#LENGTH_UNSET} otherwise. * * @param key The cache key for the data. + * @return The content length for the given key if one set, or {@link + * com.google.android.exoplayer2.C#LENGTH_UNSET} otherwise. */ long getContentLength(String key); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java index 1af690e10f2d60f94f76ace0b65db239860f3e42..57f5a6ad9310a5daa9e862c826466ec46ad56251 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java @@ -37,7 +37,7 @@ import java.io.OutputStream; */ public final class CacheDataSink implements DataSink { - /** Default buffer size. */ + /** Default buffer size in bytes. */ public static final int DEFAULT_BUFFER_SIZE = 20480; private final Cache cache; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java index 2bf5cde8e05083c95fce2a2b4e83dc711e62b3f8..22150f8e7865903a971239de33ff74d38a8e96b7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java @@ -89,8 +89,8 @@ public final class CacheUtil { counters.alreadyCachedBytes = 0; counters.newlyCachedBytes = 0; while (left != 0) { - long blockLength = cache.getCachedBytes(key, start, - left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); + long blockLength = + cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); if (blockLength > 0) { counters.alreadyCachedBytes += blockLength; } else { @@ -126,6 +126,12 @@ public final class CacheUtil { * Caches the data defined by {@code dataSpec} while skipping already cached data. Caching stops * early if end of input is reached and {@code enableEOFException} is false. * + *
If a {@link PriorityTaskManager} is given, it's used to pause and resume caching depending
+ * on {@code priority} and the priority of other tasks registered to the PriorityTaskManager.
+ * Please note that it's the responsibility of the calling code to call {@link
+ * PriorityTaskManager#add} to register with the manager before calling this method, and to call
+ * {@link PriorityTaskManager#remove} afterwards to unregister.
+ *
* @param dataSpec Defines the data to be cached.
* @param cache A {@link Cache} to store the data.
* @param dataSource A {@link CacheDataSource} that works on the {@code cache}.
@@ -164,8 +170,8 @@ public final class CacheUtil {
long start = dataSpec.absoluteStreamPosition;
long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key);
while (left != 0) {
- long blockLength = cache.getCachedBytes(key, start,
- left != C.LENGTH_UNSET ? left : Long.MAX_VALUE);
+ long blockLength =
+ cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE);
if (blockLength > 0) {
// Skip already cached data.
} else {
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java
index fb59d23666e8735309b47a982d99a357b35196a4..34884a457d30a6520d4f676af5eba7d028a10714 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java
@@ -125,7 +125,7 @@ import java.util.TreeSet;
* @param length The maximum length of the data to be returned.
* @return the length of the cached or not cached data block length.
*/
- public long getCachedBytes(long position, long length) {
+ public long getCachedBytesLength(long position, long length) {
SimpleCacheSpan span = getSpan(position);
if (span.isHoleSpan()) {
// We don't have a span covering the start of the queried region.
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java
index ffac8a35f1874cba8a51094c59b7031d58e34cb7..9d4a66134371ff2a88f9e50a6631e80c4ac0cb1a 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java
@@ -385,13 +385,13 @@ public final class SimpleCache implements Cache {
@Override
public synchronized boolean isCached(String key, long position, long length) {
CachedContent cachedContent = index.get(key);
- return cachedContent != null && cachedContent.getCachedBytes(position, length) >= length;
+ return cachedContent != null && cachedContent.getCachedBytesLength(position, length) >= length;
}
@Override
- public synchronized long getCachedBytes(String key, long position, long length) {
+ public synchronized long getCachedLength(String key, long position, long length) {
CachedContent cachedContent = index.get(key);
- return cachedContent != null ? cachedContent.getCachedBytes(position, length) : -length;
+ return cachedContent != null ? cachedContent.getCachedBytesLength(position, length) : -length;
}
@Override
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java
index 8c5b7e26e77b3e544cdc8a09289e3a9ca06c7a15..e12d876ce14254bed0ac3bdd23a117667e744da1 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java
@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.upstream.cache;
+import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
@@ -35,19 +36,50 @@ import java.util.regex.Pattern;
private static final Pattern CACHE_FILE_PATTERN_V3 = Pattern.compile(
"^(\\d+)\\.(\\d+)\\.(\\d+)\\.v3\\.exo$", Pattern.DOTALL);
- public static File getCacheFile(File cacheDir, int id, long position,
- long lastAccessTimestamp) {
+ /**
+ * Returns a new {@link File} instance from {@code cacheDir}, {@code id}, {@code position}, {@code
+ * lastAccessTimestamp}.
+ *
+ * @param cacheDir The parent abstract pathname.
+ * @param id The cache file id.
+ * @param position The position of the stored data in the original stream.
+ * @param lastAccessTimestamp The last access timestamp.
+ * @return The cache file.
+ */
+ public static File getCacheFile(File cacheDir, int id, long position, long lastAccessTimestamp) {
return new File(cacheDir, id + "." + position + "." + lastAccessTimestamp + SUFFIX);
}
+ /**
+ * Creates a lookup span.
+ *
+ * @param key The cache key.
+ * @param position The position of the {@link CacheSpan} in the original stream.
+ * @return The span.
+ */
public static SimpleCacheSpan createLookup(String key, long position) {
return new SimpleCacheSpan(key, position, C.LENGTH_UNSET, C.TIME_UNSET, null);
}
+ /**
+ * Creates an open hole span.
+ *
+ * @param key The cache key.
+ * @param position The position of the {@link CacheSpan} in the original stream.
+ * @return The span.
+ */
public static SimpleCacheSpan createOpenHole(String key, long position) {
return new SimpleCacheSpan(key, position, C.LENGTH_UNSET, C.TIME_UNSET, null);
}
+ /**
+ * Creates a closed hole span.
+ *
+ * @param key The cache key.
+ * @param position The position of the {@link CacheSpan} in the original stream.
+ * @param length The length of the {@link CacheSpan}.
+ * @return The span.
+ */
public static SimpleCacheSpan createClosedHole(String key, long position, long length) {
return new SimpleCacheSpan(key, position, length, C.TIME_UNSET, null);
}
@@ -60,6 +92,7 @@ import java.util.regex.Pattern;
* @return The span, or null if the file name is not correctly formatted, or if the id is not
* present in the content index.
*/
+ @Nullable
public static SimpleCacheSpan createCacheEntry(File file, CachedContentIndex index) {
String name = file.getName();
if (!name.endsWith(SUFFIX)) {
@@ -81,6 +114,15 @@ import java.util.regex.Pattern;
Long.parseLong(matcher.group(3)), file);
}
+ /**
+ * 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.
+ * @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;
String filename = file.getName();
@@ -106,8 +148,17 @@ import java.util.regex.Pattern;
return newCacheFile;
}
- private SimpleCacheSpan(String key, long position, long length, long lastAccessTimestamp,
- File file) {
+ /**
+ * @param key The cache key.
+ * @param position The position of the {@link CacheSpan} in the original stream.
+ * @param length The length of the {@link CacheSpan}, or {@link C#LENGTH_UNSET} if this is an
+ * open-ended hole.
+ * @param lastAccessTimestamp The last access timestamp, or {@link C#TIME_UNSET} if {@link
+ * #isCached} is false.
+ * @param file The file corresponding to this {@link CacheSpan}, or null if it's a hole.
+ */
+ private SimpleCacheSpan(
+ String key, long position, long length, long lastAccessTimestamp, @Nullable File file) {
super(key, position, length, lastAccessTimestamp, file);
}
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java
index 65850a13e73f0436f7fce83c818e746bcb5e5b01..c31cd0384ee97c59d0a10c2f4167a6aace8196ff 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java
@@ -31,7 +31,11 @@ import java.util.ArrayList;
/** Assertion methods for {@link com.google.android.exoplayer2.upstream.cache.Cache}. */
/* package */ final class CacheAsserts {
- /** Asserts that the cache content is equal to the data in the {@code fakeDataSet}. */
+ /**
+ * Asserts that the cache content is equal to the data in the {@code fakeDataSet}.
+ *
+ * @throws IOException If an error occurred reading from the Cache.
+ */
public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet) throws IOException {
ArrayList