diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Player.java b/library/common/src/main/java/com/google/android/exoplayer2/Player.java
index 7e6aaece17..5ced18a108 100644
--- a/library/common/src/main/java/com/google/android/exoplayer2/Player.java
+++ b/library/common/src/main/java/com/google/android/exoplayer2/Player.java
@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2;
+import android.os.Bundle;
import android.os.Looper;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -529,7 +530,7 @@ public interface Player {
}
/** Position info describing a playback position involved in a discontinuity. */
- final class PositionInfo {
+ final class PositionInfo implements Bundleable {
/**
* The UID of the window, or {@code null}, if the timeline is {@link Timeline#isEmpty() empty}.
@@ -614,6 +615,75 @@ public interface Player {
adGroupIndex,
adIndexInAdGroup);
}
+
+ // Bundleable implementation.
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ FIELD_WINDOW_INDEX,
+ FIELD_PERIOD_INDEX,
+ FIELD_POSITION_MS,
+ FIELD_CONTENT_POSITION_MS,
+ FIELD_AD_GROUP_INDEX,
+ FIELD_AD_INDEX_IN_AD_GROUP
+ })
+ private @interface FieldNumber {}
+
+ private static final int FIELD_WINDOW_INDEX = 0;
+ private static final int FIELD_PERIOD_INDEX = 1;
+ private static final int FIELD_POSITION_MS = 2;
+ private static final int FIELD_CONTENT_POSITION_MS = 3;
+ private static final int FIELD_AD_GROUP_INDEX = 4;
+ private static final int FIELD_AD_INDEX_IN_AD_GROUP = 5;
+
+ /**
+ * {@inheritDoc}
+ *
+ *
It omits the {@link #windowUid} and {@link #periodUid} fields. The {@link #windowUid} and
+ * {@link #periodUid} of an instance restored by {@link #CREATOR} will always be {@code null}.
+ */
+ @Override
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putInt(keyForField(FIELD_WINDOW_INDEX), windowIndex);
+ bundle.putInt(keyForField(FIELD_PERIOD_INDEX), periodIndex);
+ bundle.putLong(keyForField(FIELD_POSITION_MS), positionMs);
+ bundle.putLong(keyForField(FIELD_CONTENT_POSITION_MS), contentPositionMs);
+ bundle.putInt(keyForField(FIELD_AD_GROUP_INDEX), adGroupIndex);
+ bundle.putInt(keyForField(FIELD_AD_INDEX_IN_AD_GROUP), adIndexInAdGroup);
+ return bundle;
+ }
+
+ /** Object that can restore {@link PositionInfo} from a {@link Bundle}. */
+ public static final Creator CREATOR = PositionInfo::fromBundle;
+
+ private static PositionInfo fromBundle(Bundle bundle) {
+ int windowIndex =
+ bundle.getInt(keyForField(FIELD_WINDOW_INDEX), /* defaultValue= */ C.INDEX_UNSET);
+ int periodIndex =
+ bundle.getInt(keyForField(FIELD_PERIOD_INDEX), /* defaultValue= */ C.INDEX_UNSET);
+ long positionMs =
+ bundle.getLong(keyForField(FIELD_POSITION_MS), /* defaultValue= */ C.TIME_UNSET);
+ long contentPositionMs =
+ bundle.getLong(keyForField(FIELD_CONTENT_POSITION_MS), /* defaultValue= */ C.TIME_UNSET);
+ int adGroupIndex =
+ bundle.getInt(keyForField(FIELD_AD_GROUP_INDEX), /* defaultValue= */ C.INDEX_UNSET);
+ int adIndexInAdGroup =
+ bundle.getInt(keyForField(FIELD_AD_INDEX_IN_AD_GROUP), /* defaultValue= */ C.INDEX_UNSET);
+ return new PositionInfo(
+ /* windowUid= */ null,
+ windowIndex,
+ /* periodUid= */ null,
+ periodIndex,
+ positionMs,
+ contentPositionMs,
+ adGroupIndex,
+ adIndexInAdGroup);
+ }
+
+ 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/PositionInfoTest.java b/library/common/src/test/java/com/google/android/exoplayer2/PositionInfoTest.java
new file mode 100644
index 0000000000..c86bd0ae38
--- /dev/null
+++ b/library/common/src/test/java/com/google/android/exoplayer2/PositionInfoTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2021 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 com.google.android.exoplayer2;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.google.android.exoplayer2.Player.PositionInfo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link Player.PositionInfo}. */
+@RunWith(AndroidJUnit4.class)
+public class PositionInfoTest {
+
+ @Test
+ public void roundtripViaBundle_ofPositionInfoWithoutObjectFields_yieldsEqualInstance() {
+ PositionInfo positionInfo =
+ new PositionInfo(
+ /* windowUid= */ null,
+ /* windowIndex= */ 23,
+ /* periodUid= */ null,
+ /* periodIndex= */ 11,
+ /* positionMs= */ 8787L,
+ /* contentPositionMs= */ 12L,
+ /* adGroupIndex= */ 2,
+ /* adIndexInAdGroup= */ 444);
+
+ assertThat(PositionInfo.CREATOR.fromBundle(positionInfo.toBundle())).isEqualTo(positionInfo);
+ }
+
+ @Test
+ public void roundtripViaBundle_ofPositionInfoWithWindowUid_yieldsNullWindowUid() {
+ PositionInfo positionInfo =
+ new PositionInfo(
+ /* windowUid= */ new Object(),
+ /* windowIndex= */ 23,
+ /* periodUid= */ null,
+ /* periodIndex= */ 11,
+ /* positionMs= */ 8787L,
+ /* contentPositionMs= */ 12L,
+ /* adGroupIndex= */ 2,
+ /* adIndexInAdGroup= */ 444);
+
+ PositionInfo positionInfoFromBundle = PositionInfo.CREATOR.fromBundle(positionInfo.toBundle());
+ assertThat(positionInfoFromBundle.windowUid).isNull();
+ }
+
+ @Test
+ public void roundtripViaBundle_ofPositionInfoWithPeriodUid_yieldsNullPeriodUid() {
+ PositionInfo positionInfo =
+ new PositionInfo(
+ /* windowUid= */ null,
+ /* windowIndex= */ 23,
+ /* periodUid= */ new Object(),
+ /* periodIndex= */ 11,
+ /* positionMs= */ 8787L,
+ /* contentPositionMs= */ 12L,
+ /* adGroupIndex= */ 2,
+ /* adIndexInAdGroup= */ 444);
+
+ PositionInfo positionInfoFromBundle = PositionInfo.CREATOR.fromBundle(positionInfo.toBundle());
+ assertThat(positionInfoFromBundle.periodUid).isNull();
+ }
+}