diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
index c918603931..a3e89cd753 100644
--- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
+++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
@@ -98,7 +98,7 @@ public class PlayerActivity extends AppCompatActivity
// Activity lifecycle.
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dataSourceFactory = DemoUtil.getDataSourceFactory(/* context= */ this);
@@ -114,7 +114,9 @@ public class PlayerActivity extends AppCompatActivity
playerView.requestFocus();
if (savedInstanceState != null) {
- trackSelectorParameters = savedInstanceState.getParcelable(KEY_TRACK_SELECTOR_PARAMETERS);
+ trackSelectorParameters =
+ DefaultTrackSelector.Parameters.CREATOR.fromBundle(
+ savedInstanceState.getBundle(KEY_TRACK_SELECTOR_PARAMETERS));
startAutoPlay = savedInstanceState.getBoolean(KEY_AUTO_PLAY);
startWindow = savedInstanceState.getInt(KEY_WINDOW);
startPosition = savedInstanceState.getLong(KEY_POSITION);
@@ -207,7 +209,7 @@ public class PlayerActivity extends AppCompatActivity
super.onSaveInstanceState(outState);
updateTrackSelectorParameters();
updateStartPosition();
- outState.putParcelable(KEY_TRACK_SELECTOR_PARAMETERS, trackSelectorParameters);
+ outState.putBundle(KEY_TRACK_SELECTOR_PARAMETERS, trackSelectorParameters.toBundle());
outState.putBoolean(KEY_AUTO_PLAY, startAutoPlay);
outState.putInt(KEY_WINDOW, startWindow);
outState.putLong(KEY_POSITION, startPosition);
diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Format.java b/library/common/src/main/java/com/google/android/exoplayer2/Format.java
index eba199299e..6fcc34b11f 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/Format.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/Format.java
@@ -15,19 +15,21 @@
*/
package com.google.android.exoplayer2;
-import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
-
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Bundle;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.drm.UnsupportedMediaCrypto;
import com.google.android.exoplayer2.metadata.Metadata;
+import com.google.android.exoplayer2.util.BundleableUtils;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import com.google.common.base.Joiner;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -112,7 +114,7 @@ import java.util.UUID;
*
{@link #accessibilityChannel}
*
*/
-public final class Format implements Parcelable {
+public final class Format implements Bundleable {
/**
* Builds {@link Format} instances.
@@ -610,6 +612,8 @@ public final class Format implements Parcelable {
*/
public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
+ private static final Format DEFAULT = new Builder().build();
+
/** An identifier for the format, or null if unknown or not applicable. */
@Nullable public final String id;
/** The human readable label, or null if unknown or not applicable. */
@@ -968,54 +972,6 @@ public final class Format implements Parcelable {
}
}
- // Some fields are deprecated but they're still assigned below.
- @SuppressWarnings({"ResourceType"})
- /* package */ Format(Parcel in) {
- id = in.readString();
- label = in.readString();
- language = in.readString();
- selectionFlags = in.readInt();
- roleFlags = in.readInt();
- averageBitrate = in.readInt();
- peakBitrate = in.readInt();
- bitrate = peakBitrate != NO_VALUE ? peakBitrate : averageBitrate;
- codecs = in.readString();
- metadata = in.readParcelable(Metadata.class.getClassLoader());
- // Container specific.
- containerMimeType = in.readString();
- // Sample specific.
- sampleMimeType = in.readString();
- maxInputSize = in.readInt();
- int initializationDataSize = in.readInt();
- initializationData = new ArrayList<>(initializationDataSize);
- for (int i = 0; i < initializationDataSize; i++) {
- initializationData.add(checkNotNull(in.createByteArray()));
- }
- drmInitData = in.readParcelable(DrmInitData.class.getClassLoader());
- subsampleOffsetUs = in.readLong();
- // Video specific.
- width = in.readInt();
- height = in.readInt();
- frameRate = in.readFloat();
- rotationDegrees = in.readInt();
- pixelWidthHeightRatio = in.readFloat();
- boolean hasProjectionData = Util.readBoolean(in);
- projectionData = hasProjectionData ? in.createByteArray() : null;
- stereoMode = in.readInt();
- colorInfo = in.readParcelable(ColorInfo.class.getClassLoader());
- // Audio specific.
- channelCount = in.readInt();
- sampleRate = in.readInt();
- pcmEncoding = in.readInt();
- encoderDelay = in.readInt();
- encoderPadding = in.readInt();
- // Text specific.
- accessibilityChannel = in.readInt();
- // Provided by source.
- // Encrypted content must always have a non-null exoMediaCryptoType.
- exoMediaCryptoType = drmInitData != null ? UnsupportedMediaCrypto.class : null;
- }
-
/** Returns a {@link Format.Builder} initialized with the values of this instance. */
public Builder buildUpon() {
return new Builder(this);
@@ -1371,69 +1327,208 @@ public final class Format implements Parcelable {
return builder.toString();
}
- // Parcelable implementation.
+ // Bundleable implementation.
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_ID,
+ FIELD_LABEL,
+ FIELD_LANGUAGE,
+ FIELD_SELECTION_FLAGS,
+ FIELD_ROLE_FLAGS,
+ FIELD_AVERAGE_BITRATE,
+ FIELD_PEAK_BITRATE,
+ FIELD_CODECS,
+ FIELD_METADATA,
+ FIELD_CONTAINER_MIME_TYPE,
+ FIELD_SAMPLE_MIME_TYPE,
+ FIELD_MAX_INPUT_SIZE,
+ FIELD_INITIALIZATION_DATA,
+ FIELD_DRM_INIT_DATA,
+ FIELD_SUBSAMPLE_OFFSET_US,
+ FIELD_WIDTH,
+ FIELD_HEIGHT,
+ FIELD_FRAME_RATE,
+ FIELD_ROTATION_DEGREES,
+ FIELD_PIXEL_WIDTH_HEIGHT_RATIO,
+ FIELD_PROJECTION_DATA,
+ FIELD_STEREO_MODE,
+ FIELD_COLOR_INFO,
+ FIELD_CHANNEL_COUNT,
+ FIELD_SAMPLE_RATE,
+ FIELD_PCM_ENCODING,
+ FIELD_ENCODER_DELAY,
+ FIELD_ENCODER_PADDING,
+ FIELD_ACCESSIBILITY_CHANNEL,
+ })
+ private @interface FieldNumber {}
- @Override
- public int describeContents() {
- return 0;
- }
+ private static final int FIELD_ID = 0;
+ private static final int FIELD_LABEL = 1;
+ private static final int FIELD_LANGUAGE = 2;
+ private static final int FIELD_SELECTION_FLAGS = 3;
+ private static final int FIELD_ROLE_FLAGS = 4;
+ private static final int FIELD_AVERAGE_BITRATE = 5;
+ private static final int FIELD_PEAK_BITRATE = 6;
+ private static final int FIELD_CODECS = 7;
+ private static final int FIELD_METADATA = 8;
+ private static final int FIELD_CONTAINER_MIME_TYPE = 9;
+ private static final int FIELD_SAMPLE_MIME_TYPE = 10;
+ private static final int FIELD_MAX_INPUT_SIZE = 11;
+ private static final int FIELD_INITIALIZATION_DATA = 12;
+ private static final int FIELD_DRM_INIT_DATA = 13;
+ private static final int FIELD_SUBSAMPLE_OFFSET_US = 14;
+ private static final int FIELD_WIDTH = 15;
+ private static final int FIELD_HEIGHT = 16;
+ private static final int FIELD_FRAME_RATE = 17;
+ private static final int FIELD_ROTATION_DEGREES = 18;
+ private static final int FIELD_PIXEL_WIDTH_HEIGHT_RATIO = 19;
+ private static final int FIELD_PROJECTION_DATA = 20;
+ private static final int FIELD_STEREO_MODE = 21;
+ private static final int FIELD_COLOR_INFO = 22;
+ private static final int FIELD_CHANNEL_COUNT = 23;
+ private static final int FIELD_SAMPLE_RATE = 24;
+ private static final int FIELD_PCM_ENCODING = 25;
+ private static final int FIELD_ENCODER_DELAY = 26;
+ private static final int FIELD_ENCODER_PADDING = 27;
+ private static final int FIELD_ACCESSIBILITY_CHANNEL = 28;
+ /**
+ * {@inheritDoc}
+ *
+ * Omits the {@link #exoMediaCryptoType} field. The {@link #exoMediaCryptoType} of an instance
+ * restored by {@link #CREATOR} will always be {@link UnsupportedMediaCrypto}.
+ */
@Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(id);
- dest.writeString(label);
- dest.writeString(language);
- dest.writeInt(selectionFlags);
- dest.writeInt(roleFlags);
- dest.writeInt(averageBitrate);
- dest.writeInt(peakBitrate);
- dest.writeString(codecs);
- dest.writeParcelable(metadata, 0);
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(keyForField(FIELD_ID), id);
+ bundle.putString(keyForField(FIELD_LABEL), label);
+ bundle.putString(keyForField(FIELD_LANGUAGE), language);
+ bundle.putInt(keyForField(FIELD_SELECTION_FLAGS), selectionFlags);
+ bundle.putInt(keyForField(FIELD_ROLE_FLAGS), roleFlags);
+ bundle.putInt(keyForField(FIELD_AVERAGE_BITRATE), averageBitrate);
+ bundle.putInt(keyForField(FIELD_PEAK_BITRATE), peakBitrate);
+ bundle.putString(keyForField(FIELD_CODECS), codecs);
+ // Metadata is currently not Bundleable because Metadata.Entry is an Interface,
+ // which would be difficult to unbundle in a backward compatible way.
+ // The entries are additionally of limited usefulness to remote processes.
+ bundle.putParcelable(keyForField(FIELD_METADATA), metadata);
// Container specific.
- dest.writeString(containerMimeType);
+ bundle.putString(keyForField(FIELD_CONTAINER_MIME_TYPE), containerMimeType);
// Sample specific.
- dest.writeString(sampleMimeType);
- dest.writeInt(maxInputSize);
- int initializationDataSize = initializationData.size();
- dest.writeInt(initializationDataSize);
- for (int i = 0; i < initializationDataSize; i++) {
- dest.writeByteArray(initializationData.get(i));
+ bundle.putString(keyForField(FIELD_SAMPLE_MIME_TYPE), sampleMimeType);
+ bundle.putInt(keyForField(FIELD_MAX_INPUT_SIZE), maxInputSize);
+ for (int i = 0; i < initializationData.size(); i++) {
+ bundle.putByteArray(keyForInitializationData(i), initializationData.get(i));
}
- dest.writeParcelable(drmInitData, 0);
- dest.writeLong(subsampleOffsetUs);
+ // DrmInitData doesn't need to be Bundleable as it's only used in the playing process to
+ // initialize the decoder.
+ bundle.putParcelable(keyForField(FIELD_DRM_INIT_DATA), drmInitData);
+ bundle.putLong(keyForField(FIELD_SUBSAMPLE_OFFSET_US), subsampleOffsetUs);
// Video specific.
- dest.writeInt(width);
- dest.writeInt(height);
- dest.writeFloat(frameRate);
- dest.writeInt(rotationDegrees);
- dest.writeFloat(pixelWidthHeightRatio);
- Util.writeBoolean(dest, projectionData != null);
- if (projectionData != null) {
- dest.writeByteArray(projectionData);
- }
- dest.writeInt(stereoMode);
- dest.writeParcelable(colorInfo, flags);
+ bundle.putInt(keyForField(FIELD_WIDTH), width);
+ bundle.putInt(keyForField(FIELD_HEIGHT), height);
+ bundle.putFloat(keyForField(FIELD_FRAME_RATE), frameRate);
+ bundle.putInt(keyForField(FIELD_ROTATION_DEGREES), rotationDegrees);
+ bundle.putFloat(keyForField(FIELD_PIXEL_WIDTH_HEIGHT_RATIO), pixelWidthHeightRatio);
+ bundle.putByteArray(keyForField(FIELD_PROJECTION_DATA), projectionData);
+ bundle.putInt(keyForField(FIELD_STEREO_MODE), stereoMode);
+ bundle.putBundle(keyForField(FIELD_COLOR_INFO), BundleableUtils.toNullableBundle(colorInfo));
// Audio specific.
- dest.writeInt(channelCount);
- dest.writeInt(sampleRate);
- dest.writeInt(pcmEncoding);
- dest.writeInt(encoderDelay);
- dest.writeInt(encoderPadding);
+ bundle.putInt(keyForField(FIELD_CHANNEL_COUNT), channelCount);
+ bundle.putInt(keyForField(FIELD_SAMPLE_RATE), sampleRate);
+ bundle.putInt(keyForField(FIELD_PCM_ENCODING), pcmEncoding);
+ bundle.putInt(keyForField(FIELD_ENCODER_DELAY), encoderDelay);
+ bundle.putInt(keyForField(FIELD_ENCODER_PADDING), encoderPadding);
// Text specific.
- dest.writeInt(accessibilityChannel);
+ bundle.putInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), accessibilityChannel);
+ return bundle;
}
- public static final Creator CREATOR =
- new Creator() {
+ /** Object that can restore {@code Format} from a {@link Bundle}. */
+ public static final Creator CREATOR = Format::fromBundle;
- @Override
- public Format createFromParcel(Parcel in) {
- return new Format(in);
- }
+ private static Format fromBundle(Bundle bundle) {
+ Builder builder = new Builder();
+ BundleableUtils.ensureClassLoader(bundle);
+ builder
+ .setId(defaultIfNull(bundle.getString(keyForField(FIELD_ID)), DEFAULT.id))
+ .setLabel(defaultIfNull(bundle.getString(keyForField(FIELD_LABEL)), DEFAULT.label))
+ .setLanguage(defaultIfNull(bundle.getString(keyForField(FIELD_LANGUAGE)), DEFAULT.language))
+ .setSelectionFlags(
+ bundle.getInt(keyForField(FIELD_SELECTION_FLAGS), DEFAULT.selectionFlags))
+ .setRoleFlags(bundle.getInt(keyForField(FIELD_ROLE_FLAGS), DEFAULT.roleFlags))
+ .setAverageBitrate(
+ bundle.getInt(keyForField(FIELD_AVERAGE_BITRATE), DEFAULT.averageBitrate))
+ .setPeakBitrate(bundle.getInt(keyForField(FIELD_PEAK_BITRATE), DEFAULT.peakBitrate))
+ .setCodecs(defaultIfNull(bundle.getString(keyForField(FIELD_CODECS)), DEFAULT.codecs))
+ .setMetadata(
+ defaultIfNull(bundle.getParcelable(keyForField(FIELD_METADATA)), DEFAULT.metadata))
+ // Container specific.
+ .setContainerMimeType(
+ defaultIfNull(
+ bundle.getString(keyForField(FIELD_CONTAINER_MIME_TYPE)),
+ DEFAULT.containerMimeType))
+ // Sample specific.
+ .setSampleMimeType(
+ defaultIfNull(
+ bundle.getString(keyForField(FIELD_SAMPLE_MIME_TYPE)), DEFAULT.sampleMimeType))
+ .setMaxInputSize(bundle.getInt(keyForField(FIELD_MAX_INPUT_SIZE), DEFAULT.maxInputSize));
- @Override
- public Format[] newArray(int size) {
- return new Format[size];
- }
- };
+ List initializationData = new ArrayList<>();
+ for (int i = 0; ; i++) {
+ @Nullable byte[] data = bundle.getByteArray(keyForInitializationData(i));
+ if (data == null) {
+ break;
+ }
+ initializationData.add(data);
+ }
+ builder
+ .setInitializationData(initializationData)
+ .setDrmInitData(bundle.getParcelable(keyForField(FIELD_DRM_INIT_DATA)))
+ .setSubsampleOffsetUs(
+ bundle.getLong(keyForField(FIELD_SUBSAMPLE_OFFSET_US), DEFAULT.subsampleOffsetUs))
+ // Video specific.
+ .setWidth(bundle.getInt(keyForField(FIELD_WIDTH), DEFAULT.width))
+ .setHeight(bundle.getInt(keyForField(FIELD_HEIGHT), DEFAULT.height))
+ .setFrameRate(bundle.getFloat(keyForField(FIELD_FRAME_RATE), DEFAULT.frameRate))
+ .setRotationDegrees(
+ bundle.getInt(keyForField(FIELD_ROTATION_DEGREES), DEFAULT.rotationDegrees))
+ .setPixelWidthHeightRatio(
+ bundle.getFloat(
+ keyForField(FIELD_PIXEL_WIDTH_HEIGHT_RATIO), DEFAULT.pixelWidthHeightRatio))
+ .setProjectionData(bundle.getByteArray(keyForField(FIELD_PROJECTION_DATA)))
+ .setStereoMode(bundle.getInt(keyForField(FIELD_STEREO_MODE), DEFAULT.stereoMode))
+ .setColorInfo(
+ BundleableUtils.fromNullableBundle(
+ ColorInfo.CREATOR, bundle.getBundle(keyForField(FIELD_COLOR_INFO))))
+ // Audio specific.
+ .setChannelCount(bundle.getInt(keyForField(FIELD_CHANNEL_COUNT), DEFAULT.channelCount))
+ .setSampleRate(bundle.getInt(keyForField(FIELD_SAMPLE_RATE), DEFAULT.sampleRate))
+ .setPcmEncoding(bundle.getInt(keyForField(FIELD_PCM_ENCODING), DEFAULT.pcmEncoding))
+ .setEncoderDelay(bundle.getInt(keyForField(FIELD_ENCODER_DELAY), DEFAULT.encoderDelay))
+ .setEncoderPadding(
+ bundle.getInt(keyForField(FIELD_ENCODER_PADDING), DEFAULT.encoderPadding))
+ // Text specific.
+ .setAccessibilityChannel(
+ bundle.getInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), DEFAULT.accessibilityChannel));
+
+ return builder.build();
+ }
+
+ private static String keyForField(@FieldNumber int field) {
+ return Integer.toString(field, Character.MAX_RADIX);
+ }
+
+ private static String keyForInitializationData(int initialisationDataIndex) {
+ return keyForField(FIELD_INITIALIZATION_DATA)
+ + "_"
+ + Integer.toString(initialisationDataIndex, Character.MAX_RADIX);
+ }
+
+ @Nullable
+ private static T defaultIfNull(@Nullable T value, @Nullable T defaultValue) {
+ return value != null ? value : defaultValue;
+ }
}
diff --git a/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java b/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java
index 0888f3fa96..4f9f93fc33 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java
@@ -15,17 +15,26 @@
*/
package com.google.android.exoplayer2.source;
-import android.os.Parcel;
-import android.os.Parcelable;
+import static com.google.android.exoplayer2.util.Assertions.checkArgument;
+
+import android.os.Bundle;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.util.Assertions;
+import com.google.android.exoplayer2.util.BundleableUtils;
import com.google.android.exoplayer2.util.Log;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.List;
/** Defines an immutable group of tracks identified by their format identity. */
-public final class TrackGroup implements Parcelable {
+public final class TrackGroup implements Bundleable {
private static final String TAG = "TrackGroup";
@@ -37,22 +46,18 @@ public final class TrackGroup implements Parcelable {
// Lazily initialized hashcode.
private int hashCode;
- /** @param formats The track formats. At least one {@link Format} must be provided. */
+ /**
+ * Constructs an instance {@code TrackGroup} containing the provided {@code formats}.
+ *
+ * @param formats Non empty array of format.
+ */
public TrackGroup(Format... formats) {
- Assertions.checkState(formats.length > 0);
+ checkArgument(formats.length > 0);
this.formats = formats;
this.length = formats.length;
verifyCorrectness();
}
- /* package */ TrackGroup(Parcel in) {
- length = in.readInt();
- formats = new Format[length];
- for (int i = 0; i < length; i++) {
- formats[i] = in.readParcelable(Format.class.getClassLoader());
- }
- }
-
/**
* Returns the format of the track at a given index.
*
@@ -103,35 +108,40 @@ public final class TrackGroup implements Parcelable {
return length == other.length && Arrays.equals(formats, other.formats);
}
- // Parcelable implementation.
+ // Bundleable implementation.
+
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_FORMATS,
+ })
+ private @interface FieldNumber {}
+
+ private static final int FIELD_FORMATS = 0;
@Override
- public int describeContents() {
- return 0;
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(
+ keyForField(FIELD_FORMATS), BundleableUtils.toBundleArrayList(Lists.newArrayList(formats)));
+ return bundle;
}
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(length);
- for (int i = 0; i < length; i++) {
- dest.writeParcelable(formats[i], 0);
- }
- }
-
- public static final Parcelable.Creator CREATOR =
- new Parcelable.Creator() {
-
- @Override
- public TrackGroup createFromParcel(Parcel in) {
- return new TrackGroup(in);
- }
-
- @Override
- public TrackGroup[] newArray(int size) {
- return new TrackGroup[size];
- }
+ /** Object that can restore {@code TrackGroup} from a {@link Bundle}. */
+ public static final Creator CREATOR =
+ bundle -> {
+ List formats =
+ BundleableUtils.fromBundleNullableList(
+ Format.CREATOR,
+ bundle.getParcelableArrayList(keyForField(FIELD_FORMATS)),
+ ImmutableList.of());
+ return new TrackGroup(formats.toArray(new Format[0]));
};
+ private static String keyForField(@FieldNumber int field) {
+ return Integer.toString(field, Character.MAX_RADIX);
+ }
+
private void verifyCorrectness() {
// TrackGroups should only contain tracks with exactly the same content (but in different
// qualities). We only log an error instead of throwing to not break backwards-compatibility for
diff --git a/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java b/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java
index 8db7b9c385..0af14a5fdc 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java
@@ -15,14 +15,22 @@
*/
package com.google.android.exoplayer2.source;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Bundle;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.util.BundleableUtils;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.List;
/** An immutable array of {@link TrackGroup}s. */
-public final class TrackGroupArray implements Parcelable {
+public final class TrackGroupArray implements Bundleable {
/** The empty array. */
public static final TrackGroupArray EMPTY = new TrackGroupArray();
@@ -35,20 +43,12 @@ public final class TrackGroupArray implements Parcelable {
// Lazily initialized hashcode.
private int hashCode;
- /** @param trackGroups The groups. May be empty. */
+ /** Construct a {@code TrackGroupArray} from an array of (possibly empty) trackGroups. */
public TrackGroupArray(TrackGroup... trackGroups) {
this.trackGroups = trackGroups;
this.length = trackGroups.length;
}
- /* package */ TrackGroupArray(Parcel in) {
- length = in.readInt();
- trackGroups = new TrackGroup[length];
- for (int i = 0; i < length; i++) {
- trackGroups[i] = in.readParcelable(TrackGroup.class.getClassLoader());
- }
- }
-
/**
* Returns the group at a given index.
*
@@ -102,32 +102,38 @@ public final class TrackGroupArray implements Parcelable {
return length == other.length && Arrays.equals(trackGroups, other.trackGroups);
}
- // Parcelable implementation.
+ // Bundleable implementation.
+
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_TRACK_GROUPS,
+ })
+ private @interface FieldNumber {}
+
+ private static final int FIELD_TRACK_GROUPS = 0;
@Override
- public int describeContents() {
- return 0;
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(
+ keyForField(FIELD_TRACK_GROUPS),
+ BundleableUtils.toBundleArrayList(Lists.newArrayList(trackGroups)));
+ return bundle;
}
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(length);
- for (int i = 0; i < length; i++) {
- dest.writeParcelable(trackGroups[i], 0);
- }
- }
-
- public static final Parcelable.Creator CREATOR =
- new Parcelable.Creator() {
-
- @Override
- public TrackGroupArray createFromParcel(Parcel in) {
- return new TrackGroupArray(in);
- }
-
- @Override
- public TrackGroupArray[] newArray(int size) {
- return new TrackGroupArray[size];
- }
+ /** Object that can restores a TrackGroupArray from a {@link Bundle}. */
+ public static final Creator CREATOR =
+ bundle -> {
+ List trackGroups =
+ BundleableUtils.fromBundleNullableList(
+ TrackGroup.CREATOR,
+ bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUPS)),
+ /* defaultValue= */ ImmutableList.of());
+ return new TrackGroupArray(trackGroups.toArray(new TrackGroup[0]));
};
+
+ private static String keyForField(@FieldNumber int field) {
+ return Integer.toString(field, Character.MAX_RADIX);
+ }
}
diff --git a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java
index bb8fce5fa4..e62e93893b 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java
@@ -16,23 +16,28 @@
package com.google.android.exoplayer2.trackselection;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
+import static com.google.common.base.MoreObjects.firstNonNull;
import android.content.Context;
import android.graphics.Point;
+import android.os.Bundle;
import android.os.Looper;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.view.accessibility.CaptioningManager;
+import androidx.annotation.CallSuper;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
/** Constraint parameters for track selection. */
-public class TrackSelectionParameters implements Parcelable {
+public class TrackSelectionParameters implements Bundleable {
/**
* A builder for {@link TrackSelectionParameters}. See the {@link TrackSelectionParameters}
@@ -108,10 +113,7 @@ public class TrackSelectionParameters implements Parcelable {
setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true);
}
- /**
- * @param initialValues The {@link TrackSelectionParameters} from which the initial values of
- * the builder are obtained.
- */
+ /** Creates a builder with the initial values specified in {@code initialValues}. */
protected Builder(TrackSelectionParameters initialValues) {
// Video
maxVideoWidth = initialValues.maxVideoWidth;
@@ -141,6 +143,89 @@ public class TrackSelectionParameters implements Parcelable {
forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate;
}
+ /** Creates a builder with the initial values specified in {@code bundle}. */
+ protected Builder(Bundle bundle) {
+ // Video
+ maxVideoWidth =
+ bundle.getInt(keyForField(FIELD_MAX_VIDEO_WIDTH), DEFAULT_WITHOUT_CONTEXT.maxVideoWidth);
+ maxVideoHeight =
+ bundle.getInt(
+ keyForField(FIELD_MAX_VIDEO_HEIGHT), DEFAULT_WITHOUT_CONTEXT.maxVideoHeight);
+ maxVideoFrameRate =
+ bundle.getInt(
+ keyForField(FIELD_MAX_VIDEO_FRAMERATE), DEFAULT_WITHOUT_CONTEXT.maxVideoFrameRate);
+ maxVideoBitrate =
+ bundle.getInt(
+ keyForField(FIELD_MAX_VIDEO_BITRATE), DEFAULT_WITHOUT_CONTEXT.maxVideoBitrate);
+ minVideoWidth =
+ bundle.getInt(keyForField(FIELD_MIN_VIDEO_WIDTH), DEFAULT_WITHOUT_CONTEXT.minVideoWidth);
+ minVideoHeight =
+ bundle.getInt(
+ keyForField(FIELD_MIN_VIDEO_HEIGHT), DEFAULT_WITHOUT_CONTEXT.minVideoHeight);
+ minVideoFrameRate =
+ bundle.getInt(
+ keyForField(FIELD_MIN_VIDEO_FRAMERATE), DEFAULT_WITHOUT_CONTEXT.minVideoFrameRate);
+ minVideoBitrate =
+ bundle.getInt(
+ keyForField(FIELD_MIN_VIDEO_BITRATE), DEFAULT_WITHOUT_CONTEXT.minVideoBitrate);
+ viewportWidth =
+ bundle.getInt(keyForField(FIELD_VIEWPORT_WIDTH), DEFAULT_WITHOUT_CONTEXT.viewportWidth);
+ viewportHeight =
+ bundle.getInt(keyForField(FIELD_VIEWPORT_HEIGHT), DEFAULT_WITHOUT_CONTEXT.viewportHeight);
+ viewportOrientationMayChange =
+ bundle.getBoolean(
+ keyForField(FIELD_VIEWPORT_ORIENTATION_MAY_CHANGE),
+ DEFAULT_WITHOUT_CONTEXT.viewportOrientationMayChange);
+ preferredVideoMimeTypes =
+ ImmutableList.copyOf(
+ firstNonNull(
+ bundle.getStringArray(keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES)),
+ new String[0]));
+ // Audio
+ String[] preferredAudioLanguages1 =
+ firstNonNull(
+ bundle.getStringArray(keyForField(FIELD_PREFERRED_AUDIO_LANGUAGES)), new String[0]);
+ preferredAudioLanguages = normalizeLanguageCodes(preferredAudioLanguages1);
+ preferredAudioRoleFlags =
+ bundle.getInt(
+ keyForField(FIELD_PREFERRED_AUDIO_ROLE_FLAGS),
+ DEFAULT_WITHOUT_CONTEXT.preferredAudioRoleFlags);
+ maxAudioChannelCount =
+ bundle.getInt(
+ keyForField(FIELD_MAX_AUDIO_CHANNEL_COUNT),
+ DEFAULT_WITHOUT_CONTEXT.maxAudioChannelCount);
+ maxAudioBitrate =
+ bundle.getInt(
+ keyForField(FIELD_MAX_AUDIO_BITRATE), DEFAULT_WITHOUT_CONTEXT.maxAudioBitrate);
+ preferredAudioMimeTypes =
+ ImmutableList.copyOf(
+ firstNonNull(
+ bundle.getStringArray(keyForField(FIELD_PREFERRED_AUDIO_MIME_TYPES)),
+ new String[0]));
+ // Text
+ preferredTextLanguages =
+ normalizeLanguageCodes(
+ firstNonNull(
+ bundle.getStringArray(keyForField(FIELD_PREFERRED_TEXT_LANGUAGES)),
+ new String[0]));
+ preferredTextRoleFlags =
+ bundle.getInt(
+ keyForField(FIELD_PREFERRED_TEXT_ROLE_FLAGS),
+ DEFAULT_WITHOUT_CONTEXT.preferredTextRoleFlags);
+ selectUndeterminedTextLanguage =
+ bundle.getBoolean(
+ keyForField(FIELD_SELECT_UNDETERMINED_TEXT_LANGUAGE),
+ DEFAULT_WITHOUT_CONTEXT.selectUndeterminedTextLanguage);
+ // General
+ forceLowestBitrate =
+ bundle.getBoolean(
+ keyForField(FIELD_FORCE_LOWEST_BITRATE), DEFAULT_WITHOUT_CONTEXT.forceLowestBitrate);
+ forceHighestSupportedBitrate =
+ bundle.getBoolean(
+ keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE),
+ DEFAULT_WITHOUT_CONTEXT.forceHighestSupportedBitrate);
+ }
+
// Video
/**
@@ -322,11 +407,7 @@ public class TrackSelectionParameters implements Parcelable {
* @return This builder.
*/
public Builder setPreferredAudioLanguages(String... preferredAudioLanguages) {
- ImmutableList.Builder listBuilder = ImmutableList.builder();
- for (String language : checkNotNull(preferredAudioLanguages)) {
- listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language)));
- }
- this.preferredAudioLanguages = listBuilder.build();
+ this.preferredAudioLanguages = normalizeLanguageCodes(preferredAudioLanguages);
return this;
}
@@ -427,11 +508,7 @@ public class TrackSelectionParameters implements Parcelable {
* @return This builder.
*/
public Builder setPreferredTextLanguages(String... preferredTextLanguages) {
- ImmutableList.Builder listBuilder = ImmutableList.builder();
- for (String language : checkNotNull(preferredTextLanguages)) {
- listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language)));
- }
- this.preferredTextLanguages = listBuilder.build();
+ this.preferredTextLanguages = normalizeLanguageCodes(preferredTextLanguages);
return this;
}
@@ -512,6 +589,14 @@ public class TrackSelectionParameters implements Parcelable {
preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale));
}
}
+
+ private static ImmutableList normalizeLanguageCodes(String[] preferredTextLanguages) {
+ ImmutableList.Builder listBuilder = ImmutableList.builder();
+ for (String language : checkNotNull(preferredTextLanguages)) {
+ listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language)));
+ }
+ return listBuilder.build();
+ }
}
/**
@@ -537,20 +622,6 @@ public class TrackSelectionParameters implements Parcelable {
*/
@Deprecated public static final TrackSelectionParameters DEFAULT = DEFAULT_WITHOUT_CONTEXT;
- public static final Creator CREATOR =
- new Creator() {
-
- @Override
- public TrackSelectionParameters createFromParcel(Parcel in) {
- return new TrackSelectionParameters(in);
- }
-
- @Override
- public TrackSelectionParameters[] newArray(int size) {
- return new TrackSelectionParameters[size];
- }
- };
-
/** Returns an instance configured with default values. */
public static TrackSelectionParameters getDefaults(Context context) {
return new Builder(context).build();
@@ -707,42 +778,6 @@ public class TrackSelectionParameters implements Parcelable {
this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate;
}
- /* package */ TrackSelectionParameters(Parcel in) {
- ArrayList preferredAudioLanguages = new ArrayList<>();
- in.readList(preferredAudioLanguages, /* loader= */ null);
- this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages);
- this.preferredAudioRoleFlags = in.readInt();
- ArrayList preferredTextLanguages1 = new ArrayList<>();
- in.readList(preferredTextLanguages1, /* loader= */ null);
- this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages1);
- this.preferredTextRoleFlags = in.readInt();
- this.selectUndeterminedTextLanguage = Util.readBoolean(in);
- // Video
- this.maxVideoWidth = in.readInt();
- this.maxVideoHeight = in.readInt();
- this.maxVideoFrameRate = in.readInt();
- this.maxVideoBitrate = in.readInt();
- this.minVideoWidth = in.readInt();
- this.minVideoHeight = in.readInt();
- this.minVideoFrameRate = in.readInt();
- this.minVideoBitrate = in.readInt();
- this.viewportWidth = in.readInt();
- this.viewportHeight = in.readInt();
- this.viewportOrientationMayChange = Util.readBoolean(in);
- ArrayList preferredVideoMimeTypes = new ArrayList<>();
- in.readList(preferredVideoMimeTypes, /* loader= */ null);
- this.preferredVideoMimeTypes = ImmutableList.copyOf(preferredVideoMimeTypes);
- // Audio
- this.maxAudioChannelCount = in.readInt();
- this.maxAudioBitrate = in.readInt();
- ArrayList preferredAudioMimeTypes = new ArrayList<>();
- in.readList(preferredAudioMimeTypes, /* loader= */ null);
- this.preferredAudioMimeTypes = ImmutableList.copyOf(preferredAudioMimeTypes);
- // General
- this.forceLowestBitrate = Util.readBoolean(in);
- this.forceHighestSupportedBitrate = Util.readBoolean(in);
- }
-
/** Creates a new {@link Builder}, copying the initial values from this instance. */
public Builder buildUpon() {
return new Builder(this);
@@ -817,39 +852,109 @@ public class TrackSelectionParameters implements Parcelable {
return result;
}
- // Parcelable implementation.
+ // Bundleable implementation
+
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_PREFERRED_AUDIO_LANGUAGES,
+ FIELD_PREFERRED_AUDIO_ROLE_FLAGS,
+ FIELD_PREFERRED_TEXT_LANGUAGES,
+ FIELD_PREFERRED_TEXT_ROLE_FLAGS,
+ FIELD_SELECT_UNDETERMINED_TEXT_LANGUAGE,
+ FIELD_MAX_VIDEO_WIDTH,
+ FIELD_MAX_VIDEO_HEIGHT,
+ FIELD_MAX_VIDEO_FRAMERATE,
+ FIELD_MAX_VIDEO_BITRATE,
+ FIELD_MIN_VIDEO_WIDTH,
+ FIELD_MIN_VIDEO_HEIGHT,
+ FIELD_MIN_VIDEO_FRAMERATE,
+ FIELD_MIN_VIDEO_BITRATE,
+ FIELD_VIEWPORT_WIDTH,
+ FIELD_VIEWPORT_HEIGHT,
+ FIELD_VIEWPORT_ORIENTATION_MAY_CHANGE,
+ FIELD_PREFERRED_VIDEO_MIMETYPES,
+ FIELD_MAX_AUDIO_CHANNEL_COUNT,
+ FIELD_MAX_AUDIO_BITRATE,
+ FIELD_PREFERRED_AUDIO_MIME_TYPES,
+ FIELD_FORCE_LOWEST_BITRATE,
+ FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE,
+ })
+ private @interface FieldNumber {}
+
+ private static final int FIELD_PREFERRED_AUDIO_LANGUAGES = 1;
+ private static final int FIELD_PREFERRED_AUDIO_ROLE_FLAGS = 2;
+ private static final int FIELD_PREFERRED_TEXT_LANGUAGES = 3;
+ private static final int FIELD_PREFERRED_TEXT_ROLE_FLAGS = 4;
+ private static final int FIELD_SELECT_UNDETERMINED_TEXT_LANGUAGE = 5;
+ private static final int FIELD_MAX_VIDEO_WIDTH = 6;
+ private static final int FIELD_MAX_VIDEO_HEIGHT = 7;
+ private static final int FIELD_MAX_VIDEO_FRAMERATE = 8;
+ private static final int FIELD_MAX_VIDEO_BITRATE = 9;
+ private static final int FIELD_MIN_VIDEO_WIDTH = 10;
+ private static final int FIELD_MIN_VIDEO_HEIGHT = 11;
+ private static final int FIELD_MIN_VIDEO_FRAMERATE = 12;
+ private static final int FIELD_MIN_VIDEO_BITRATE = 13;
+ private static final int FIELD_VIEWPORT_WIDTH = 14;
+ private static final int FIELD_VIEWPORT_HEIGHT = 15;
+ private static final int FIELD_VIEWPORT_ORIENTATION_MAY_CHANGE = 16;
+ private static final int FIELD_PREFERRED_VIDEO_MIMETYPES = 17;
+ private static final int FIELD_MAX_AUDIO_CHANNEL_COUNT = 18;
+ private static final int FIELD_MAX_AUDIO_BITRATE = 19;
+ private static final int FIELD_PREFERRED_AUDIO_MIME_TYPES = 20;
+ private static final int FIELD_FORCE_LOWEST_BITRATE = 21;
+ private static final int FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE = 22;
@Override
- public int describeContents() {
- return 0;
+ @CallSuper
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+
+ // Video
+ bundle.putInt(keyForField(FIELD_MAX_VIDEO_WIDTH), maxVideoWidth);
+ bundle.putInt(keyForField(FIELD_MAX_VIDEO_HEIGHT), maxVideoHeight);
+ bundle.putInt(keyForField(FIELD_MAX_VIDEO_FRAMERATE), maxVideoFrameRate);
+ bundle.putInt(keyForField(FIELD_MAX_VIDEO_BITRATE), maxVideoBitrate);
+ bundle.putInt(keyForField(FIELD_MIN_VIDEO_WIDTH), minVideoWidth);
+ bundle.putInt(keyForField(FIELD_MIN_VIDEO_HEIGHT), minVideoHeight);
+ bundle.putInt(keyForField(FIELD_MIN_VIDEO_FRAMERATE), minVideoFrameRate);
+ bundle.putInt(keyForField(FIELD_MIN_VIDEO_BITRATE), minVideoBitrate);
+ bundle.putInt(keyForField(FIELD_VIEWPORT_WIDTH), viewportWidth);
+ bundle.putInt(keyForField(FIELD_VIEWPORT_HEIGHT), viewportHeight);
+ bundle.putBoolean(
+ keyForField(FIELD_VIEWPORT_ORIENTATION_MAY_CHANGE), viewportOrientationMayChange);
+ bundle.putStringArray(
+ keyForField(FIELD_PREFERRED_VIDEO_MIMETYPES),
+ preferredVideoMimeTypes.toArray(new String[0]));
+ // Audio
+ bundle.putStringArray(
+ keyForField(FIELD_PREFERRED_AUDIO_LANGUAGES),
+ preferredAudioLanguages.toArray(new String[0]));
+ bundle.putInt(keyForField(FIELD_PREFERRED_AUDIO_ROLE_FLAGS), preferredAudioRoleFlags);
+ bundle.putInt(keyForField(FIELD_MAX_AUDIO_CHANNEL_COUNT), maxAudioChannelCount);
+ bundle.putInt(keyForField(FIELD_MAX_AUDIO_BITRATE), maxAudioBitrate);
+ bundle.putStringArray(
+ keyForField(FIELD_PREFERRED_AUDIO_MIME_TYPES),
+ preferredAudioMimeTypes.toArray(new String[0]));
+ // Text
+ bundle.putStringArray(
+ keyForField(FIELD_PREFERRED_TEXT_LANGUAGES), preferredTextLanguages.toArray(new String[0]));
+ bundle.putInt(keyForField(FIELD_PREFERRED_TEXT_ROLE_FLAGS), preferredTextRoleFlags);
+ bundle.putBoolean(
+ keyForField(FIELD_SELECT_UNDETERMINED_TEXT_LANGUAGE), selectUndeterminedTextLanguage);
+ // General
+ bundle.putBoolean(keyForField(FIELD_FORCE_LOWEST_BITRATE), forceLowestBitrate);
+ bundle.putBoolean(
+ keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), forceHighestSupportedBitrate);
+
+ return bundle;
}
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeList(preferredAudioLanguages);
- dest.writeInt(preferredAudioRoleFlags);
- dest.writeList(preferredTextLanguages);
- dest.writeInt(preferredTextRoleFlags);
- Util.writeBoolean(dest, selectUndeterminedTextLanguage);
- // Video
- dest.writeInt(maxVideoWidth);
- dest.writeInt(maxVideoHeight);
- dest.writeInt(maxVideoFrameRate);
- dest.writeInt(maxVideoBitrate);
- dest.writeInt(minVideoWidth);
- dest.writeInt(minVideoHeight);
- dest.writeInt(minVideoFrameRate);
- dest.writeInt(minVideoBitrate);
- dest.writeInt(viewportWidth);
- dest.writeInt(viewportHeight);
- Util.writeBoolean(dest, viewportOrientationMayChange);
- dest.writeList(preferredVideoMimeTypes);
- // Audio
- dest.writeInt(maxAudioChannelCount);
- dest.writeInt(maxAudioBitrate);
- dest.writeList(preferredAudioMimeTypes);
- // General
- Util.writeBoolean(dest, forceLowestBitrate);
- Util.writeBoolean(dest, forceHighestSupportedBitrate);
+ /** Object that can restore {@code TrackSelectionParameters} from a {@link Bundle}. */
+ public static final Creator CREATOR =
+ bundle -> new Builder(bundle).build();
+
+ private static String keyForField(@FieldNumber int field) {
+ return Integer.toString(field, Character.MAX_RADIX);
}
}
diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java b/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java
index adc9514f7d..1a29691dd8 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/util/BundleableUtils.java
@@ -15,7 +15,11 @@
*/
package com.google.android.exoplayer2.util;
+import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
+import static com.google.android.exoplayer2.util.Util.castNonNull;
+
import android.os.Bundle;
+import android.util.SparseArray;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Bundleable;
import com.google.common.collect.ImmutableList;
@@ -68,13 +72,41 @@ public final class BundleableUtils {
Bundleable.Creator creator, List bundleList) {
ImmutableList.Builder builder = ImmutableList.builder();
for (int i = 0; i < bundleList.size(); i++) {
- Bundle bundle = bundleList.get(i);
+ Bundle bundle = checkNotNull(bundleList.get(i)); // Fail fast during parsing.
T bundleable = creator.fromBundle(bundle);
builder.add(bundleable);
}
return builder.build();
}
+ /**
+ * Converts a list of {@link Bundle} to a list of {@link Bundleable}. Returns {@code defaultValue}
+ * if {@code bundleList} is null.
+ */
+ public static List fromBundleNullableList(
+ Bundleable.Creator creator, @Nullable List bundleList, List defaultValue) {
+ return (bundleList == null) ? defaultValue : fromBundleList(creator, bundleList);
+ }
+
+ /**
+ * Converts a {@link SparseArray} of {@link Bundle} to a {@link SparseArray} of {@link
+ * Bundleable}. Returns {@code defaultValue} if {@code bundleSparseArray} is null.
+ */
+ public static SparseArray fromBundleNullableSparseArray(
+ Bundleable.Creator creator,
+ @Nullable SparseArray bundleSparseArray,
+ SparseArray defaultValue) {
+ if (bundleSparseArray == null) {
+ return defaultValue;
+ }
+ // Can't use ImmutableList as it doesn't support null elements.
+ SparseArray result = new SparseArray<>(bundleSparseArray.size());
+ for (int i = 0; i < bundleSparseArray.size(); i++) {
+ result.put(bundleSparseArray.keyAt(i), creator.fromBundle(bundleSparseArray.valueAt(i)));
+ }
+ return result;
+ }
+
/**
* Converts a list of {@link Bundleable} to an {@link ArrayList} of {@link Bundle} so that the
* returned list can be put to {@link Bundle} using {@link Bundle#putParcelableArrayList}
@@ -88,5 +120,31 @@ public final class BundleableUtils {
return arrayList;
}
+ /**
+ * Converts a {@link SparseArray} of {@link Bundleable} to an {@link SparseArray} of {@link
+ * Bundle} so that the returned {@link SparseArray} can be put to {@link Bundle} using {@link
+ * Bundle#putSparseParcelableArray} conveniently.
+ */
+ public static SparseArray toBundleSparseArray(
+ SparseArray bundleableSparseArray) {
+ SparseArray sparseArray = new SparseArray<>(bundleableSparseArray.size());
+ for (int i = 0; i < bundleableSparseArray.size(); i++) {
+ sparseArray.put(bundleableSparseArray.keyAt(i), bundleableSparseArray.valueAt(i).toBundle());
+ }
+ return sparseArray;
+ }
+
+ /**
+ * Set the application class loader to the given {@link Bundle} if no class loader is present.
+ *
+ * This assumes that all classes unparceled from {@code bundle} are sharing the class loader of
+ * {@code BundleableUtils}.
+ */
+ public static void ensureClassLoader(@Nullable Bundle bundle) {
+ if (bundle != null) {
+ bundle.setClassLoader(castNonNull(BundleableUtils.class.getClassLoader()));
+ }
+ }
+
private BundleableUtils() {}
}
diff --git a/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java
index 38fe968668..17ca09a747 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java
@@ -15,17 +15,20 @@
*/
package com.google.android.exoplayer2.video;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Bundle;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.util.Util;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import org.checkerframework.dataflow.qual.Pure;
/** Stores color info. */
-public final class ColorInfo implements Parcelable {
+public final class ColorInfo implements Bundleable {
/**
* Returns the {@link C.ColorSpace} corresponding to the given ISO color primary code, as per
@@ -116,16 +119,6 @@ public final class ColorInfo implements Parcelable {
this.hdrStaticInfo = hdrStaticInfo;
}
- @SuppressWarnings("ResourceType")
- /* package */ ColorInfo(Parcel in) {
- colorSpace = in.readInt();
- colorRange = in.readInt();
- colorTransfer = in.readInt();
- boolean hasHdrStaticInfo = Util.readBoolean(in);
- hdrStaticInfo = hasHdrStaticInfo ? in.createByteArray() : null;
- }
-
- // Parcelable implementation.
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
@@ -167,32 +160,42 @@ public final class ColorInfo implements Parcelable {
return hashCode;
}
- @Override
- public int describeContents() {
- return 0;
- }
+ // Bundleable implementation
+
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_COLOR_SPACE,
+ FIELD_COLOR_RANGE,
+ FIELD_COLOR_TRANSFER,
+ FIELD_HDR_STATIC_INFO,
+ })
+ private @interface FieldNumber {}
+
+ private static final int FIELD_COLOR_SPACE = 0;
+ private static final int FIELD_COLOR_RANGE = 1;
+ private static final int FIELD_COLOR_TRANSFER = 2;
+ private static final int FIELD_HDR_STATIC_INFO = 3;
@Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(colorSpace);
- dest.writeInt(colorRange);
- dest.writeInt(colorTransfer);
- Util.writeBoolean(dest, hdrStaticInfo != null);
- if (hdrStaticInfo != null) {
- dest.writeByteArray(hdrStaticInfo);
- }
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putInt(keyForField(FIELD_COLOR_SPACE), colorSpace);
+ bundle.putInt(keyForField(FIELD_COLOR_RANGE), colorRange);
+ bundle.putInt(keyForField(FIELD_COLOR_TRANSFER), colorTransfer);
+ bundle.putByteArray(keyForField(FIELD_HDR_STATIC_INFO), hdrStaticInfo);
+ return bundle;
}
- public static final Parcelable.Creator CREATOR =
- new Parcelable.Creator() {
- @Override
- public ColorInfo createFromParcel(Parcel in) {
- return new ColorInfo(in);
- }
+ public static final Creator CREATOR =
+ bundle ->
+ new ColorInfo(
+ bundle.getInt(keyForField(FIELD_COLOR_SPACE), Format.NO_VALUE),
+ bundle.getInt(keyForField(FIELD_COLOR_RANGE), Format.NO_VALUE),
+ bundle.getInt(keyForField(FIELD_COLOR_TRANSFER), Format.NO_VALUE),
+ bundle.getByteArray(keyForField(FIELD_HDR_STATIC_INFO)));
- @Override
- public ColorInfo[] newArray(int size) {
- return new ColorInfo[size];
- }
- };
+ private static String keyForField(@FieldNumber int field) {
+ return Integer.toString(field, Character.MAX_RADIX);
+ }
}
diff --git a/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java b/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java
index 1ad888c868..87fc725029 100644
--- a/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java
+++ b/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java
@@ -20,7 +20,6 @@ import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_MP4;
import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_WEBM;
import static com.google.common.truth.Truth.assertThat;
-import android.os.Parcel;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
@@ -46,21 +45,15 @@ public final class FormatTest {
}
@Test
- public void parcelFormat_createsEqualFormat_exceptExoMediaCryptoType() {
- Format formatToParcel = createTestFormat();
+ public void roundTripViaBundle_ofParameters_yieldsEqualInstanceExceptExoMediaCryptoType() {
+ Format formatToBundle = createTestFormat();
- Parcel parcel = Parcel.obtain();
- formatToParcel.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
+ Format formatFromBundle = Format.CREATOR.fromBundle(formatToBundle.toBundle());
- Format formatFromParcel = Format.CREATOR.createFromParcel(parcel);
- Format expectedFormat =
- formatToParcel.buildUpon().setExoMediaCryptoType(UnsupportedMediaCrypto.class).build();
-
- assertThat(formatFromParcel.exoMediaCryptoType).isEqualTo(UnsupportedMediaCrypto.class);
- assertThat(formatFromParcel).isEqualTo(expectedFormat);
-
- parcel.recycle();
+ assertThat(formatFromBundle.exoMediaCryptoType).isEqualTo(UnsupportedMediaCrypto.class);
+ assertThat(formatFromBundle)
+ .isEqualTo(
+ formatToBundle.buildUpon().setExoMediaCryptoType(UnsupportedMediaCrypto.class).build());
}
private static Format createTestFormat() {
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java
index 2d78d4409d..778999d2cb 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java
@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.C.FormatSupport;
import com.google.android.exoplayer2.source.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.util.Assertions;
+import com.google.android.exoplayer2.util.BundleableUtils;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.lang.annotation.Documented;
@@ -234,7 +235,9 @@ public final class ExoPlaybackException extends PlaybackException {
rendererName = bundle.getString(keyForField(FIELD_RENDERER_NAME));
rendererIndex =
bundle.getInt(keyForField(FIELD_RENDERER_INDEX), /* defaultValue= */ C.INDEX_UNSET);
- rendererFormat = bundle.getParcelable(keyForField(FIELD_RENDERER_FORMAT));
+ rendererFormat =
+ BundleableUtils.fromNullableBundle(
+ Format.CREATOR, bundle.getBundle(keyForField(FIELD_RENDERER_FORMAT)));
rendererFormatSupport =
bundle.getInt(
keyForField(FIELD_RENDERER_FORMAT_SUPPORT), /* defaultValue= */ C.FORMAT_HANDLED);
@@ -396,7 +399,8 @@ public final class ExoPlaybackException extends PlaybackException {
bundle.putInt(keyForField(FIELD_TYPE), type);
bundle.putString(keyForField(FIELD_RENDERER_NAME), rendererName);
bundle.putInt(keyForField(FIELD_RENDERER_INDEX), rendererIndex);
- bundle.putParcelable(keyForField(FIELD_RENDERER_FORMAT), rendererFormat);
+ bundle.putBundle(
+ keyForField(FIELD_RENDERER_FORMAT), BundleableUtils.toNullableBundle(rendererFormat));
bundle.putInt(keyForField(FIELD_RENDERER_FORMAT_SUPPORT), rendererFormatSupport);
bundle.putBoolean(keyForField(FIELD_IS_RECOVERABLE), isRecoverable);
return bundle;
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
index 91c4a79d3a..cca7bc1873 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
@@ -17,13 +17,14 @@ package com.google.android.exoplayer2.trackselection;
import android.content.Context;
import android.graphics.Point;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Bundle;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.C.FormatSupport;
import com.google.android.exoplayer2.ExoPlaybackException;
@@ -39,11 +40,15 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Assertions;
+import com.google.android.exoplayer2.util.BundleableUtils;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -239,6 +244,66 @@ public class DefaultTrackSelector extends MappingTrackSelector {
rendererDisabledFlags = initialValues.rendererDisabledFlags.clone();
}
+ @SuppressWarnings("method.invocation") // Only setter are invoked.
+ private ParametersBuilder(Bundle bundle) {
+ super(bundle);
+ Parameters defaultValue = Parameters.DEFAULT_WITHOUT_CONTEXT;
+ // Video
+ setExceedVideoConstraintsIfNecessary(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_EXCEED_VIDEO_CONSTRAINTS_IF_NECESSARY),
+ defaultValue.exceedVideoConstraintsIfNecessary));
+ setAllowVideoMixedMimeTypeAdaptiveness(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_ALLOW_VIDEO_MIXED_MIME_TYPE_ADAPTIVENESS),
+ defaultValue.allowVideoMixedMimeTypeAdaptiveness));
+ setAllowVideoNonSeamlessAdaptiveness(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_ALLOW_VIDEO_NON_SEAMLESS_ADAPTIVENESS),
+ defaultValue.allowVideoNonSeamlessAdaptiveness));
+ // Audio
+ setExceedAudioConstraintsIfNecessary(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_EXCEED_AUDIO_CONSTRAINTS_IF_NCESSARY),
+ defaultValue.exceedAudioConstraintsIfNecessary));
+ setAllowAudioMixedMimeTypeAdaptiveness(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_ALLOW_AUDIO_MIXED_MIME_TYPE_ADAPTIVENESS),
+ defaultValue.allowAudioMixedMimeTypeAdaptiveness));
+ setAllowAudioMixedSampleRateAdaptiveness(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_ALLOW_AUDIO_MIXED_SAMPLE_RATE_ADAPTIVENESS),
+ defaultValue.allowAudioMixedSampleRateAdaptiveness));
+ setAllowAudioMixedChannelCountAdaptiveness(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_ALLOW_AUDIO_MIXED_CHANNEL_COUNT_ADAPTIVENESS),
+ defaultValue.allowAudioMixedChannelCountAdaptiveness));
+ // Text
+ setDisabledTextTrackSelectionFlags(
+ bundle.getInt(
+ Parameters.keyForField(Parameters.FIELD_DISABLED_TEXT_TRACK_SELECTION_FLAGS),
+ defaultValue.disabledTextTrackSelectionFlags));
+ // General
+ setExceedRendererCapabilitiesIfNecessary(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_EXCEED_RENDERER_CAPABILITIES_IF_NECESSARY),
+ defaultValue.exceedRendererCapabilitiesIfNecessary));
+ setTunnelingEnabled(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_TUNNELING_ENABLED),
+ defaultValue.tunnelingEnabled));
+ setAllowMultipleAdaptiveSelections(
+ bundle.getBoolean(
+ Parameters.keyForField(Parameters.FIELD_ALLOW_MULTIPLE_ADAPTIVE_SELECTIONS),
+ defaultValue.allowMultipleAdaptiveSelections));
+
+ selectionOverrides = new SparseArray<>();
+ setSelectionOverridesFromBundle(bundle);
+
+ rendererDisabledFlags = new SparseBooleanArray();
+ setRendererDisableFlagsFromBundle(bundle);
+ }
+
// Video
@Override
@@ -724,12 +789,52 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return clone;
}
+
+ private void setSelectionOverridesFromBundle(Bundle bundle) {
+ @Nullable
+ int[] rendererIndexes =
+ bundle.getIntArray(
+ Parameters.keyForField(Parameters.FIELD_SELECTION_OVERRIDES_RENDERER_INDEXES));
+ List trackGroupArrays =
+ BundleableUtils.fromBundleNullableList(
+ TrackGroupArray.CREATOR,
+ bundle.getParcelableArrayList(
+ Parameters.keyForField(Parameters.FIELD_SELECTION_OVERRIDES_TRACK_GROUP_ARRAYS)),
+ /* defaultValue= */ ImmutableList.of());
+ SparseArray selectionOverrides =
+ BundleableUtils.fromBundleNullableSparseArray(
+ SelectionOverride.CREATOR,
+ bundle.getSparseParcelableArray(
+ Parameters.keyForField(Parameters.FIELD_SELECTION_OVERRIDES)),
+ /* defaultValue= */ new SparseArray<>());
+
+ if (rendererIndexes == null || rendererIndexes.length != trackGroupArrays.size()) {
+ return; // Incorrect format, ignore all overrides.
+ }
+ for (int i = 0; i < rendererIndexes.length; i++) {
+ int rendererIndex = rendererIndexes[i];
+ TrackGroupArray groups = trackGroupArrays.get(i);
+ @Nullable SelectionOverride selectionOverride = selectionOverrides.get(i);
+ setSelectionOverride(rendererIndex, groups, selectionOverride);
+ }
+ }
+
+ private void setRendererDisableFlagsFromBundle(Bundle bundle) {
+ int[] rendererIndexes =
+ bundle.getIntArray(Parameters.keyForField(Parameters.FIELD_RENDERER_DISABLED_INDEXES));
+ if (rendererIndexes == null) {
+ return;
+ }
+ for (int rendererIndex : rendererIndexes) {
+ setRendererDisabled(rendererIndex, true);
+ }
+ }
}
/**
* Extends {@link Parameters} by adding fields that are specific to {@link DefaultTrackSelector}.
*/
- public static final class Parameters extends TrackSelectionParameters implements Parcelable {
+ public static final class Parameters extends TrackSelectionParameters implements Bundleable {
/**
* An instance with default values, except those obtained from the {@link Context}.
@@ -755,19 +860,6 @@ public class DefaultTrackSelector extends MappingTrackSelector {
*/
@Deprecated public static final Parameters DEFAULT = DEFAULT_WITHOUT_CONTEXT;
- public static final Creator CREATOR =
- new Creator() {
-
- @Override
- public Parameters createFromParcel(Parcel in) {
- return new Parameters(in);
- }
-
- @Override
- public Parameters[] newArray(int size) {
- return new Parameters[size];
- }
- };
/**
* Bitmask of selection flags that are disabled for text track selections. See {@link
* C.SelectionFlags}. The default value is {@code 0} (i.e. no flags).
@@ -868,28 +960,6 @@ public class DefaultTrackSelector extends MappingTrackSelector {
rendererDisabledFlags = builder.rendererDisabledFlags;
}
- /* package */ Parameters(Parcel in) {
- super(in);
- // Video
- this.exceedVideoConstraintsIfNecessary = Util.readBoolean(in);
- this.allowVideoMixedMimeTypeAdaptiveness = Util.readBoolean(in);
- this.allowVideoNonSeamlessAdaptiveness = Util.readBoolean(in);
- // Audio
- this.exceedAudioConstraintsIfNecessary = Util.readBoolean(in);
- this.allowAudioMixedMimeTypeAdaptiveness = Util.readBoolean(in);
- this.allowAudioMixedSampleRateAdaptiveness = Util.readBoolean(in);
- this.allowAudioMixedChannelCountAdaptiveness = Util.readBoolean(in);
- // Text
- this.disabledTextTrackSelectionFlags = in.readInt();
- // General
- this.exceedRendererCapabilitiesIfNecessary = Util.readBoolean(in);
- this.tunnelingEnabled = Util.readBoolean(in);
- this.allowMultipleAdaptiveSelections = Util.readBoolean(in);
- // Overrides
- this.selectionOverrides = readSelectionOverrides(in);
- this.rendererDisabledFlags = Util.castNonNull(in.readSparseBooleanArray());
- }
-
/**
* Returns whether the renderer is disabled.
*
@@ -928,6 +998,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
/** Creates a new {@link ParametersBuilder}, copying the initial values from this instance. */
+ @Override
public ParametersBuilder buildUpon() {
return new ParametersBuilder(this);
}
@@ -987,80 +1058,141 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return result;
}
- // Parcelable implementation.
+ // Bundleable implementation.
+
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_EXCEED_VIDEO_CONSTRAINTS_IF_NECESSARY,
+ FIELD_ALLOW_VIDEO_MIXED_MIME_TYPE_ADAPTIVENESS,
+ FIELD_ALLOW_VIDEO_NON_SEAMLESS_ADAPTIVENESS,
+ FIELD_EXCEED_AUDIO_CONSTRAINTS_IF_NCESSARY,
+ FIELD_ALLOW_AUDIO_MIXED_MIME_TYPE_ADAPTIVENESS,
+ FIELD_ALLOW_AUDIO_MIXED_SAMPLE_RATE_ADAPTIVENESS,
+ FIELD_ALLOW_AUDIO_MIXED_CHANNEL_COUNT_ADAPTIVENESS,
+ FIELD_DISABLED_TEXT_TRACK_SELECTION_FLAGS,
+ FIELD_EXCEED_RENDERER_CAPABILITIES_IF_NECESSARY,
+ FIELD_TUNNELING_ENABLED,
+ FIELD_ALLOW_MULTIPLE_ADAPTIVE_SELECTIONS,
+ FIELD_SELECTION_OVERRIDES_RENDERER_INDEXES,
+ FIELD_SELECTION_OVERRIDES_TRACK_GROUP_ARRAYS,
+ FIELD_SELECTION_OVERRIDES,
+ FIELD_RENDERER_DISABLED_INDEXES,
+ })
+ private @interface FieldNumber {}
+
+ // Start at 1000 to avoid conflict with the base class fields.
+ private static final int FIELD_EXCEED_VIDEO_CONSTRAINTS_IF_NECESSARY = 1000;
+ private static final int FIELD_ALLOW_VIDEO_MIXED_MIME_TYPE_ADAPTIVENESS = 1001;
+ private static final int FIELD_ALLOW_VIDEO_NON_SEAMLESS_ADAPTIVENESS = 1002;
+ private static final int FIELD_EXCEED_AUDIO_CONSTRAINTS_IF_NCESSARY = 1003;
+ private static final int FIELD_ALLOW_AUDIO_MIXED_MIME_TYPE_ADAPTIVENESS = 1004;
+ private static final int FIELD_ALLOW_AUDIO_MIXED_SAMPLE_RATE_ADAPTIVENESS = 1005;
+ private static final int FIELD_ALLOW_AUDIO_MIXED_CHANNEL_COUNT_ADAPTIVENESS = 1006;
+ private static final int FIELD_DISABLED_TEXT_TRACK_SELECTION_FLAGS = 1007;
+ private static final int FIELD_EXCEED_RENDERER_CAPABILITIES_IF_NECESSARY = 1008;
+ private static final int FIELD_TUNNELING_ENABLED = 1009;
+ private static final int FIELD_ALLOW_MULTIPLE_ADAPTIVE_SELECTIONS = 1010;
+ private static final int FIELD_SELECTION_OVERRIDES_RENDERER_INDEXES = 1011;
+ private static final int FIELD_SELECTION_OVERRIDES_TRACK_GROUP_ARRAYS = 1012;
+ private static final int FIELD_SELECTION_OVERRIDES = 1013;
+ private static final int FIELD_RENDERER_DISABLED_INDEXES = 1014;
@Override
- public int describeContents() {
- return 0;
- }
+ public Bundle toBundle() {
+ Bundle bundle = super.toBundle();
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
// Video
- Util.writeBoolean(dest, exceedVideoConstraintsIfNecessary);
- Util.writeBoolean(dest, allowVideoMixedMimeTypeAdaptiveness);
- Util.writeBoolean(dest, allowVideoNonSeamlessAdaptiveness);
+ bundle.putBoolean(
+ keyForField(FIELD_EXCEED_VIDEO_CONSTRAINTS_IF_NECESSARY),
+ exceedVideoConstraintsIfNecessary);
+ bundle.putBoolean(
+ keyForField(FIELD_ALLOW_VIDEO_MIXED_MIME_TYPE_ADAPTIVENESS),
+ allowVideoMixedMimeTypeAdaptiveness);
+ bundle.putBoolean(
+ keyForField(FIELD_ALLOW_VIDEO_NON_SEAMLESS_ADAPTIVENESS),
+ allowVideoNonSeamlessAdaptiveness);
// Audio
- Util.writeBoolean(dest, exceedAudioConstraintsIfNecessary);
- Util.writeBoolean(dest, allowAudioMixedMimeTypeAdaptiveness);
- Util.writeBoolean(dest, allowAudioMixedSampleRateAdaptiveness);
- Util.writeBoolean(dest, allowAudioMixedChannelCountAdaptiveness);
+ bundle.putBoolean(
+ keyForField(FIELD_EXCEED_AUDIO_CONSTRAINTS_IF_NCESSARY),
+ exceedAudioConstraintsIfNecessary);
+ bundle.putBoolean(
+ keyForField(FIELD_ALLOW_AUDIO_MIXED_MIME_TYPE_ADAPTIVENESS),
+ allowAudioMixedMimeTypeAdaptiveness);
+ bundle.putBoolean(
+ keyForField(FIELD_ALLOW_AUDIO_MIXED_SAMPLE_RATE_ADAPTIVENESS),
+ allowAudioMixedSampleRateAdaptiveness);
+ bundle.putBoolean(
+ keyForField(FIELD_ALLOW_AUDIO_MIXED_CHANNEL_COUNT_ADAPTIVENESS),
+ allowAudioMixedChannelCountAdaptiveness);
// Text
- dest.writeInt(disabledTextTrackSelectionFlags);
+ bundle.putInt(
+ keyForField(FIELD_DISABLED_TEXT_TRACK_SELECTION_FLAGS), disabledTextTrackSelectionFlags);
// General
- Util.writeBoolean(dest, exceedRendererCapabilitiesIfNecessary);
- Util.writeBoolean(dest, tunnelingEnabled);
- Util.writeBoolean(dest, allowMultipleAdaptiveSelections);
- // Overrides
- writeSelectionOverridesToParcel(dest, selectionOverrides);
- dest.writeSparseBooleanArray(rendererDisabledFlags);
+ bundle.putBoolean(
+ keyForField(FIELD_EXCEED_RENDERER_CAPABILITIES_IF_NECESSARY),
+ exceedRendererCapabilitiesIfNecessary);
+ bundle.putBoolean(keyForField(FIELD_TUNNELING_ENABLED), tunnelingEnabled);
+ bundle.putBoolean(
+ keyForField(FIELD_ALLOW_MULTIPLE_ADAPTIVE_SELECTIONS), allowMultipleAdaptiveSelections);
+
+ putSelectionOverridesToBundle(bundle, selectionOverrides);
+ putRendererDisabledFlagsToBundle(bundle, rendererDisabledFlags);
+
+ return bundle;
}
- // Static utility methods.
+ /** Object that can restore {@code Parameters} from a {@link Bundle}. */
+ public static final Creator CREATOR =
+ bundle -> new ParametersBuilder(bundle).build();
- private static SparseArray