Forward addTransferListener for all wrapping data sources.

This allows to register a listener on an outer wrapping data source which
receives data transfer events from the wrapped source.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=203358981
This commit is contained in:
tonihei 2018-07-05 04:17:22 -07:00 committed by Oliver Woodman
parent 5047a5a4da
commit 264bed06f2
8 changed files with 132 additions and 38 deletions

View File

@ -52,8 +52,7 @@ public interface DataSource {
} }
/** /**
* Adds a {@link TransferListener} to listen to data transfers. Must be called before the first * Adds a {@link TransferListener} to listen to data transfers. This method is not thread-safe.
* call to {@link #open(DataSpec)}.
* *
* @param transferListener A {@link TransferListener}. * @param transferListener A {@link TransferListener}.
*/ */

View File

@ -17,10 +17,12 @@ package com.google.android.exoplayer2.upstream;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -55,19 +57,18 @@ public final class DefaultDataSource implements DataSource {
private static final String SCHEME_RAW = RawResourceDataSource.RAW_RESOURCE_SCHEME; private static final String SCHEME_RAW = RawResourceDataSource.RAW_RESOURCE_SCHEME;
private final Context context; private final Context context;
private final TransferListener<? super DataSource> listener; private final List<TransferListener<? super DataSource>> transferListeners;
private final DataSource baseDataSource; private final DataSource baseDataSource;
// Lazily initialized. // Lazily initialized.
private DataSource fileDataSource; private @Nullable DataSource fileDataSource;
private DataSource assetDataSource; private @Nullable DataSource assetDataSource;
private DataSource contentDataSource; private @Nullable DataSource contentDataSource;
private DataSource rtmpDataSource; private @Nullable DataSource rtmpDataSource;
private DataSource dataSchemeDataSource; private @Nullable DataSource dataSchemeDataSource;
private DataSource rawResourceDataSource; private @Nullable DataSource rawResourceDataSource;
private DataSource dataSource; private @Nullable DataSource dataSource;
/** /**
* Constructs a new instance, optionally configured to follow cross-protocol redirects. * Constructs a new instance, optionally configured to follow cross-protocol redirects.
@ -78,8 +79,11 @@ public final class DefaultDataSource implements DataSource {
* @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
* to HTTPS and vice versa) are enabled when fetching remote data. * to HTTPS and vice versa) are enabled when fetching remote data.
*/ */
public DefaultDataSource(Context context, TransferListener<? super DataSource> listener, public DefaultDataSource(
String userAgent, boolean allowCrossProtocolRedirects) { Context context,
@Nullable TransferListener<? super DataSource> listener,
String userAgent,
boolean allowCrossProtocolRedirects) {
this(context, listener, userAgent, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, this(context, listener, userAgent, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, allowCrossProtocolRedirects); DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, allowCrossProtocolRedirects);
} }
@ -92,13 +96,17 @@ public final class DefaultDataSource implements DataSource {
* @param userAgent The User-Agent string that should be used when requesting remote data. * @param userAgent The User-Agent string that should be used when requesting remote data.
* @param connectTimeoutMillis The connection timeout that should be used when requesting remote * @param connectTimeoutMillis The connection timeout that should be used when requesting remote
* data, in milliseconds. A timeout of zero is interpreted as an infinite timeout. * data, in milliseconds. A timeout of zero is interpreted as an infinite timeout.
* @param readTimeoutMillis The read timeout that should be used when requesting remote data, * @param readTimeoutMillis The read timeout that should be used when requesting remote data, in
* in milliseconds. A timeout of zero is interpreted as an infinite timeout. * milliseconds. A timeout of zero is interpreted as an infinite timeout.
* @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP * @param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
* to HTTPS and vice versa) are enabled when fetching remote data. * to HTTPS and vice versa) are enabled when fetching remote data.
*/ */
public DefaultDataSource(Context context, TransferListener<? super DataSource> listener, public DefaultDataSource(
String userAgent, int connectTimeoutMillis, int readTimeoutMillis, Context context,
@Nullable TransferListener<? super DataSource> listener,
String userAgent,
int connectTimeoutMillis,
int readTimeoutMillis,
boolean allowCrossProtocolRedirects) { boolean allowCrossProtocolRedirects) {
this(context, listener, this(context, listener,
new DefaultHttpDataSource(userAgent, null, listener, connectTimeoutMillis, new DefaultHttpDataSource(userAgent, null, listener, connectTimeoutMillis,
@ -114,11 +122,28 @@ public final class DefaultDataSource implements DataSource {
* @param baseDataSource A {@link DataSource} to use for URI schemes other than file, asset and * @param baseDataSource A {@link DataSource} to use for URI schemes other than file, asset and
* content. This {@link DataSource} should normally support at least http(s). * content. This {@link DataSource} should normally support at least http(s).
*/ */
public DefaultDataSource(Context context, TransferListener<? super DataSource> listener, public DefaultDataSource(
Context context,
@Nullable TransferListener<? super DataSource> listener,
DataSource baseDataSource) { DataSource baseDataSource) {
this.context = context.getApplicationContext(); this.context = context.getApplicationContext();
this.listener = listener;
this.baseDataSource = Assertions.checkNotNull(baseDataSource); this.baseDataSource = Assertions.checkNotNull(baseDataSource);
transferListeners = new ArrayList<>();
if (listener != null) {
transferListeners.add(listener);
}
}
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
baseDataSource.addTransferListener(transferListener);
transferListeners.add(transferListener);
maybeAddListenerToDataSource(fileDataSource, transferListener);
maybeAddListenerToDataSource(assetDataSource, transferListener);
maybeAddListenerToDataSource(contentDataSource, transferListener);
maybeAddListenerToDataSource(rtmpDataSource, transferListener);
maybeAddListenerToDataSource(dataSchemeDataSource, transferListener);
maybeAddListenerToDataSource(rawResourceDataSource, transferListener);
} }
@Override @Override
@ -151,11 +176,11 @@ public final class DefaultDataSource implements DataSource {
@Override @Override
public int read(byte[] buffer, int offset, int readLength) throws IOException { public int read(byte[] buffer, int offset, int readLength) throws IOException {
return dataSource.read(buffer, offset, readLength); return Assertions.checkNotNull(dataSource).read(buffer, offset, readLength);
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return dataSource == null ? null : dataSource.getUri(); return dataSource == null ? null : dataSource.getUri();
} }
@ -179,21 +204,24 @@ public final class DefaultDataSource implements DataSource {
private DataSource getFileDataSource() { private DataSource getFileDataSource() {
if (fileDataSource == null) { if (fileDataSource == null) {
fileDataSource = new FileDataSource(listener); fileDataSource = new FileDataSource();
addListenersToDataSource(fileDataSource);
} }
return fileDataSource; return fileDataSource;
} }
private DataSource getAssetDataSource() { private DataSource getAssetDataSource() {
if (assetDataSource == null) { if (assetDataSource == null) {
assetDataSource = new AssetDataSource(context, listener); assetDataSource = new AssetDataSource(context);
addListenersToDataSource(assetDataSource);
} }
return assetDataSource; return assetDataSource;
} }
private DataSource getContentDataSource() { private DataSource getContentDataSource() {
if (contentDataSource == null) { if (contentDataSource == null) {
contentDataSource = new ContentDataSource(context, listener); contentDataSource = new ContentDataSource(context);
addListenersToDataSource(contentDataSource);
} }
return contentDataSource; return contentDataSource;
} }
@ -205,6 +233,7 @@ public final class DefaultDataSource implements DataSource {
Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.rtmp.RtmpDataSource"); Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.rtmp.RtmpDataSource");
rtmpDataSource = (DataSource) clazz.getConstructor().newInstance(); rtmpDataSource = (DataSource) clazz.getConstructor().newInstance();
// LINT.ThenChange(../../../../../../../../proguard-rules.txt) // LINT.ThenChange(../../../../../../../../proguard-rules.txt)
addListenersToDataSource(rtmpDataSource);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// Expected if the app was built without the RTMP extension. // Expected if the app was built without the RTMP extension.
Log.w(TAG, "Attempting to play RTMP stream without depending on the RTMP extension"); Log.w(TAG, "Attempting to play RTMP stream without depending on the RTMP extension");
@ -222,14 +251,29 @@ public final class DefaultDataSource implements DataSource {
private DataSource getDataSchemeDataSource() { private DataSource getDataSchemeDataSource() {
if (dataSchemeDataSource == null) { if (dataSchemeDataSource == null) {
dataSchemeDataSource = new DataSchemeDataSource(); dataSchemeDataSource = new DataSchemeDataSource();
addListenersToDataSource(dataSchemeDataSource);
} }
return dataSchemeDataSource; return dataSchemeDataSource;
} }
private DataSource getRawResourceDataSource() { private DataSource getRawResourceDataSource() {
if (rawResourceDataSource == null) { if (rawResourceDataSource == null) {
rawResourceDataSource = new RawResourceDataSource(context, listener); rawResourceDataSource = new RawResourceDataSource(context);
addListenersToDataSource(rawResourceDataSource);
} }
return rawResourceDataSource; return rawResourceDataSource;
} }
private void addListenersToDataSource(DataSource dataSource) {
for (int i = 0; i < transferListeners.size(); i++) {
dataSource.addTransferListener(transferListeners.get(i));
}
}
private void maybeAddListenerToDataSource(
@Nullable DataSource dataSource, TransferListener<? super DataSource> listener) {
if (dataSource != null) {
dataSource.addTransferListener(listener);
}
}
} }

View File

@ -20,6 +20,8 @@ import android.support.annotation.Nullable;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Map;
/** /**
* A {@link DataSource} that can be used as part of a task registered with a * A {@link DataSource} that can be used as part of a task registered with a
@ -51,6 +53,11 @@ public final class PriorityDataSource implements DataSource {
this.priority = priority; this.priority = priority;
} }
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
upstream.addTransferListener(transferListener);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
priorityTaskManager.proceedOrThrow(priority); priorityTaskManager.proceedOrThrow(priority);
@ -68,6 +75,11 @@ public final class PriorityDataSource implements DataSource {
return upstream.getUri(); return upstream.getUri();
} }
@Override
public Map<String, List<String>> getResponseHeaders() {
return upstream.getResponseHeaders();
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
upstream.close(); upstream.close();

View File

@ -70,6 +70,11 @@ public final class StatsDataSource implements DataSource {
return lastResponseHeaders; return lastResponseHeaders;
} }
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
dataSource.addTransferListener(transferListener);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
// Reassign defaults in case dataSource.open throws an exception. // Reassign defaults in case dataSource.open throws an exception.

View File

@ -16,9 +16,12 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Map;
/** /**
* Tees data into a {@link DataSink} as the data is read. * Tees data into a {@link DataSink} as the data is read.
@ -40,6 +43,11 @@ public final class TeeDataSource implements DataSource {
this.dataSink = Assertions.checkNotNull(dataSink); this.dataSink = Assertions.checkNotNull(dataSink);
} }
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
upstream.addTransferListener(transferListener);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
bytesRemaining = upstream.open(dataSpec); bytesRemaining = upstream.open(dataSpec);
@ -79,10 +87,15 @@ public final class TeeDataSource implements DataSource {
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return upstream.getUri(); return upstream.getUri();
} }
@Override
public Map<String, List<String>> getResponseHeaders() {
return upstream.getResponseHeaders();
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
try { try {

View File

@ -25,6 +25,7 @@ import com.google.android.exoplayer2.upstream.DataSourceException;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.FileDataSource; import com.google.android.exoplayer2.upstream.FileDataSource;
import com.google.android.exoplayer2.upstream.TeeDataSource; import com.google.android.exoplayer2.upstream.TeeDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.upstream.cache.Cache.CacheException; import com.google.android.exoplayer2.upstream.cache.Cache.CacheException;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
@ -119,7 +120,7 @@ public final class CacheDataSource implements DataSource {
private final Cache cache; private final Cache cache;
private final DataSource cacheReadDataSource; private final DataSource cacheReadDataSource;
private final DataSource cacheWriteDataSource; private final @Nullable DataSource cacheWriteDataSource;
private final DataSource upstreamDataSource; private final DataSource upstreamDataSource;
private final CacheKeyFactory cacheKeyFactory; private final CacheKeyFactory cacheKeyFactory;
@Nullable private final EventListener eventListener; @Nullable private final EventListener eventListener;
@ -128,15 +129,15 @@ public final class CacheDataSource implements DataSource {
private final boolean ignoreCacheOnError; private final boolean ignoreCacheOnError;
private final boolean ignoreCacheForUnsetLengthRequests; private final boolean ignoreCacheForUnsetLengthRequests;
private DataSource currentDataSource; private @Nullable DataSource currentDataSource;
private boolean currentDataSpecLengthUnset; private boolean currentDataSpecLengthUnset;
private Uri uri; private @Nullable Uri uri;
private Uri actualUri; private @Nullable Uri actualUri;
private int flags; private int flags;
private String key; private @Nullable String key;
private long readPosition; private long readPosition;
private long bytesRemaining; private long bytesRemaining;
private CacheSpan currentHoleSpan; private @Nullable CacheSpan currentHoleSpan;
private boolean seenCacheError; private boolean seenCacheError;
private boolean currentRequestIgnoresCache; private boolean currentRequestIgnoresCache;
private long totalCachedBytesRead; private long totalCachedBytesRead;
@ -256,6 +257,12 @@ public final class CacheDataSource implements DataSource {
this.eventListener = eventListener; this.eventListener = eventListener;
} }
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
cacheReadDataSource.addTransferListener(transferListener);
upstreamDataSource.addTransferListener(transferListener);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
try { try {
@ -330,7 +337,7 @@ public final class CacheDataSource implements DataSource {
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return actualUri; return actualUri;
} }

View File

@ -16,9 +16,11 @@
package com.google.android.exoplayer2.upstream.crypto; package com.google.android.exoplayer2.upstream.crypto;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSource; 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.TransferListener;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -32,13 +34,18 @@ public final class AesCipherDataSource implements DataSource {
private final DataSource upstream; private final DataSource upstream;
private final byte[] secretKey; private final byte[] secretKey;
private AesFlushingCipher cipher; private @Nullable AesFlushingCipher cipher;
public AesCipherDataSource(byte[] secretKey, DataSource upstream) { public AesCipherDataSource(byte[] secretKey, DataSource upstream) {
this.upstream = upstream; this.upstream = upstream;
this.secretKey = secretKey; this.secretKey = secretKey;
} }
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
upstream.addTransferListener(transferListener);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
long dataLength = upstream.open(dataSpec); long dataLength = upstream.open(dataSpec);
@ -62,7 +69,7 @@ public final class AesCipherDataSource implements DataSource {
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return upstream.getUri(); return upstream.getUri();
} }

View File

@ -16,10 +16,12 @@
package com.google.android.exoplayer2.source.hls; package com.google.android.exoplayer2.source.hls;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceInputStream; import com.google.android.exoplayer2.upstream.DataSourceInputStream;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
@ -49,7 +51,7 @@ import javax.crypto.spec.SecretKeySpec;
private final byte[] encryptionKey; private final byte[] encryptionKey;
private final byte[] encryptionIv; private final byte[] encryptionIv;
private CipherInputStream cipherInputStream; private @Nullable CipherInputStream cipherInputStream;
/** /**
* @param upstream The upstream {@link DataSource}. * @param upstream The upstream {@link DataSource}.
@ -62,6 +64,11 @@ import javax.crypto.spec.SecretKeySpec;
this.encryptionIv = encryptionIv; this.encryptionIv = encryptionIv;
} }
@Override
public void addTransferListener(TransferListener<? super DataSource> transferListener) {
upstream.addTransferListener(transferListener);
}
@Override @Override
public long open(DataSpec dataSpec) throws IOException { public long open(DataSpec dataSpec) throws IOException {
Cipher cipher; Cipher cipher;
@ -89,7 +96,7 @@ import javax.crypto.spec.SecretKeySpec;
@Override @Override
public int read(byte[] buffer, int offset, int readLength) throws IOException { public int read(byte[] buffer, int offset, int readLength) throws IOException {
Assertions.checkState(cipherInputStream != null); Assertions.checkNotNull(cipherInputStream);
int bytesRead = cipherInputStream.read(buffer, offset, readLength); int bytesRead = cipherInputStream.read(buffer, offset, readLength);
if (bytesRead < 0) { if (bytesRead < 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
@ -98,7 +105,7 @@ import javax.crypto.spec.SecretKeySpec;
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return upstream.getUri(); return upstream.getUri();
} }