diff options
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DataSpec.java')
-rw-r--r-- | mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DataSpec.java | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DataSpec.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DataSpec.java new file mode 100644 index 0000000000..6a419c6632 --- /dev/null +++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/upstream/DataSpec.java @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mozilla.thirdparty.com.google.android.exoplayer2.upstream; + +import android.net.Uri; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import org.mozilla.thirdparty.com.google.android.exoplayer2.C; +import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Defines a region of data. + */ +public final class DataSpec { + + /** + * The flags that apply to any request for data. Possible flag values are {@link + * #FLAG_ALLOW_GZIP}, {@link #FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN} and {@link + * #FLAG_ALLOW_CACHE_FRAGMENTATION}. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef( + flag = true, + value = {FLAG_ALLOW_GZIP, FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN, FLAG_ALLOW_CACHE_FRAGMENTATION}) + public @interface Flags {} + /** + * Allows an underlying network stack to request that the server use gzip compression. + * + * <p>Should not typically be set if the data being requested is already compressed (e.g. most + * audio and video requests). May be set when requesting other data. + * + * <p>When a {@link DataSource} is used to request data with this flag set, and if the {@link + * DataSource} does make a network request, then the value returned from {@link + * DataSource#open(DataSpec)} will typically be {@link C#LENGTH_UNSET}. The data read from {@link + * DataSource#read(byte[], int, int)} will be the decompressed data. + */ + public static final int FLAG_ALLOW_GZIP = 1; + /** Prevents caching if the length cannot be resolved when the {@link DataSource} is opened. */ + public static final int FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN = 1 << 1; // 2 + /** + * Allows fragmentation of this request into multiple cache files, meaning a cache eviction policy + * will be able to evict individual fragments of the data. Depending on the cache implementation, + * setting this flag may also enable more concurrent access to the data (e.g. reading one fragment + * whilst writing another). + */ + public static final int FLAG_ALLOW_CACHE_FRAGMENTATION = 1 << 2; // 4 + + /** + * The set of HTTP methods that are supported by ExoPlayer {@link HttpDataSource}s. One of {@link + * #HTTP_METHOD_GET}, {@link #HTTP_METHOD_POST} or {@link #HTTP_METHOD_HEAD}. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({HTTP_METHOD_GET, HTTP_METHOD_POST, HTTP_METHOD_HEAD}) + public @interface HttpMethod {} + + public static final int HTTP_METHOD_GET = 1; + public static final int HTTP_METHOD_POST = 2; + public static final int HTTP_METHOD_HEAD = 3; + + /** + * The source from which data should be read. + */ + public final Uri uri; + + /** + * The HTTP method, which will be used by {@link HttpDataSource} when requesting this DataSpec. + * This value will be ignored by non-http {@link DataSource}s. + */ + public final @HttpMethod int httpMethod; + + /** + * The HTTP request body, null otherwise. If the body is non-null, then httpBody.length will be + * non-zero. + */ + @Nullable public final byte[] httpBody; + + /** Immutable map containing the headers to use in HTTP requests. */ + public final Map<String, String> httpRequestHeaders; + + /** The absolute position of the data in the full stream. */ + public final long absoluteStreamPosition; + /** + * The position of the data when read from {@link #uri}. + * <p> + * Always equal to {@link #absoluteStreamPosition} unless the {@link #uri} defines the location + * of a subset of the underlying data. + */ + public final long position; + /** + * The length of the data, or {@link C#LENGTH_UNSET}. + */ + public final long length; + /** + * A key that uniquely identifies the original stream. Used for cache indexing. May be null if the + * data spec is not intended to be used in conjunction with a cache. + */ + @Nullable public final String key; + /** Request {@link Flags flags}. */ + public final @Flags int flags; + + /** + * Construct a data spec for the given uri and with {@link #key} set to null. + * + * @param uri {@link #uri}. + */ + public DataSpec(Uri uri) { + this(uri, 0); + } + + /** + * Construct a data spec for the given uri and with {@link #key} set to null. + * + * @param uri {@link #uri}. + * @param flags {@link #flags}. + */ + public DataSpec(Uri uri, @Flags int flags) { + this(uri, 0, C.LENGTH_UNSET, null, flags); + } + + /** + * Construct a data spec where {@link #position} equals {@link #absoluteStreamPosition}. + * + * @param uri {@link #uri}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}, equal to {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + */ + public DataSpec(Uri uri, long absoluteStreamPosition, long length, @Nullable String key) { + this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, 0); + } + + /** + * Construct a data spec where {@link #position} equals {@link #absoluteStreamPosition}. + * + * @param uri {@link #uri}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}, equal to {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + * @param flags {@link #flags}. + */ + public DataSpec( + Uri uri, long absoluteStreamPosition, long length, @Nullable String key, @Flags int flags) { + this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, flags); + } + + /** + * Construct a data spec where {@link #position} equals {@link #absoluteStreamPosition} and has + * request headers. + * + * @param uri {@link #uri}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}, equal to {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + * @param flags {@link #flags}. + * @param httpRequestHeaders {@link #httpRequestHeaders} + */ + public DataSpec( + Uri uri, + long absoluteStreamPosition, + long length, + @Nullable String key, + @Flags int flags, + Map<String, String> httpRequestHeaders) { + this( + uri, + inferHttpMethod(null), + null, + absoluteStreamPosition, + absoluteStreamPosition, + length, + key, + flags, + httpRequestHeaders); + } + + /** + * Construct a data spec where {@link #position} may differ from {@link #absoluteStreamPosition}. + * + * @param uri {@link #uri}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}. + * @param position {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + * @param flags {@link #flags}. + */ + public DataSpec( + Uri uri, + long absoluteStreamPosition, + long position, + long length, + @Nullable String key, + @Flags int flags) { + this(uri, null, absoluteStreamPosition, position, length, key, flags); + } + + /** + * Construct a data spec by inferring the {@link #httpMethod} based on the {@code postBody} + * parameter. If postBody is non-null, then httpMethod is set to {@link #HTTP_METHOD_POST}. If + * postBody is null, then httpMethod is set to {@link #HTTP_METHOD_GET}. + * + * @param uri {@link #uri}. + * @param postBody {@link #httpBody} The body of the HTTP request, which is also used to infer the + * {@link #httpMethod}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}. + * @param position {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + * @param flags {@link #flags}. + */ + public DataSpec( + Uri uri, + @Nullable byte[] postBody, + long absoluteStreamPosition, + long position, + long length, + @Nullable String key, + @Flags int flags) { + this( + uri, + /* httpMethod= */ inferHttpMethod(postBody), + /* httpBody= */ postBody, + absoluteStreamPosition, + position, + length, + key, + flags); + } + + /** + * Construct a data spec where {@link #position} may differ from {@link #absoluteStreamPosition}. + * + * @param uri {@link #uri}. + * @param httpMethod {@link #httpMethod}. + * @param httpBody {@link #httpBody}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}. + * @param position {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + * @param flags {@link #flags}. + */ + public DataSpec( + Uri uri, + @HttpMethod int httpMethod, + @Nullable byte[] httpBody, + long absoluteStreamPosition, + long position, + long length, + @Nullable String key, + @Flags int flags) { + this( + uri, + httpMethod, + httpBody, + absoluteStreamPosition, + position, + length, + key, + flags, + /* httpRequestHeaders= */ Collections.emptyMap()); + } + + /** + * Construct a data spec with request parameters to be used as HTTP headers inside HTTP requests. + * + * @param uri {@link #uri}. + * @param httpMethod {@link #httpMethod}. + * @param httpBody {@link #httpBody}. + * @param absoluteStreamPosition {@link #absoluteStreamPosition}. + * @param position {@link #position}. + * @param length {@link #length}. + * @param key {@link #key}. + * @param flags {@link #flags}. + * @param httpRequestHeaders {@link #httpRequestHeaders}. + */ + public DataSpec( + Uri uri, + @HttpMethod int httpMethod, + @Nullable byte[] httpBody, + long absoluteStreamPosition, + long position, + long length, + @Nullable String key, + @Flags int flags, + Map<String, String> httpRequestHeaders) { + Assertions.checkArgument(absoluteStreamPosition >= 0); + Assertions.checkArgument(position >= 0); + Assertions.checkArgument(length > 0 || length == C.LENGTH_UNSET); + this.uri = uri; + this.httpMethod = httpMethod; + this.httpBody = (httpBody != null && httpBody.length != 0) ? httpBody : null; + this.absoluteStreamPosition = absoluteStreamPosition; + this.position = position; + this.length = length; + this.key = key; + this.flags = flags; + this.httpRequestHeaders = Collections.unmodifiableMap(new HashMap<>(httpRequestHeaders)); + } + + /** + * Returns whether the given flag is set. + * + * @param flag Flag to be checked if it is set. + */ + public boolean isFlagSet(@Flags int flag) { + return (this.flags & flag) == flag; + } + + @Override + public String toString() { + return "DataSpec[" + + getHttpMethodString() + + " " + + uri + + ", " + + Arrays.toString(httpBody) + + ", " + + absoluteStreamPosition + + ", " + + position + + ", " + + length + + ", " + + key + + ", " + + flags + + "]"; + } + + /** + * Returns an uppercase HTTP method name (e.g., "GET", "POST", "HEAD") corresponding to the {@link + * #httpMethod}. + */ + public final String getHttpMethodString() { + return getStringForHttpMethod(httpMethod); + } + + /** + * Returns an uppercase HTTP method name (e.g., "GET", "POST", "HEAD") corresponding to the {@code + * httpMethod}. + */ + public static String getStringForHttpMethod(@HttpMethod int httpMethod) { + switch (httpMethod) { + case HTTP_METHOD_GET: + return "GET"; + case HTTP_METHOD_POST: + return "POST"; + case HTTP_METHOD_HEAD: + return "HEAD"; + default: + throw new AssertionError(httpMethod); + } + } + + /** + * Returns a data spec that represents a subrange of the data defined by this DataSpec. The + * subrange includes data from the offset up to the end of this DataSpec. + * + * @param offset The offset of the subrange. + * @return A data spec that represents a subrange of the data defined by this DataSpec. + */ + public DataSpec subrange(long offset) { + return subrange(offset, length == C.LENGTH_UNSET ? C.LENGTH_UNSET : length - offset); + } + + /** + * Returns a data spec that represents a subrange of the data defined by this DataSpec. + * + * @param offset The offset of the subrange. + * @param length The length of the subrange. + * @return A data spec that represents a subrange of the data defined by this DataSpec. + */ + public DataSpec subrange(long offset, long length) { + if (offset == 0 && this.length == length) { + return this; + } else { + return new DataSpec( + uri, + httpMethod, + httpBody, + absoluteStreamPosition + offset, + position + offset, + length, + key, + flags, + httpRequestHeaders); + } + } + + /** + * Returns a copy of this data spec with the specified Uri. + * + * @param uri The new source {@link Uri}. + * @return The copied data spec with the specified Uri. + */ + public DataSpec withUri(Uri uri) { + return new DataSpec( + uri, + httpMethod, + httpBody, + absoluteStreamPosition, + position, + length, + key, + flags, + httpRequestHeaders); + } + + /** + * Returns a copy of this data spec with the specified request headers. + * + * @param requestHeaders The HTTP request headers. + * @return The copied data spec with the specified request headers. + */ + public DataSpec withRequestHeaders(Map<String, String> requestHeaders) { + return new DataSpec( + uri, + httpMethod, + httpBody, + absoluteStreamPosition, + position, + length, + key, + flags, + requestHeaders); + } + + /** + * Returns a copy this data spec with additional request headers. + * + * <p>Note: Values in {@code requestHeaders} will overwrite values with the same header key that + * were previously set in this instance's {@code #httpRequestHeaders}. + * + * @param requestHeaders The additional HTTP request headers. + * @return The copied data with the additional HTTP request headers. + */ + public DataSpec withAdditionalHeaders(Map<String, String> requestHeaders) { + Map<String, String> totalHeaders = new HashMap<>(this.httpRequestHeaders); + totalHeaders.putAll(requestHeaders); + + return new DataSpec( + uri, + httpMethod, + httpBody, + absoluteStreamPosition, + position, + length, + key, + flags, + totalHeaders); + } + + @HttpMethod + private static int inferHttpMethod(@Nullable byte[] postBody) { + return postBody != null ? HTTP_METHOD_POST : HTTP_METHOD_GET; + } +} |