Add MediaSource and DataSource to inject playback nonce into URLs.

A new playback nonce is created for each playback of the same item. Thus we
need to inject the nonce dynamically into the data source factory.

This CL adds the DataSource which does the actual insertion into the request
URLs and a MediaSource which listens to new media periods, to request the
nonce and to configure the data source factory for this media period to use
this nonce.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=197134217
This commit is contained in:
tonihei 2018-05-18 05:48:48 -07:00 committed by Andrew Lewis
parent f459611e04
commit 2b9c31a14f
7 changed files with 89 additions and 8 deletions

View File

@ -16,6 +16,7 @@
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 java.io.IOException; import java.io.IOException;
@ -79,7 +80,7 @@ public interface DataSource {
* *
* @return The {@link Uri} from which data is being read, or null if the source is not open. * @return The {@link Uri} from which data is being read, or null if the source is not open.
*/ */
Uri getUri(); @Nullable Uri getUri();
/** /**
* Closes the source. * Closes the source.

View File

@ -61,7 +61,7 @@ public final class DataSpec {
/** /**
* Body for a POST request, null otherwise. * Body for a POST request, null otherwise.
*/ */
public final byte[] postBody; public final @Nullable byte[] postBody;
/** /**
* The absolute position of the data in the full stream. * The absolute position of the data in the full stream.
*/ */
@ -81,12 +81,12 @@ public final class DataSpec {
* A key that uniquely identifies the original stream. Used for cache indexing. May be null if the * A key that uniquely identifies the original stream. Used for cache indexing. May be null if the
* {@link DataSpec} is not intended to be used in conjunction with a cache. * {@link DataSpec} is not intended to be used in conjunction with a cache.
*/ */
@Nullable public final String key; public final @Nullable String key;
/** /**
* Request flags. Currently {@link #FLAG_ALLOW_GZIP} and * Request flags. Currently {@link #FLAG_ALLOW_GZIP} and
* {@link #FLAG_ALLOW_CACHING_UNKNOWN_LENGTH} are the only supported flags. * {@link #FLAG_ALLOW_CACHING_UNKNOWN_LENGTH} are the only supported flags.
*/ */
@Flags public final int flags; public final @Flags int flags;
/** /**
* Construct a {@link DataSpec} for the given uri and with {@link #key} set to null. * Construct a {@link DataSpec} for the given uri and with {@link #key} set to null.
@ -128,7 +128,8 @@ public final class DataSpec {
* @param key {@link #key}. * @param key {@link #key}.
* @param flags {@link #flags}. * @param flags {@link #flags}.
*/ */
public DataSpec(Uri uri, long absoluteStreamPosition, long length, String key, @Flags int flags) { public DataSpec(
Uri uri, long absoluteStreamPosition, long length, @Nullable String key, @Flags int flags) {
this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, flags); this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, flags);
} }
@ -143,7 +144,12 @@ public final class DataSpec {
* @param key {@link #key}. * @param key {@link #key}.
* @param flags {@link #flags}. * @param flags {@link #flags}.
*/ */
public DataSpec(Uri uri, long absoluteStreamPosition, long position, long length, String key, public DataSpec(
Uri uri,
long absoluteStreamPosition,
long position,
long length,
@Nullable String key,
@Flags int flags) { @Flags int flags) {
this(uri, null, absoluteStreamPosition, position, length, key, flags); this(uri, null, absoluteStreamPosition, position, length, key, flags);
} }
@ -162,7 +168,7 @@ public final class DataSpec {
*/ */
public DataSpec( public DataSpec(
Uri uri, Uri uri,
byte[] postBody, @Nullable byte[] postBody,
long absoluteStreamPosition, long absoluteStreamPosition,
long position, long position,
long length, long length,
@ -222,4 +228,13 @@ public final class DataSpec {
} }
} }
/**
* Returns a copy of this {@link DataSpec} with the specified Uri.
*
* @param uri The new source {@link Uri}.
* @return The copied {@link DataSpec} with the specified Uri.
*/
public DataSpec withUri(Uri uri) {
return new DataSpec(uri, postBody, absoluteStreamPosition, position, length, key, flags);
}
} }

View File

@ -16,6 +16,7 @@
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.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;
@ -63,7 +64,7 @@ public final class PriorityDataSource implements DataSource {
} }
@Override @Override
public Uri getUri() { public @Nullable Uri getUri() {
return upstream.getUri(); return upstream.getUri();
} }

