mirror of
https://github.com/androidx/media.git
synced 2025-05-12 01:59:50 +08:00
Make CacheUtil only about writing
A subsequent change will rename it to CacheWriter and make it instantiable. Issue: #5978 PiperOrigin-RevId: 312648623
This commit is contained in:
parent
1154e8098a
commit
4384ef5b73
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.offline;
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Pair;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
@ -30,6 +29,7 @@ import com.google.android.exoplayer2.upstream.cache.Cache;
|
||||
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.ContentMetadata;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.PriorityTaskManager;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
@ -136,11 +136,18 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
|
||||
long contentLength = 0;
|
||||
long bytesDownloaded = 0;
|
||||
for (int i = segments.size() - 1; i >= 0; i--) {
|
||||
Segment segment = segments.get(i);
|
||||
Pair<Long, Long> segmentLengthAndBytesDownloaded =
|
||||
CacheUtil.getCached(segment.dataSpec, cache, cacheKeyFactory);
|
||||
long segmentLength = segmentLengthAndBytesDownloaded.first;
|
||||
long segmentBytesDownloaded = segmentLengthAndBytesDownloaded.second;
|
||||
DataSpec dataSpec = segments.get(i).dataSpec;
|
||||
String cacheKey = cacheKeyFactory.buildCacheKey(dataSpec);
|
||||
long segmentLength = dataSpec.length;
|
||||
if (segmentLength == C.LENGTH_UNSET) {
|
||||
long resourceLength =
|
||||
ContentMetadata.getContentLength(cache.getContentMetadata(cacheKey));
|
||||
if (resourceLength != C.LENGTH_UNSET) {
|
||||
segmentLength = resourceLength - dataSpec.position;
|
||||
}
|
||||
}
|
||||
long segmentBytesDownloaded =
|
||||
cache.getCachedBytes(cacheKey, dataSpec.position, segmentLength);
|
||||
bytesDownloaded += segmentBytesDownloaded;
|
||||
if (segmentLength != C.LENGTH_UNSET) {
|
||||
if (segmentLength == segmentBytesDownloaded) {
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.upstream.cache;
|
||||
|
||||
import android.util.Pair;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import com.google.android.exoplayer2.C;
|
||||
@ -57,38 +56,6 @@ public final class CacheUtil {
|
||||
@Deprecated
|
||||
public static final CacheKeyFactory DEFAULT_CACHE_KEY_FACTORY = CacheKeyFactory.DEFAULT;
|
||||
|
||||
/**
|
||||
* Queries the cache to obtain the request length and the number of bytes already cached for a
|
||||
* given {@link DataSpec}.
|
||||
*
|
||||
* @param dataSpec Defines the data to be checked.
|
||||
* @param cache A {@link Cache} which has the data.
|
||||
* @param cacheKeyFactory An optional factory for cache keys.
|
||||
* @return A pair containing the request length and the number of bytes that are already cached.
|
||||
*/
|
||||
public static Pair<Long, Long> getCached(
|
||||
DataSpec dataSpec, Cache cache, @Nullable CacheKeyFactory cacheKeyFactory) {
|
||||
String key = buildCacheKey(dataSpec, cacheKeyFactory);
|
||||
long position = dataSpec.position;
|
||||
long requestLength = getRequestLength(dataSpec, cache, key);
|
||||
long bytesAlreadyCached = 0;
|
||||
long bytesLeft = requestLength;
|
||||
while (bytesLeft != 0) {
|
||||
long blockLength = cache.getCachedLength(key, position, bytesLeft);
|
||||
if (blockLength > 0) {
|
||||
bytesAlreadyCached += blockLength;
|
||||
} else {
|
||||
blockLength = -blockLength;
|
||||
if (blockLength == Long.MAX_VALUE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
position += blockLength;
|
||||
bytesLeft -= bytesLeft == C.LENGTH_UNSET ? 0 : blockLength;
|
||||
}
|
||||
return Pair.create(requestLength, bytesAlreadyCached);
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the data defined by {@code dataSpec}, skipping already cached data. Caching stops early
|
||||
* if the end of the input is reached.
|
||||
@ -157,23 +124,26 @@ public final class CacheUtil {
|
||||
Assertions.checkNotNull(temporaryBuffer);
|
||||
|
||||
Cache cache = dataSource.getCache();
|
||||
CacheKeyFactory cacheKeyFactory = dataSource.getCacheKeyFactory();
|
||||
String key = buildCacheKey(dataSpec, cacheKeyFactory);
|
||||
long bytesLeft;
|
||||
String cacheKey = dataSource.getCacheKeyFactory().buildCacheKey(dataSpec);
|
||||
long requestLength = dataSpec.length;
|
||||
if (requestLength == C.LENGTH_UNSET) {
|
||||
long resourceLength = ContentMetadata.getContentLength(cache.getContentMetadata(cacheKey));
|
||||
if (resourceLength != C.LENGTH_UNSET) {
|
||||
requestLength = resourceLength - dataSpec.position;
|
||||
}
|
||||
}
|
||||
long bytesCached = cache.getCachedBytes(cacheKey, dataSpec.position, requestLength);
|
||||
@Nullable ProgressNotifier progressNotifier = null;
|
||||
if (progressListener != null) {
|
||||
progressNotifier = new ProgressNotifier(progressListener);
|
||||
Pair<Long, Long> lengthAndBytesAlreadyCached = getCached(dataSpec, cache, cacheKeyFactory);
|
||||
progressNotifier.init(lengthAndBytesAlreadyCached.first, lengthAndBytesAlreadyCached.second);
|
||||
bytesLeft = lengthAndBytesAlreadyCached.first;
|
||||
} else {
|
||||
bytesLeft = getRequestLength(dataSpec, cache, key);
|
||||
progressNotifier.init(requestLength, bytesCached);
|
||||
}
|
||||
|
||||
long position = dataSpec.position;
|
||||
long bytesLeft = requestLength;
|
||||
while (bytesLeft != 0) {
|
||||
throwExceptionIfCanceled(isCanceled);
|
||||
long blockLength = cache.getCachedLength(key, position, bytesLeft);
|
||||
long blockLength = cache.getCachedLength(cacheKey, position, bytesLeft);
|
||||
if (blockLength > 0) {
|
||||
// Skip already cached data.
|
||||
} else {
|
||||
@ -206,15 +176,6 @@ public final class CacheUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static long getRequestLength(DataSpec dataSpec, Cache cache, String key) {
|
||||
if (dataSpec.length != C.LENGTH_UNSET) {
|
||||
return dataSpec.length;
|
||||
} else {
|
||||
long contentLength = ContentMetadata.getContentLength(cache.getContentMetadata(key));
|
||||
return contentLength == C.LENGTH_UNSET ? C.LENGTH_UNSET : contentLength - dataSpec.position;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and discards all data specified by the {@code dataSpec}.
|
||||
*
|
||||
@ -309,12 +270,6 @@ public final class CacheUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildCacheKey(
|
||||
DataSpec dataSpec, @Nullable CacheKeyFactory cacheKeyFactory) {
|
||||
return (cacheKeyFactory != null ? cacheKeyFactory : CacheKeyFactory.DEFAULT)
|
||||
.buildCacheKey(dataSpec);
|
||||
}
|
||||
|
||||
private static void throwExceptionIfCanceled(@Nullable AtomicBoolean isCanceled)
|
||||
throws InterruptedIOException {
|
||||
if (isCanceled != null && isCanceled.get()) {
|
||||
|
@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Pair;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.C;
|
||||
@ -104,65 +103,6 @@ public final class CacheUtilTest {
|
||||
Util.recursiveDelete(tempFolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCachedNoData() {
|
||||
Pair<Long, Long> contentLengthAndBytesCached =
|
||||
CacheUtil.getCached(
|
||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
||||
|
||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(C.LENGTH_UNSET);
|
||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCachedDataUnknownLength() {
|
||||
// Mock there is 100 bytes cached at the beginning
|
||||
mockCache.spansAndGaps = new int[] {100};
|
||||
Pair<Long, Long> contentLengthAndBytesCached =
|
||||
CacheUtil.getCached(
|
||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
||||
|
||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(C.LENGTH_UNSET);
|
||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(100);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCachedNoDataKnownLength() {
|
||||
mockCache.contentLength = 1000;
|
||||
Pair<Long, Long> contentLengthAndBytesCached =
|
||||
CacheUtil.getCached(
|
||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
||||
|
||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(1000);
|
||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCached() {
|
||||
mockCache.contentLength = 1000;
|
||||
mockCache.spansAndGaps = new int[] {100, 100, 200};
|
||||
Pair<Long, Long> contentLengthAndBytesCached =
|
||||
CacheUtil.getCached(
|
||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
||||
|
||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(1000);
|
||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(300);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCachedFromNonZeroPosition() {
|
||||
mockCache.contentLength = 1000;
|
||||
mockCache.spansAndGaps = new int[] {100, 100, 200};
|
||||
Pair<Long, Long> contentLengthAndBytesCached =
|
||||
CacheUtil.getCached(
|
||||
new DataSpec(Uri.parse("test"), /* position= */ 100, /* length= */ C.LENGTH_UNSET),
|
||||
mockCache,
|
||||
/* cacheKeyFactory= */ null);
|
||||
|
||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(900);
|
||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(200);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cache() throws Exception {
|
||||
FakeDataSet fakeDataSet = new FakeDataSet().setRandomData("test_data", 100);
|
||||
|
Loading…
x
Reference in New Issue
Block a user