Rabbit-R1/android (non root)/java/sources/androidx/media3/datasource/cache/CacheDataSource.java
2024-05-21 17:08:36 -04:00

513 lines
20 KiB
Java

package androidx.media3.datasource.cache;
import android.net.Uri;
import androidx.media3.common.PriorityTaskManager;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.Util;
import androidx.media3.datasource.DataSink;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DataSourceException;
import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.FileDataSource;
import androidx.media3.datasource.PlaceholderDataSource;
import androidx.media3.datasource.PriorityDataSource;
import androidx.media3.datasource.TeeDataSource;
import androidx.media3.datasource.TransferListener;
import androidx.media3.datasource.cache.Cache;
import androidx.media3.datasource.cache.CacheDataSink;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/* loaded from: classes2.dex */
public final class CacheDataSource implements DataSource {
public static final int CACHE_IGNORED_REASON_ERROR = 0;
public static final int CACHE_IGNORED_REASON_UNSET_LENGTH = 1;
private static final int CACHE_NOT_IGNORED = -1;
public static final int FLAG_BLOCK_ON_CACHE = 1;
public static final int FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS = 4;
public static final int FLAG_IGNORE_CACHE_ON_ERROR = 2;
private static final long MIN_READ_BEFORE_CHECKING_CACHE = 102400;
private Uri actualUri;
private final boolean blockOnCache;
private long bytesRemaining;
private final Cache cache;
private final CacheKeyFactory cacheKeyFactory;
private final DataSource cacheReadDataSource;
private final DataSource cacheWriteDataSource;
private long checkCachePosition;
private DataSource currentDataSource;
private long currentDataSourceBytesRead;
private DataSpec currentDataSpec;
private CacheSpan currentHoleSpan;
private boolean currentRequestIgnoresCache;
private final EventListener eventListener;
private final boolean ignoreCacheForUnsetLengthRequests;
private final boolean ignoreCacheOnError;
private long readPosition;
private DataSpec requestDataSpec;
private boolean seenCacheError;
private long totalCachedBytesRead;
private final DataSource upstreamDataSource;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
@Documented
@Retention(RetentionPolicy.SOURCE)
/* loaded from: classes2.dex */
public @interface CacheIgnoredReason {
}
/* loaded from: classes2.dex */
public interface EventListener {
void onCacheIgnored(int i);
void onCachedBytesRead(long j, long j2);
}
@Target({ElementType.TYPE_USE})
@Documented
@Retention(RetentionPolicy.SOURCE)
/* loaded from: classes2.dex */
public @interface Flags {
}
private boolean isBypassingCache() {
return this.currentDataSource == this.upstreamDataSource;
}
private boolean isReadingFromCache() {
return this.currentDataSource == this.cacheReadDataSource;
}
private boolean isWritingToCache() {
return this.currentDataSource == this.cacheWriteDataSource;
}
public Cache getCache() {
return this.cache;
}
public CacheKeyFactory getCacheKeyFactory() {
return this.cacheKeyFactory;
}
@Override // androidx.media3.datasource.DataSource
public Uri getUri() {
return this.actualUri;
}
/* loaded from: classes2.dex */
public static final class Factory implements DataSource.Factory {
private Cache cache;
private boolean cacheIsReadOnly;
private DataSink.Factory cacheWriteDataSinkFactory;
private EventListener eventListener;
private int flags;
private DataSource.Factory upstreamDataSourceFactory;
private int upstreamPriority;
private PriorityTaskManager upstreamPriorityTaskManager;
private DataSource.Factory cacheReadDataSourceFactory = new FileDataSource.Factory();
private CacheKeyFactory cacheKeyFactory = CacheKeyFactory.DEFAULT;
public Cache getCache() {
return this.cache;
}
public CacheKeyFactory getCacheKeyFactory() {
return this.cacheKeyFactory;
}
public PriorityTaskManager getUpstreamPriorityTaskManager() {
return this.upstreamPriorityTaskManager;
}
public Factory setCache(Cache cache) {
this.cache = cache;
return this;
}
public Factory setCacheKeyFactory(CacheKeyFactory cacheKeyFactory) {
this.cacheKeyFactory = cacheKeyFactory;
return this;
}
public Factory setCacheReadDataSourceFactory(DataSource.Factory factory) {
this.cacheReadDataSourceFactory = factory;
return this;
}
public Factory setCacheWriteDataSinkFactory(DataSink.Factory factory) {
this.cacheWriteDataSinkFactory = factory;
this.cacheIsReadOnly = factory == null;
return this;
}
public Factory setEventListener(EventListener eventListener) {
this.eventListener = eventListener;
return this;
}
public Factory setFlags(int i) {
this.flags = i;
return this;
}
public Factory setUpstreamDataSourceFactory(DataSource.Factory factory) {
this.upstreamDataSourceFactory = factory;
return this;
}
public Factory setUpstreamPriority(int i) {
this.upstreamPriority = i;
return this;
}
public Factory setUpstreamPriorityTaskManager(PriorityTaskManager priorityTaskManager) {
this.upstreamPriorityTaskManager = priorityTaskManager;
return this;
}
@Override // androidx.media3.datasource.DataSource.Factory
public CacheDataSource createDataSource() {
DataSource.Factory factory = this.upstreamDataSourceFactory;
return createDataSourceInternal(factory != null ? factory.createDataSource() : null, this.flags, this.upstreamPriority);
}
public CacheDataSource createDataSourceForDownloading() {
DataSource.Factory factory = this.upstreamDataSourceFactory;
return createDataSourceInternal(factory != null ? factory.createDataSource() : null, this.flags | 1, -1000);
}
public CacheDataSource createDataSourceForRemovingDownload() {
return createDataSourceInternal(null, this.flags | 1, -1000);
}
private CacheDataSource createDataSourceInternal(DataSource dataSource, int i, int i2) {
DataSink dataSink;
Cache cache = (Cache) Assertions.checkNotNull(this.cache);
if (this.cacheIsReadOnly || dataSource == null) {
dataSink = null;
} else {
DataSink.Factory factory = this.cacheWriteDataSinkFactory;
if (factory != null) {
dataSink = factory.createDataSink();
} else {
dataSink = new CacheDataSink.Factory().setCache(cache).createDataSink();
}
}
return new CacheDataSource(cache, dataSource, this.cacheReadDataSourceFactory.createDataSource(), dataSink, this.cacheKeyFactory, i, this.upstreamPriorityTaskManager, i2, this.eventListener);
}
}
public CacheDataSource(Cache cache, DataSource dataSource) {
this(cache, dataSource, 0);
}
public CacheDataSource(Cache cache, DataSource dataSource, int i) {
this(cache, dataSource, new FileDataSource(), new CacheDataSink(cache, 5242880L), i, null);
}
public CacheDataSource(Cache cache, DataSource dataSource, DataSource dataSource2, DataSink dataSink, int i, EventListener eventListener) {
this(cache, dataSource, dataSource2, dataSink, i, eventListener, null);
}
public CacheDataSource(Cache cache, DataSource dataSource, DataSource dataSource2, DataSink dataSink, int i, EventListener eventListener, CacheKeyFactory cacheKeyFactory) {
this(cache, dataSource, dataSource2, dataSink, cacheKeyFactory, i, null, 0, eventListener);
}
private CacheDataSource(Cache cache, DataSource dataSource, DataSource dataSource2, DataSink dataSink, CacheKeyFactory cacheKeyFactory, int i, PriorityTaskManager priorityTaskManager, int i2, EventListener eventListener) {
this.cache = cache;
this.cacheReadDataSource = dataSource2;
this.cacheKeyFactory = cacheKeyFactory == null ? CacheKeyFactory.DEFAULT : cacheKeyFactory;
this.blockOnCache = (i & 1) != 0;
this.ignoreCacheOnError = (i & 2) != 0;
this.ignoreCacheForUnsetLengthRequests = (i & 4) != 0;
if (dataSource != null) {
dataSource = priorityTaskManager != null ? new PriorityDataSource(dataSource, priorityTaskManager, i2) : dataSource;
this.upstreamDataSource = dataSource;
this.cacheWriteDataSource = dataSink != null ? new TeeDataSource(dataSource, dataSink) : null;
} else {
this.upstreamDataSource = PlaceholderDataSource.INSTANCE;
this.cacheWriteDataSource = null;
}
this.eventListener = eventListener;
}
@Override // androidx.media3.datasource.DataSource
public void addTransferListener(TransferListener transferListener) {
Assertions.checkNotNull(transferListener);
this.cacheReadDataSource.addTransferListener(transferListener);
this.upstreamDataSource.addTransferListener(transferListener);
}
@Override // androidx.media3.datasource.DataSource
public long open(DataSpec dataSpec) throws IOException {
long min;
try {
String buildCacheKey = this.cacheKeyFactory.buildCacheKey(dataSpec);
DataSpec build = dataSpec.buildUpon().setKey(buildCacheKey).build();
this.requestDataSpec = build;
this.actualUri = getRedirectedUriOrDefault(this.cache, buildCacheKey, build.uri);
this.readPosition = dataSpec.position;
int shouldIgnoreCacheForRequest = shouldIgnoreCacheForRequest(dataSpec);
boolean z = shouldIgnoreCacheForRequest != -1;
this.currentRequestIgnoresCache = z;
if (z) {
notifyCacheIgnored(shouldIgnoreCacheForRequest);
}
if (this.currentRequestIgnoresCache) {
this.bytesRemaining = -1L;
} else {
long contentLength = ContentMetadata.getContentLength(this.cache.getContentMetadata(buildCacheKey));
this.bytesRemaining = contentLength;
if (contentLength != -1) {
long j = contentLength - dataSpec.position;
this.bytesRemaining = j;
if (j < 0) {
throw new DataSourceException(2008);
}
}
}
if (dataSpec.length != -1) {
long j2 = this.bytesRemaining;
if (j2 == -1) {
min = dataSpec.length;
} else {
min = Math.min(j2, dataSpec.length);
}
this.bytesRemaining = min;
}
long j3 = this.bytesRemaining;
if (j3 > 0 || j3 == -1) {
openNextSource(build, false);
}
return dataSpec.length != -1 ? dataSpec.length : this.bytesRemaining;
} catch (Throwable th) {
handleBeforeThrow(th);
throw th;
}
}
@Override // androidx.media3.common.DataReader
public int read(byte[] bArr, int i, int i2) throws IOException {
if (i2 == 0) {
return 0;
}
if (this.bytesRemaining == 0) {
return -1;
}
DataSpec dataSpec = (DataSpec) Assertions.checkNotNull(this.requestDataSpec);
DataSpec dataSpec2 = (DataSpec) Assertions.checkNotNull(this.currentDataSpec);
try {
if (this.readPosition >= this.checkCachePosition) {
openNextSource(dataSpec, true);
}
int read = ((DataSource) Assertions.checkNotNull(this.currentDataSource)).read(bArr, i, i2);
if (read != -1) {
if (isReadingFromCache()) {
this.totalCachedBytesRead += read;
}
long j = read;
this.readPosition += j;
this.currentDataSourceBytesRead += j;
long j2 = this.bytesRemaining;
if (j2 != -1) {
this.bytesRemaining = j2 - j;
}
} else if (isReadingFromUpstream() && (dataSpec2.length == -1 || this.currentDataSourceBytesRead < dataSpec2.length)) {
setNoBytesRemainingAndMaybeStoreLength((String) Util.castNonNull(dataSpec.key));
} else {
long j3 = this.bytesRemaining;
if (j3 <= 0) {
if (j3 == -1) {
}
}
closeCurrentSource();
openNextSource(dataSpec, false);
return read(bArr, i, i2);
}
return read;
} catch (Throwable th) {
handleBeforeThrow(th);
throw th;
}
}
@Override // androidx.media3.datasource.DataSource
public Map<String, List<String>> getResponseHeaders() {
if (isReadingFromUpstream()) {
return this.upstreamDataSource.getResponseHeaders();
}
return Collections.emptyMap();
}
@Override // androidx.media3.datasource.DataSource
public void close() throws IOException {
this.requestDataSpec = null;
this.actualUri = null;
this.readPosition = 0L;
notifyBytesRead();
try {
closeCurrentSource();
} catch (Throwable th) {
handleBeforeThrow(th);
throw th;
}
}
private void openNextSource(DataSpec dataSpec, boolean z) throws IOException {
CacheSpan startReadWrite;
long j;
DataSpec build;
DataSource dataSource;
String str = (String) Util.castNonNull(dataSpec.key);
if (this.currentRequestIgnoresCache) {
startReadWrite = null;
} else if (this.blockOnCache) {
try {
startReadWrite = this.cache.startReadWrite(str, this.readPosition, this.bytesRemaining);
} catch (InterruptedException unused) {
Thread.currentThread().interrupt();
throw new InterruptedIOException();
}
} else {
startReadWrite = this.cache.startReadWriteNonBlocking(str, this.readPosition, this.bytesRemaining);
}
if (startReadWrite == null) {
dataSource = this.upstreamDataSource;
build = dataSpec.buildUpon().setPosition(this.readPosition).setLength(this.bytesRemaining).build();
} else if (startReadWrite.isCached) {
Uri fromFile = Uri.fromFile((File) Util.castNonNull(startReadWrite.file));
long j2 = startReadWrite.position;
long j3 = this.readPosition - j2;
long j4 = startReadWrite.length - j3;
long j5 = this.bytesRemaining;
if (j5 != -1) {
j4 = Math.min(j4, j5);
}
build = dataSpec.buildUpon().setUri(fromFile).setUriPositionOffset(j2).setPosition(j3).setLength(j4).build();
dataSource = this.cacheReadDataSource;
} else {
if (startReadWrite.isOpenEnded()) {
j = this.bytesRemaining;
} else {
j = startReadWrite.length;
long j6 = this.bytesRemaining;
if (j6 != -1) {
j = Math.min(j, j6);
}
}
build = dataSpec.buildUpon().setPosition(this.readPosition).setLength(j).build();
dataSource = this.cacheWriteDataSource;
if (dataSource == null) {
dataSource = this.upstreamDataSource;
this.cache.releaseHoleSpan(startReadWrite);
startReadWrite = null;
}
}
this.checkCachePosition = (this.currentRequestIgnoresCache || dataSource != this.upstreamDataSource) ? Long.MAX_VALUE : this.readPosition + MIN_READ_BEFORE_CHECKING_CACHE;
if (z) {
Assertions.checkState(isBypassingCache());
if (dataSource == this.upstreamDataSource) {
return;
}
try {
closeCurrentSource();
} finally {
}
}
if (startReadWrite != null && startReadWrite.isHoleSpan()) {
this.currentHoleSpan = startReadWrite;
}
this.currentDataSource = dataSource;
this.currentDataSpec = build;
this.currentDataSourceBytesRead = 0L;
long open = dataSource.open(build);
ContentMetadataMutations contentMetadataMutations = new ContentMetadataMutations();
if (build.length == -1 && open != -1) {
this.bytesRemaining = open;
ContentMetadataMutations.setContentLength(contentMetadataMutations, this.readPosition + open);
}
if (isReadingFromUpstream()) {
this.actualUri = dataSource.getUri();
ContentMetadataMutations.setRedirectedUri(contentMetadataMutations, dataSpec.uri.equals(this.actualUri) ^ true ? this.actualUri : null);
}
if (isWritingToCache()) {
this.cache.applyContentMetadataMutations(str, contentMetadataMutations);
}
}
private void setNoBytesRemainingAndMaybeStoreLength(String str) throws IOException {
this.bytesRemaining = 0L;
if (isWritingToCache()) {
ContentMetadataMutations contentMetadataMutations = new ContentMetadataMutations();
ContentMetadataMutations.setContentLength(contentMetadataMutations, this.readPosition);
this.cache.applyContentMetadataMutations(str, contentMetadataMutations);
}
}
private static Uri getRedirectedUriOrDefault(Cache cache, String str, Uri uri) {
Uri redirectedUri = ContentMetadata.getRedirectedUri(cache.getContentMetadata(str));
return redirectedUri != null ? redirectedUri : uri;
}
private boolean isReadingFromUpstream() {
return !isReadingFromCache();
}
/* JADX WARN: Multi-variable type inference failed */
private void closeCurrentSource() throws IOException {
DataSource dataSource = this.currentDataSource;
if (dataSource == null) {
return;
}
try {
dataSource.close();
} finally {
this.currentDataSpec = null;
this.currentDataSource = null;
CacheSpan cacheSpan = this.currentHoleSpan;
if (cacheSpan != null) {
this.cache.releaseHoleSpan(cacheSpan);
this.currentHoleSpan = null;
}
}
}
private void handleBeforeThrow(Throwable th) {
if (isReadingFromCache() || (th instanceof Cache.CacheException)) {
this.seenCacheError = true;
}
}
private int shouldIgnoreCacheForRequest(DataSpec dataSpec) {
if (this.ignoreCacheOnError && this.seenCacheError) {
return 0;
}
return (this.ignoreCacheForUnsetLengthRequests && dataSpec.length == -1) ? 1 : -1;
}
private void notifyCacheIgnored(int i) {
EventListener eventListener = this.eventListener;
if (eventListener != null) {
eventListener.onCacheIgnored(i);
}
}
private void notifyBytesRead() {
EventListener eventListener = this.eventListener;
if (eventListener == null || this.totalCachedBytesRead <= 0) {
return;
}
eventListener.onCachedBytesRead(this.cache.getCacheSpace(), this.totalCachedBytesRead);
this.totalCachedBytesRead = 0L;
}
}