View File

@ -143,6 +143,26 @@ public final class UriUtil {
} }
} }
/**
* Removes query parameter from an Uri, if present.
*
* @param uri The uri.
* @param queryParameterName The name of the query parameter.
* @return The uri without the query parameter.
*/
public static Uri removeQueryParameter(Uri uri, String queryParameterName) {
Uri.Builder builder = uri.buildUpon();
builder.clearQuery();
for (String key : uri.getQueryParameterNames()) {
if (!key.equals(queryParameterName)) {
for (String value : uri.getQueryParameters(key)) {
builder.appendQueryParameter(key, value);
}
}
}
return builder.build();
}
/** /**
* Removes dot segments from the path of a URI. * Removes dot segments from the path of a URI.
* *

View File

@ -15,9 +15,11 @@
*/ */
package com.google.android.exoplayer2.util; package com.google.android.exoplayer2.util;
import static com.google.android.exoplayer2.util.UriUtil.removeQueryParameter;
import static com.google.android.exoplayer2.util.UriUtil.resolve; import static com.google.android.exoplayer2.util.UriUtil.resolve;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
@ -104,4 +106,36 @@ public final class UriUtilTest {
assertThat(resolve("a:b", "../c")).isEqualTo("a:c"); assertThat(resolve("a:b", "../c")).isEqualTo("a:c");
} }
@Test
public void removeOnlyQueryParameter() {
Uri uri = Uri.parse("http://uri?query=value");
assertThat(removeQueryParameter(uri, "query").toString()).isEqualTo("http://uri");
}
@Test
public void removeFirstQueryParameter() {
Uri uri = Uri.parse("http://uri?query=value&second=value2");
assertThat(removeQueryParameter(uri, "query").toString()).isEqualTo("http://uri?second=value2");
}
@Test
public void removeMiddleQueryParameter() {
Uri uri = Uri.parse("http://uri?first=value1&query=value&last=value2");
assertThat(removeQueryParameter(uri, "query").toString())
.isEqualTo("http://uri?first=value1&last=value2");
}
@Test
public void removeLastQueryParameter() {
Uri uri = Uri.parse("http://uri?first=value1&query=value");
assertThat(removeQueryParameter(uri, "query").toString()).isEqualTo("http://uri?first=value1");
}
@Test
public void removeNonExistentQueryParameter() {
Uri uri = Uri.parse("http://uri");
assertThat(removeQueryParameter(uri, "foo").toString()).isEqualTo("http://uri");
uri = Uri.parse("http://uri?query=value");
assertThat(removeQueryParameter(uri, "foo").toString()).isEqualTo("http://uri?query=value");
}
} }

View File

@ -217,6 +217,11 @@ public class FakeDataSource implements DataSource {
return dataSpecs; return dataSpecs;
} }
/** Returns whether the data source is currently opened. */
public final boolean isOpened() {
return opened;
}
protected void onDataRead(int bytesRead) throws IOException { protected void onDataRead(int bytesRead) throws IOException {
// Do nothing. Can be overridden. // Do nothing. Can be overridden.
} }

View File

@ -159,6 +159,11 @@ public class FakeMediaSource extends BaseMediaSource {
} }
} }
/** Asserts that the source has been prepared. */
public void assertPrepared() {
assertThat(preparedSource).isTrue();
}
/** /**
* Assert that the source and all periods have been released. * Assert that the source and all periods have been released.
*/ */