Commit 8de149eb by olly Committed by Oliver Woodman

Use custom cache key factory for removal as well as downloading

Issue #5013

PiperOrigin-RevId: 223838303
parent 87a74ee0
...@@ -27,12 +27,14 @@ import com.google.android.exoplayer2.upstream.cache.CacheDataSinkFactory; ...@@ -27,12 +27,14 @@ import com.google.android.exoplayer2.upstream.cache.CacheDataSinkFactory;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource; import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory; import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory; import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory;
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
/** A helper class that holds necessary parameters for {@link Downloader} construction. */ /** A helper class that holds necessary parameters for {@link Downloader} construction. */
public final class DownloaderConstructorHelper { public final class DownloaderConstructorHelper {
private final Cache cache; private final Cache cache;
@Nullable private final CacheKeyFactory cacheKeyFactory;
@Nullable private final PriorityTaskManager priorityTaskManager; @Nullable private final PriorityTaskManager priorityTaskManager;
private final CacheDataSourceFactory onlineCacheDataSourceFactory; private final CacheDataSourceFactory onlineCacheDataSourceFactory;
private final CacheDataSourceFactory offlineCacheDataSourceFactory; private final CacheDataSourceFactory offlineCacheDataSourceFactory;
...@@ -130,6 +132,7 @@ public final class DownloaderConstructorHelper { ...@@ -130,6 +132,7 @@ public final class DownloaderConstructorHelper {
cacheKeyFactory); cacheKeyFactory);
this.cache = cache; this.cache = cache;
this.priorityTaskManager = priorityTaskManager; this.priorityTaskManager = priorityTaskManager;
this.cacheKeyFactory = cacheKeyFactory;
} }
/** Returns the {@link Cache} instance. */ /** Returns the {@link Cache} instance. */
...@@ -137,6 +140,11 @@ public final class DownloaderConstructorHelper { ...@@ -137,6 +140,11 @@ public final class DownloaderConstructorHelper {
return cache; return cache;
} }
/** Returns the {@link CacheKeyFactory}. */
public CacheKeyFactory getCacheKeyFactory() {
return cacheKeyFactory != null ? cacheKeyFactory : CacheUtil.DEFAULT_CACHE_KEY_FACTORY;
}
/** Returns a {@link PriorityTaskManager} instance. */ /** Returns a {@link PriorityTaskManager} instance. */
public PriorityTaskManager getPriorityTaskManager() { public PriorityTaskManager getPriorityTaskManager() {
// Return a dummy PriorityTaskManager if none is provided. Create a new PriorityTaskManager // Return a dummy PriorityTaskManager if none is provided. Create a new PriorityTaskManager
......
...@@ -21,6 +21,7 @@ import com.google.android.exoplayer2.C; ...@@ -21,6 +21,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.cache.Cache; import com.google.android.exoplayer2.upstream.cache.Cache;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource; import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory;
import com.google.android.exoplayer2.upstream.cache.CacheUtil; import com.google.android.exoplayer2.upstream.cache.CacheUtil;
import com.google.android.exoplayer2.upstream.cache.CacheUtil.CachingCounters; import com.google.android.exoplayer2.upstream.cache.CacheUtil.CachingCounters;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
...@@ -37,6 +38,7 @@ public final class ProgressiveDownloader implements Downloader { ...@@ -37,6 +38,7 @@ public final class ProgressiveDownloader implements Downloader {
private final DataSpec dataSpec; private final DataSpec dataSpec;
private final Cache cache; private final Cache cache;
private final CacheDataSource dataSource; private final CacheDataSource dataSource;
private final CacheKeyFactory cacheKeyFactory;
private final PriorityTaskManager priorityTaskManager; private final PriorityTaskManager priorityTaskManager;
private final CacheUtil.CachingCounters cachingCounters; private final CacheUtil.CachingCounters cachingCounters;
private final AtomicBoolean isCanceled; private final AtomicBoolean isCanceled;
...@@ -49,9 +51,12 @@ public final class ProgressiveDownloader implements Downloader { ...@@ -49,9 +51,12 @@ public final class ProgressiveDownloader implements Downloader {
*/ */
public ProgressiveDownloader( public ProgressiveDownloader(
Uri uri, @Nullable String customCacheKey, DownloaderConstructorHelper constructorHelper) { Uri uri, @Nullable String customCacheKey, DownloaderConstructorHelper constructorHelper) {
this.dataSpec = new DataSpec(uri, 0, C.LENGTH_UNSET, customCacheKey, 0); this.dataSpec =
new DataSpec(
uri, /* absoluteStreamPosition= */ 0, C.LENGTH_UNSET, customCacheKey, /* flags= */ 0);
this.cache = constructorHelper.getCache(); this.cache = constructorHelper.getCache();
this.dataSource = constructorHelper.createCacheDataSource(); this.dataSource = constructorHelper.createCacheDataSource();
this.cacheKeyFactory = constructorHelper.getCacheKeyFactory();
this.priorityTaskManager = constructorHelper.getPriorityTaskManager(); this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
cachingCounters = new CachingCounters(); cachingCounters = new CachingCounters();
isCanceled = new AtomicBoolean(); isCanceled = new AtomicBoolean();
...@@ -64,6 +69,7 @@ public final class ProgressiveDownloader implements Downloader { ...@@ -64,6 +69,7 @@ public final class ProgressiveDownloader implements Downloader {
CacheUtil.cache( CacheUtil.cache(
dataSpec, dataSpec,
cache, cache,
cacheKeyFactory,
dataSource, dataSource,
new byte[BUFFER_SIZE_BYTES], new byte[BUFFER_SIZE_BYTES],
priorityTaskManager, priorityTaskManager,
...@@ -101,6 +107,6 @@ public final class ProgressiveDownloader implements Downloader { ...@@ -101,6 +107,6 @@ public final class ProgressiveDownloader implements Downloader {
@Override @Override
public void remove() { public void remove() {
CacheUtil.remove(cache, CacheUtil.getKey(dataSpec)); CacheUtil.remove(dataSpec, cache, cacheKeyFactory);
} }
} }
...@@ -22,6 +22,7 @@ import com.google.android.exoplayer2.upstream.DataSource; ...@@ -22,6 +22,7 @@ import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.cache.Cache; import com.google.android.exoplayer2.upstream.cache.Cache;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource; import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory;
import com.google.android.exoplayer2.upstream.cache.CacheUtil; import com.google.android.exoplayer2.upstream.cache.CacheUtil;
import com.google.android.exoplayer2.upstream.cache.CacheUtil.CachingCounters; import com.google.android.exoplayer2.upstream.cache.CacheUtil.CachingCounters;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
...@@ -62,10 +63,11 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme ...@@ -62,10 +63,11 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
private static final int BUFFER_SIZE_BYTES = 128 * 1024; private static final int BUFFER_SIZE_BYTES = 128 * 1024;
private final Uri manifestUri; private final Uri manifestUri;
private final PriorityTaskManager priorityTaskManager;
private final Cache cache; private final Cache cache;
private final CacheDataSource dataSource; private final CacheDataSource dataSource;
private final CacheDataSource offlineDataSource; private final CacheDataSource offlineDataSource;
private final CacheKeyFactory cacheKeyFactory;
private final PriorityTaskManager priorityTaskManager;
private final ArrayList<StreamKey> streamKeys; private final ArrayList<StreamKey> streamKeys;
private final AtomicBoolean isCanceled; private final AtomicBoolean isCanceled;
...@@ -87,6 +89,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme ...@@ -87,6 +89,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
this.cache = constructorHelper.getCache(); this.cache = constructorHelper.getCache();
this.dataSource = constructorHelper.createCacheDataSource(); this.dataSource = constructorHelper.createCacheDataSource();
this.offlineDataSource = constructorHelper.createOfflineCacheDataSource(); this.offlineDataSource = constructorHelper.createOfflineCacheDataSource();
this.cacheKeyFactory = constructorHelper.getCacheKeyFactory();
this.priorityTaskManager = constructorHelper.getPriorityTaskManager(); this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
totalSegments = C.LENGTH_UNSET; totalSegments = C.LENGTH_UNSET;
totalBytes = C.LENGTH_UNSET; totalBytes = C.LENGTH_UNSET;
...@@ -117,6 +120,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme ...@@ -117,6 +120,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
CacheUtil.cache( CacheUtil.cache(
segments.get(i).dataSpec, segments.get(i).dataSpec,
cache, cache,
cacheKeyFactory,
dataSource, dataSource,
buffer, buffer,
priorityTaskManager, priorityTaskManager,
...@@ -170,13 +174,13 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme ...@@ -170,13 +174,13 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
M manifest = getManifest(offlineDataSource, manifestUri); M manifest = getManifest(offlineDataSource, manifestUri);
List<Segment> segments = getSegments(offlineDataSource, manifest, true); List<Segment> segments = getSegments(offlineDataSource, manifest, true);
for (int i = 0; i < segments.size(); i++) { for (int i = 0; i < segments.size(); i++) {
removeUri(segments.get(i).dataSpec.uri); removeDataSpec(segments.get(i).dataSpec);
} }
} catch (IOException e) { } catch (IOException e) {
// Ignore exceptions when removing. // Ignore exceptions when removing.
} finally { } finally {
// Always attempt to remove the manifest. // Always attempt to remove the manifest.
removeUri(manifestUri); removeDataSpec(new DataSpec(manifestUri));
} }
} }
...@@ -225,7 +229,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme ...@@ -225,7 +229,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
long totalBytes = 0; long totalBytes = 0;
for (int i = segments.size() - 1; i >= 0; i--) { for (int i = segments.size() - 1; i >= 0; i--) {
Segment segment = segments.get(i); Segment segment = segments.get(i);
CacheUtil.getCached(segment.dataSpec, cache, cachingCounters); CacheUtil.getCached(segment.dataSpec, cache, cacheKeyFactory, cachingCounters);
downloadedBytes += cachingCounters.alreadyCachedBytes; downloadedBytes += cachingCounters.alreadyCachedBytes;
if (cachingCounters.contentLength != C.LENGTH_UNSET) { if (cachingCounters.contentLength != C.LENGTH_UNSET) {
if (cachingCounters.alreadyCachedBytes == cachingCounters.contentLength) { if (cachingCounters.alreadyCachedBytes == cachingCounters.contentLength) {
...@@ -244,8 +248,8 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme ...@@ -244,8 +248,8 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
return segments; return segments;
} }
private void removeUri(Uri uri) { private void removeDataSpec(DataSpec dataSpec) {
CacheUtil.remove(cache, CacheUtil.generateKey(uri)); CacheUtil.remove(dataSpec, cache, cacheKeyFactory);
} }
} }
...@@ -54,8 +54,9 @@ public final class CacheUtil { ...@@ -54,8 +54,9 @@ public final class CacheUtil {
/** Default buffer size to be used while caching. */ /** Default buffer size to be used while caching. */
public static final int DEFAULT_BUFFER_SIZE_BYTES = 128 * 1024; public static final int DEFAULT_BUFFER_SIZE_BYTES = 128 * 1024;
/** Default {@link CacheKeyFactory} that calls through to {@link #getKey}. */ /** Default {@link CacheKeyFactory}. */
public static final CacheKeyFactory DEFAULT_CACHE_KEY_FACTORY = CacheUtil::getKey; public static final CacheKeyFactory DEFAULT_CACHE_KEY_FACTORY =
(dataSpec) -> dataSpec.key != null ? dataSpec.key : generateKey(dataSpec.uri);
/** /**
* Generates a cache key out of the given {@link Uri}. * Generates a cache key out of the given {@link Uri}.
...@@ -67,26 +68,21 @@ public final class CacheUtil { ...@@ -67,26 +68,21 @@ public final class CacheUtil {
} }
/** /**
* Returns the {@code dataSpec.key} if not null, otherwise generates a cache key out of {@code * Sets a {@link CachingCounters} to contain the number of bytes already downloaded and the length
* dataSpec.uri} * for the content defined by a {@code dataSpec}. {@link CachingCounters#newlyCachedBytes} is
* * reset to 0.
* @param dataSpec Defines a content which the requested key is for.
*/
public static String getKey(DataSpec dataSpec) {
return dataSpec.key != null ? dataSpec.key : generateKey(dataSpec.uri);
}
/**
* Sets a {@link CachingCounters} to contain the number of bytes already downloaded and the
* length for the content defined by a {@code dataSpec}. {@link CachingCounters#newlyCachedBytes}
* is reset to 0.
* *
* @param dataSpec Defines the data to be checked. * @param dataSpec Defines the data to be checked.
* @param cache A {@link Cache} which has the data. * @param cache A {@link Cache} which has the data.
* @param cacheKeyFactory An optional factory for cache keys.
* @param counters The {@link CachingCounters} to update. * @param counters The {@link CachingCounters} to update.
*/ */
public static void getCached(DataSpec dataSpec, Cache cache, CachingCounters counters) { public static void getCached(
String key = getKey(dataSpec); DataSpec dataSpec,
Cache cache,
@Nullable CacheKeyFactory cacheKeyFactory,
CachingCounters counters) {
String key = buildCacheKey(dataSpec, cacheKeyFactory);
long start = dataSpec.absoluteStreamPosition; long start = dataSpec.absoluteStreamPosition;
long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key); long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key);
counters.contentLength = left; counters.contentLength = left;
...@@ -114,6 +110,7 @@ public final class CacheUtil { ...@@ -114,6 +110,7 @@ public final class CacheUtil {
* *
* @param dataSpec Defines the data to be cached. * @param dataSpec Defines the data to be cached.
* @param cache A {@link Cache} to store the data. * @param cache A {@link Cache} to store the data.
* @param cacheKeyFactory An optional factory for cache keys.
* @param upstream A {@link DataSource} for reading data not in the cache. * @param upstream A {@link DataSource} for reading data not in the cache.
* @param counters If not null, updated during caching. * @param counters If not null, updated during caching.
* @param isCanceled An optional flag that will interrupt caching if set to true. * @param isCanceled An optional flag that will interrupt caching if set to true.
...@@ -123,6 +120,7 @@ public final class CacheUtil { ...@@ -123,6 +120,7 @@ public final class CacheUtil {
public static void cache( public static void cache(
DataSpec dataSpec, DataSpec dataSpec,
Cache cache, Cache cache,
@Nullable CacheKeyFactory cacheKeyFactory,
DataSource upstream, DataSource upstream,
@Nullable CachingCounters counters, @Nullable CachingCounters counters,
@Nullable AtomicBoolean isCanceled) @Nullable AtomicBoolean isCanceled)
...@@ -130,6 +128,7 @@ public final class CacheUtil { ...@@ -130,6 +128,7 @@ public final class CacheUtil {
cache( cache(
dataSpec, dataSpec,
cache, cache,
cacheKeyFactory,
new CacheDataSource(cache, upstream), new CacheDataSource(cache, upstream),
new byte[DEFAULT_BUFFER_SIZE_BYTES], new byte[DEFAULT_BUFFER_SIZE_BYTES],
/* priorityTaskManager= */ null, /* priorityTaskManager= */ null,
...@@ -151,6 +150,7 @@ public final class CacheUtil { ...@@ -151,6 +150,7 @@ public final class CacheUtil {
* *
* @param dataSpec Defines the data to be cached. * @param dataSpec Defines the data to be cached.
* @param cache A {@link Cache} to store the data. * @param cache A {@link Cache} to store the data.
* @param cacheKeyFactory An optional factory for cache keys.
* @param dataSource A {@link CacheDataSource} that works on the {@code cache}. * @param dataSource A {@link CacheDataSource} that works on the {@code cache}.
* @param buffer The buffer to be used while caching. * @param buffer The buffer to be used while caching.
* @param priorityTaskManager If not null it's used to check whether it is allowed to proceed with * @param priorityTaskManager If not null it's used to check whether it is allowed to proceed with
...@@ -166,6 +166,7 @@ public final class CacheUtil { ...@@ -166,6 +166,7 @@ public final class CacheUtil {
public static void cache( public static void cache(
DataSpec dataSpec, DataSpec dataSpec,
Cache cache, Cache cache,
@Nullable CacheKeyFactory cacheKeyFactory,
CacheDataSource dataSource, CacheDataSource dataSource,
byte[] buffer, byte[] buffer,
PriorityTaskManager priorityTaskManager, PriorityTaskManager priorityTaskManager,
...@@ -179,13 +180,13 @@ public final class CacheUtil { ...@@ -179,13 +180,13 @@ public final class CacheUtil {
if (counters != null) { if (counters != null) {
// Initialize the CachingCounter values. // Initialize the CachingCounter values.
getCached(dataSpec, cache, counters); getCached(dataSpec, cache, cacheKeyFactory, counters);
} else { } else {
// Dummy CachingCounters. No need to initialize as they will not be visible to the caller. // Dummy CachingCounters. No need to initialize as they will not be visible to the caller.
counters = new CachingCounters(); counters = new CachingCounters();
} }
String key = getKey(dataSpec); String key = buildCacheKey(dataSpec, cacheKeyFactory);
long start = dataSpec.absoluteStreamPosition; long start = dataSpec.absoluteStreamPosition;
long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key); long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key);
while (left != 0) { while (left != 0) {
...@@ -296,18 +297,41 @@ public final class CacheUtil { ...@@ -296,18 +297,41 @@ public final class CacheUtil {
} }
} }
/** Removes all of the data in the {@code cache} pointed by the {@code key}. */ /**
* Removes all of the data specified by the {@code dataSpec}.
*
* @param dataSpec Defines the data to be removed.
* @param cache A {@link Cache} to store the data.
* @param cacheKeyFactory An optional factory for cache keys.
*/
public static void remove(
DataSpec dataSpec, Cache cache, @Nullable CacheKeyFactory cacheKeyFactory) {
remove(cache, buildCacheKey(dataSpec, cacheKeyFactory));
}
/**
* Removes all of the data specified by the {@code key}.
*
* @param cache A {@link Cache} to store the data.
* @param key The key whose data should be removed.
*/
public static void remove(Cache cache, String key) { public static void remove(Cache cache, String key) {
NavigableSet<CacheSpan> cachedSpans = cache.getCachedSpans(key); NavigableSet<CacheSpan> cachedSpans = cache.getCachedSpans(key);
for (CacheSpan cachedSpan : cachedSpans) { for (CacheSpan cachedSpan : cachedSpans) {
try { try {
cache.removeSpan(cachedSpan); cache.removeSpan(cachedSpan);
} catch (Cache.CacheException e) { } catch (Cache.CacheException e) {
// do nothing // Do nothing.
} }
} }
} }
private static String buildCacheKey(
DataSpec dataSpec, @Nullable CacheKeyFactory cacheKeyFactory) {
return (cacheKeyFactory != null ? cacheKeyFactory : DEFAULT_CACHE_KEY_FACTORY)
.buildCacheKey(dataSpec);
}
private static void throwExceptionIfInterruptedOrCancelled(AtomicBoolean isCanceled) private static void throwExceptionIfInterruptedOrCancelled(AtomicBoolean isCanceled)
throws InterruptedException { throws InterruptedException {
if (Thread.interrupted() || (isCanceled != null && isCanceled.get())) { if (Thread.interrupted() || (isCanceled != null && isCanceled.get())) {
......
...@@ -338,7 +338,12 @@ public final class CacheDataSourceTest { ...@@ -338,7 +338,12 @@ public final class CacheDataSourceTest {
.appendReadData(1024 * 1024) .appendReadData(1024 * 1024)
.endData()); .endData());
CacheUtil.cache( CacheUtil.cache(
unboundedDataSpec, cache, upstream2, /* counters= */ null, /* isCanceled= */ null); unboundedDataSpec,
cache,
/* cacheKeyFactory= */ null,
upstream2,
/* counters= */ null,
/* isCanceled= */ null);
// Read the rest of the data. // Read the rest of the data.
TestUtil.readToEnd(cacheDataSource); TestUtil.readToEnd(cacheDataSource);
...@@ -382,7 +387,12 @@ public final class CacheDataSourceTest { ...@@ -382,7 +387,12 @@ public final class CacheDataSourceTest {
.appendReadData(1024 * 1024) .appendReadData(1024 * 1024)
.endData()); .endData());
CacheUtil.cache( CacheUtil.cache(
unboundedDataSpec, cache, upstream2, /* counters= */ null, /* isCanceled= */ null); unboundedDataSpec,
cache,
/* cacheKeyFactory= */ null,
upstream2,
/* counters= */ null,
/* isCanceled= */ null);
// Read the rest of the data. // Read the rest of the data.
TestUtil.readToEnd(cacheDataSource); TestUtil.readToEnd(cacheDataSource);
...@@ -400,7 +410,13 @@ public final class CacheDataSourceTest { ...@@ -400,7 +410,13 @@ public final class CacheDataSourceTest {
// Cache the latter half of the data. // Cache the latter half of the data.
int halfDataLength = 512; int halfDataLength = 512;
DataSpec dataSpec = buildDataSpec(halfDataLength, C.LENGTH_UNSET); DataSpec dataSpec = buildDataSpec(halfDataLength, C.LENGTH_UNSET);
CacheUtil.cache(dataSpec, cache, upstream, /* counters= */ null, /* isCanceled= */ null); CacheUtil.cache(
dataSpec,
cache,
/* cacheKeyFactory= */ null,
upstream,
/* counters= */ null,
/* isCanceled= */ null);
// Create cache read-only CacheDataSource. // Create cache read-only CacheDataSource.
CacheDataSource cacheDataSource = CacheDataSource cacheDataSource =
...@@ -411,7 +427,7 @@ public final class CacheDataSourceTest { ...@@ -411,7 +427,7 @@ public final class CacheDataSourceTest {
TestUtil.readExactly(cacheDataSource, 100); TestUtil.readExactly(cacheDataSource, 100);
// Delete cached data. // Delete cached data.
CacheUtil.remove(cache, defaultCacheKey); CacheUtil.remove(unboundedDataSpec, cache, /* cacheKeyFactory= */ null);
assertCacheEmpty(cache); assertCacheEmpty(cache);
// Read the rest of the data. // Read the rest of the data.
...@@ -430,7 +446,13 @@ public final class CacheDataSourceTest { ...@@ -430,7 +446,13 @@ public final class CacheDataSourceTest {
// Cache the latter half of the data. // Cache the latter half of the data.
int halfDataLength = 512; int halfDataLength = 512;
DataSpec dataSpec = buildDataSpec(/* position= */ 0, halfDataLength); DataSpec dataSpec = buildDataSpec(/* position= */ 0, halfDataLength);
CacheUtil.cache(dataSpec, cache, upstream, /* counters= */ null, /* isCanceled= */ null); CacheUtil.cache(
dataSpec,
cache,
/* cacheKeyFactory= */ null,
upstream,
/* counters= */ null,
/* isCanceled= */ null);
// Create blocking CacheDataSource. // Create blocking CacheDataSource.
CacheDataSource cacheDataSource = CacheDataSource cacheDataSource =
......
...@@ -15,13 +15,9 @@ ...@@ -15,13 +15,9 @@
*/ */
package com.google.android.exoplayer2.upstream.cache; package com.google.android.exoplayer2.upstream.cache;
import static android.net.Uri.EMPTY;
import static android.net.Uri.parse;
import static com.google.android.exoplayer2.C.LENGTH_UNSET; import static com.google.android.exoplayer2.C.LENGTH_UNSET;
import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCacheEmpty; import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCacheEmpty;
import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedData; import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedData;
import static com.google.android.exoplayer2.upstream.cache.CacheUtil.generateKey;
import static com.google.android.exoplayer2.upstream.cache.CacheUtil.getKey;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
...@@ -107,50 +103,40 @@ public final class CacheUtilTest { ...@@ -107,50 +103,40 @@ public final class CacheUtilTest {
@Test @Test
public void testGenerateKey() throws Exception { public void testGenerateKey() throws Exception {
assertThat(generateKey(EMPTY)).isNotNull(); assertThat(CacheUtil.generateKey(Uri.EMPTY)).isNotNull();
Uri testUri = Uri.parse("test"); Uri testUri = Uri.parse("test");
String key = CacheUtil.generateKey(testUri); String key = CacheUtil.generateKey(testUri);
assertThat(key).isNotNull(); assertThat(key).isNotNull();
// Should generate the same key for the same input // Should generate the same key for the same input.
assertThat(generateKey(testUri)).isEqualTo(key); assertThat(CacheUtil.generateKey(testUri)).isEqualTo(key);
// Should generate different key for different input // Should generate different key for different input.
assertThat(key.equals(generateKey(parse("test2")))).isFalse(); assertThat(key.equals(CacheUtil.generateKey(Uri.parse("test2")))).isFalse();
}
@Test
public void testGetKey() throws Exception {
Uri testUri = Uri.parse("test");
String key = "key";
// If DataSpec.key is present, returns it
assertThat(getKey(new DataSpec(testUri, 0, LENGTH_UNSET, key))).isEqualTo(key);
// If not generates a new one using DataSpec.uri
assertThat(getKey(new DataSpec(testUri, 0, LENGTH_UNSET, null)))
.isEqualTo(generateKey(testUri));
} }
@Test @Test
public void testDefaultCacheKeyFactory_buildCacheKey() throws Exception { public void testDefaultCacheKeyFactory_buildCacheKey() throws Exception {
Uri testUri = Uri.parse("test"); Uri testUri = Uri.parse("test");
String key = "key"; String key = "key";
// If DataSpec.key is present, returns it // If DataSpec.key is present, returns it.
assertThat( assertThat(
CacheUtil.DEFAULT_CACHE_KEY_FACTORY.buildCacheKey( CacheUtil.DEFAULT_CACHE_KEY_FACTORY.buildCacheKey(
new DataSpec(testUri, 0, LENGTH_UNSET, key))) new DataSpec(testUri, 0, LENGTH_UNSET, key)))
.isEqualTo(key); .isEqualTo(key);
// If not generates a new one using DataSpec.uri // If not generates a new one using DataSpec.uri.
assertThat( assertThat(
CacheUtil.DEFAULT_CACHE_KEY_FACTORY.buildCacheKey( CacheUtil.DEFAULT_CACHE_KEY_FACTORY.buildCacheKey(
new DataSpec(testUri, 0, LENGTH_UNSET, null))) new DataSpec(testUri, 0, LENGTH_UNSET, null)))
.isEqualTo(generateKey(testUri)); .isEqualTo(testUri.toString());
} }
@Test @Test
public void testGetCachedNoData() throws Exception { public void testGetCachedNoData() throws Exception {
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.getCached(new DataSpec(Uri.parse("test")), mockCache, counters); CacheUtil.getCached(
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null, counters);
assertCounters(counters, 0, 0, C.LENGTH_UNSET); assertCounters(counters, 0, 0, C.LENGTH_UNSET);
} }
...@@ -160,7 +146,8 @@ public final class CacheUtilTest { ...@@ -160,7 +146,8 @@ public final class CacheUtilTest {
// Mock there is 100 bytes cached at the beginning // Mock there is 100 bytes cached at the beginning
mockCache.spansAndGaps = new int[] {100}; mockCache.spansAndGaps = new int[] {100};
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.getCached(new DataSpec(Uri.parse("test")), mockCache, counters); CacheUtil.getCached(
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null, counters);
assertCounters(counters, 100, 0, C.LENGTH_UNSET); assertCounters(counters, 100, 0, C.LENGTH_UNSET);
} }
...@@ -169,7 +156,8 @@ public final class CacheUtilTest { ...@@ -169,7 +156,8 @@ public final class CacheUtilTest {
public void testGetCachedNoDataKnownLength() throws Exception { public void testGetCachedNoDataKnownLength() throws Exception {
mockCache.contentLength = 1000; mockCache.contentLength = 1000;
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.getCached(new DataSpec(Uri.parse("test")), mockCache, counters); CacheUtil.getCached(
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null, counters);
assertCounters(counters, 0, 0, 1000); assertCounters(counters, 0, 0, 1000);
} }
...@@ -179,7 +167,8 @@ public final class CacheUtilTest { ...@@ -179,7 +167,8 @@ public final class CacheUtilTest {
mockCache.contentLength = 1000; mockCache.contentLength = 1000;
mockCache.spansAndGaps = new int[] {100, 100, 200}; mockCache.spansAndGaps = new int[] {100, 100, 200};
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.getCached(new DataSpec(Uri.parse("test")), mockCache, counters); CacheUtil.getCached(
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null, counters);
assertCounters(counters, 300, 0, 1000); assertCounters(counters, 300, 0, 1000);
} }
...@@ -191,7 +180,12 @@ public final class CacheUtilTest { ...@@ -191,7 +180,12 @@ public final class CacheUtilTest {
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.cache( CacheUtil.cache(
new DataSpec(Uri.parse("test_data")), cache, dataSource, counters, /* isCanceled= */ null); new DataSpec(Uri.parse("test_data")),
cache,
/* cacheKeyFactory= */ null,
dataSource,
counters,
/* isCanceled= */ null);
assertCounters(counters, 0, 100, 100); assertCounters(counters, 0, 100, 100);
assertCachedData(cache, fakeDataSet); assertCachedData(cache, fakeDataSet);
...@@ -205,11 +199,18 @@ public final class CacheUtilTest { ...@@ -205,11 +199,18 @@ public final class CacheUtilTest {
Uri testUri = Uri.parse("test_data"); Uri testUri = Uri.parse("test_data");
DataSpec dataSpec = new DataSpec(testUri, 10, 20, null); DataSpec dataSpec = new DataSpec(testUri, 10, 20, null);
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.cache(dataSpec, cache, dataSource, counters, /* isCanceled= */ null); CacheUtil.cache(
dataSpec, cache, /* cacheKeyFactory= */ null, dataSource, counters, /* isCanceled= */ null);
assertCounters(counters, 0, 20, 20); assertCounters(counters, 0, 20, 20);
CacheUtil.cache(new DataSpec(testUri), cache, dataSource, counters, /* isCanceled= */ null); CacheUtil.cache(
new DataSpec(testUri),
cache,
/* cacheKeyFactory= */ null,
dataSource,
counters,
/* isCanceled= */ null);
assertCounters(counters, 20, 80, 100); assertCounters(counters, 20, 80, 100);
assertCachedData(cache, fakeDataSet); assertCachedData(cache, fakeDataSet);
...@@ -224,7 +225,8 @@ public final class CacheUtilTest { ...@@ -224,7 +225,8 @@ public final class CacheUtilTest {
DataSpec dataSpec = new DataSpec(Uri.parse("test_data")); DataSpec dataSpec = new DataSpec(Uri.parse("test_data"));
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.cache(dataSpec, cache, dataSource, counters, /* isCanceled= */ null); CacheUtil.cache(
dataSpec, cache, /* cacheKeyFactory= */ null, dataSource, counters, /* isCanceled= */ null);
assertCounters(counters, 0, 100, 100); assertCounters(counters, 0, 100, 100);
assertCachedData(cache, fakeDataSet); assertCachedData(cache, fakeDataSet);
...@@ -240,11 +242,18 @@ public final class CacheUtilTest { ...@@ -240,11 +242,18 @@ public final class CacheUtilTest {
Uri testUri = Uri.parse("test_data"); Uri testUri = Uri.parse("test_data");
DataSpec dataSpec = new DataSpec(testUri, 10, 20, null); DataSpec dataSpec = new DataSpec(testUri, 10, 20, null);
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.cache(dataSpec, cache, dataSource, counters, /* isCanceled= */ null); CacheUtil.cache(
dataSpec, cache, /* cacheKeyFactory= */ null, dataSource, counters, /* isCanceled= */ null);
assertCounters(counters, 0, 20, 20); assertCounters(counters, 0, 20, 20);
CacheUtil.cache(new DataSpec(testUri), cache, dataSource, counters, /* isCanceled= */ null); CacheUtil.cache(
new DataSpec(testUri),
cache,
/* cacheKeyFactory= */ null,
dataSource,
counters,
/* isCanceled= */ null);
assertCounters(counters, 20, 80, 100); assertCounters(counters, 20, 80, 100);
assertCachedData(cache, fakeDataSet); assertCachedData(cache, fakeDataSet);
...@@ -258,7 +267,8 @@ public final class CacheUtilTest { ...@@ -258,7 +267,8 @@ public final class CacheUtilTest {
Uri testUri = Uri.parse("test_data"); Uri testUri = Uri.parse("test_data");
DataSpec dataSpec = new DataSpec(testUri, 0, 1000, null); DataSpec dataSpec = new DataSpec(testUri, 0, 1000, null);
CachingCounters counters = new CachingCounters(); CachingCounters counters = new CachingCounters();
CacheUtil.cache(dataSpec, cache, dataSource, counters, /* isCanceled= */ null); CacheUtil.cache(
dataSpec, cache, /* cacheKeyFactory= */ null, dataSource, counters, /* isCanceled= */ null);
assertCounters(counters, 0, 100, 1000); assertCounters(counters, 0, 100, 1000);
assertCachedData(cache, fakeDataSet); assertCachedData(cache, fakeDataSet);
...@@ -276,6 +286,7 @@ public final class CacheUtilTest { ...@@ -276,6 +286,7 @@ public final class CacheUtilTest {
CacheUtil.cache( CacheUtil.cache(
dataSpec, dataSpec,
cache, cache,
/* cacheKeyFactory= */ null,
new CacheDataSource(cache, dataSource), new CacheDataSource(cache, dataSource),
new byte[CacheUtil.DEFAULT_BUFFER_SIZE_BYTES], new byte[CacheUtil.DEFAULT_BUFFER_SIZE_BYTES],
/* priorityTaskManager= */ null, /* priorityTaskManager= */ null,
...@@ -304,7 +315,12 @@ public final class CacheUtilTest { ...@@ -304,7 +315,12 @@ public final class CacheUtilTest {
FakeDataSource dataSource = new FakeDataSource(fakeDataSet); FakeDataSource dataSource = new FakeDataSource(fakeDataSet);
CacheUtil.cache( CacheUtil.cache(
new DataSpec(Uri.parse("test_data")), cache, dataSource, counters, /* isCanceled= */ null); new DataSpec(Uri.parse("test_data")),
cache,
/* cacheKeyFactory= */ null,
dataSource,
counters,
/* isCanceled= */ null);
assertCounters(counters, 0, 300, 300); assertCounters(counters, 0, 300, 300);
assertCachedData(cache, fakeDataSet); assertCachedData(cache, fakeDataSet);
...@@ -316,10 +332,12 @@ public final class CacheUtilTest { ...@@ -316,10 +332,12 @@ public final class CacheUtilTest {
FakeDataSource dataSource = new FakeDataSource(fakeDataSet); FakeDataSource dataSource = new FakeDataSource(fakeDataSet);
Uri uri = Uri.parse("test_data"); Uri uri = Uri.parse("test_data");
DataSpec dataSpec = new DataSpec(uri);
CacheUtil.cache( CacheUtil.cache(
new DataSpec(uri), dataSpec,
cache, cache,
// set maxCacheFileSize to 10 to make sure there are multiple spans /* cacheKeyFactory= */ null,
// Set maxCacheFileSize to 10 to make sure there are multiple spans.
new CacheDataSource(cache, dataSource, 0, 10), new CacheDataSource(cache, dataSource, 0, 10),
new byte[CacheUtil.DEFAULT_BUFFER_SIZE_BYTES], new byte[CacheUtil.DEFAULT_BUFFER_SIZE_BYTES],
/* priorityTaskManager= */ null, /* priorityTaskManager= */ null,
...@@ -327,7 +345,7 @@ public final class CacheUtilTest { ...@@ -327,7 +345,7 @@ public final class CacheUtilTest {
/* counters= */ null, /* counters= */ null,
/* isCanceled= */ null, /* isCanceled= */ null,
true); true);
CacheUtil.remove(cache, CacheUtil.generateKey(uri)); CacheUtil.remove(dataSpec, cache, /* cacheKeyFactory= */ null);
assertCacheEmpty(cache); assertCacheEmpty(cache);
} }
...@@ -338,5 +356,4 @@ public final class CacheUtilTest { ...@@ -338,5 +356,4 @@ public final class CacheUtilTest {
assertThat(counters.newlyCachedBytes).isEqualTo(newlyCachedBytes); assertThat(counters.newlyCachedBytes).isEqualTo(newlyCachedBytes);
assertThat(counters.contentLength).isEqualTo(contentLength); assertThat(counters.contentLength).isEqualTo(contentLength);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment