mirror of
https://github.com/Pinball3D/Rabbit-R1.git
synced 2024-12-27 09:32:27 -06:00
513 lines
20 KiB
Java
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;
|
|
}
|
|
}
|