mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Implement Bundleable for AdPlaybackState
PiperOrigin-RevId: 361731578
This commit is contained in:
parent
bc9fb8615e
commit
6f9dbfe0c1
2 changed files with 125 additions and 27 deletions
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.ads;
|
package com.google.android.exoplayer2.source.ads;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -24,7 +25,6 @@ import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.Bundleable;
|
import com.google.android.exoplayer2.Bundleable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
|
@ -39,7 +39,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
* <p>Instances are immutable. Call the {@code with*} methods to get new instances that have the
|
* <p>Instances are immutable. Call the {@code with*} methods to get new instances that have the
|
||||||
* required changes.
|
* required changes.
|
||||||
*/
|
*/
|
||||||
public final class AdPlaybackState {
|
public final class AdPlaybackState implements Bundleable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a group of ads, with information about their states.
|
* Represents a group of ads, with information about their states.
|
||||||
|
|
@ -69,7 +69,7 @@ public final class AdPlaybackState {
|
||||||
|
|
||||||
private AdGroup(
|
private AdGroup(
|
||||||
int count, @AdState int[] states, @NullableType Uri[] uris, long[] durationsUs) {
|
int count, @AdState int[] states, @NullableType Uri[] uris, long[] durationsUs) {
|
||||||
Assertions.checkArgument(states.length == uris.length);
|
checkArgument(states.length == uris.length);
|
||||||
this.count = count;
|
this.count = count;
|
||||||
this.states = states;
|
this.states = states;
|
||||||
this.uris = uris;
|
this.uris = uris;
|
||||||
|
|
@ -165,9 +165,9 @@ public final class AdPlaybackState {
|
||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdGroup withAdState(@AdState int state, int index) {
|
public AdGroup withAdState(@AdState int state, int index) {
|
||||||
Assertions.checkArgument(count == C.LENGTH_UNSET || index < count);
|
checkArgument(count == C.LENGTH_UNSET || index < count);
|
||||||
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, index + 1);
|
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, index + 1);
|
||||||
Assertions.checkArgument(
|
checkArgument(
|
||||||
states[index] == AD_STATE_UNAVAILABLE
|
states[index] == AD_STATE_UNAVAILABLE
|
||||||
|| states[index] == AD_STATE_AVAILABLE
|
|| states[index] == AD_STATE_AVAILABLE
|
||||||
|| states[index] == state);
|
|| states[index] == state);
|
||||||
|
|
@ -260,28 +260,24 @@ public final class AdPlaybackState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Object that can restore {@link AdGroup} from a {@link Bundle}. */
|
/** Object that can restore {@link AdGroup} from a {@link Bundle}. */
|
||||||
public static final Creator<AdGroup> CREATOR =
|
public static final Creator<AdGroup> CREATOR = AdGroup::fromBundle;
|
||||||
new Creator<AdGroup>() {
|
|
||||||
|
|
||||||
// getParcelableArrayList may have null elements.
|
// getParcelableArrayList may have null elements.
|
||||||
@SuppressWarnings("nullness:type.argument.type.incompatible")
|
@SuppressWarnings("nullness:type.argument.type.incompatible")
|
||||||
@Override
|
private static AdGroup fromBundle(Bundle bundle) {
|
||||||
public AdGroup fromBundle(Bundle bundle) {
|
int count = bundle.getInt(keyForField(FIELD_COUNT), /* defaultValue= */ C.LENGTH_UNSET);
|
||||||
int count = bundle.getInt(keyForField(FIELD_COUNT), /* defaultValue= */ C.LENGTH_UNSET);
|
@Nullable
|
||||||
@Nullable
|
ArrayList<@NullableType Uri> uriList = bundle.getParcelableArrayList(keyForField(FIELD_URIS));
|
||||||
ArrayList<@NullableType Uri> uriList =
|
@Nullable
|
||||||
bundle.getParcelableArrayList(keyForField(FIELD_URIS));
|
@AdState
|
||||||
@Nullable
|
int[] states = bundle.getIntArray(keyForField(FIELD_STATES));
|
||||||
@AdState
|
@Nullable long[] durationsUs = bundle.getLongArray(keyForField(FIELD_DURATIONS_US));
|
||||||
int[] states = bundle.getIntArray(keyForField(FIELD_STATES));
|
return new AdGroup(
|
||||||
@Nullable long[] durationsUs = bundle.getLongArray(keyForField(FIELD_DURATIONS_US));
|
count,
|
||||||
return new AdGroup(
|
states == null ? new int[0] : states,
|
||||||
count,
|
uriList == null ? new Uri[0] : uriList.toArray(new Uri[0]),
|
||||||
states == null ? new int[0] : states,
|
durationsUs == null ? new long[0] : durationsUs);
|
||||||
uriList == null ? new Uri[0] : uriList.toArray(new Uri[0]),
|
}
|
||||||
durationsUs == null ? new long[0] : durationsUs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static String keyForField(@AdGroup.FieldNumber int field) {
|
private static String keyForField(@AdGroup.FieldNumber int field) {
|
||||||
return Integer.toString(field, Character.MAX_RADIX);
|
return Integer.toString(field, Character.MAX_RADIX);
|
||||||
|
|
@ -368,6 +364,7 @@ public final class AdPlaybackState {
|
||||||
@Nullable AdGroup[] adGroups,
|
@Nullable AdGroup[] adGroups,
|
||||||
long adResumePositionUs,
|
long adResumePositionUs,
|
||||||
long contentDurationUs) {
|
long contentDurationUs) {
|
||||||
|
checkArgument(adGroups == null || adGroups.length == adGroupTimesUs.length);
|
||||||
this.adsId = adsId;
|
this.adsId = adsId;
|
||||||
this.adGroupTimesUs = adGroupTimesUs;
|
this.adGroupTimesUs = adGroupTimesUs;
|
||||||
this.adResumePositionUs = adResumePositionUs;
|
this.adResumePositionUs = adResumePositionUs;
|
||||||
|
|
@ -449,7 +446,7 @@ public final class AdPlaybackState {
|
||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withAdCount(int adGroupIndex, int adCount) {
|
public AdPlaybackState withAdCount(int adGroupIndex, int adCount) {
|
||||||
Assertions.checkArgument(adCount > 0);
|
checkArgument(adCount > 0);
|
||||||
if (adGroups[adGroupIndex].count == adCount) {
|
if (adGroups[adGroupIndex].count == adCount) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
@ -634,4 +631,79 @@ public final class AdPlaybackState {
|
||||||
return positionUs < adGroupPositionUs;
|
return positionUs < adGroupPositionUs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bundleable implementation.
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({
|
||||||
|
FIELD_AD_GROUP_TIMES_US,
|
||||||
|
FIELD_AD_GROUPS,
|
||||||
|
FIELD_AD_RESUME_POSITION_US,
|
||||||
|
FIELD_CONTENT_DURATION_US
|
||||||
|
})
|
||||||
|
private @interface FieldNumber {}
|
||||||
|
|
||||||
|
private static final int FIELD_AD_GROUP_TIMES_US = 1;
|
||||||
|
private static final int FIELD_AD_GROUPS = 2;
|
||||||
|
private static final int FIELD_AD_RESUME_POSITION_US = 3;
|
||||||
|
private static final int FIELD_CONTENT_DURATION_US = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>It omits the {@link #adsId} field so the {@link #adsId} of instances restored by {@link
|
||||||
|
* #CREATOR} will always be {@code null}.
|
||||||
|
*/
|
||||||
|
// TODO(b/166765820): See if missing adsId would be okay and add adsId to the Bundle otherwise.
|
||||||
|
@Override
|
||||||
|
public Bundle toBundle() {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putLongArray(keyForField(FIELD_AD_GROUP_TIMES_US), adGroupTimesUs);
|
||||||
|
ArrayList<Bundle> adGroupBundleList = new ArrayList<>();
|
||||||
|
for (AdGroup adGroup : adGroups) {
|
||||||
|
adGroupBundleList.add(adGroup.toBundle());
|
||||||
|
}
|
||||||
|
bundle.putParcelableArrayList(keyForField(FIELD_AD_GROUPS), adGroupBundleList);
|
||||||
|
bundle.putLong(keyForField(FIELD_AD_RESUME_POSITION_US), adResumePositionUs);
|
||||||
|
bundle.putLong(keyForField(FIELD_CONTENT_DURATION_US), contentDurationUs);
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object that can restore {@link AdPlaybackState} from a {@link Bundle}.
|
||||||
|
*
|
||||||
|
* <p>The {@link #adsId} of restored instances will always be {@code null}.
|
||||||
|
*/
|
||||||
|
public static final Bundleable.Creator<AdPlaybackState> CREATOR = AdPlaybackState::fromBundle;
|
||||||
|
|
||||||
|
private static AdPlaybackState fromBundle(Bundle bundle) {
|
||||||
|
@Nullable long[] adGroupTimesUs = bundle.getLongArray(keyForField(FIELD_AD_GROUP_TIMES_US));
|
||||||
|
@Nullable
|
||||||
|
ArrayList<Bundle> adGroupBundleList =
|
||||||
|
bundle.getParcelableArrayList(keyForField(FIELD_AD_GROUPS));
|
||||||
|
@Nullable AdGroup[] adGroups;
|
||||||
|
if (adGroupBundleList == null) {
|
||||||
|
adGroups = null;
|
||||||
|
} else {
|
||||||
|
adGroups = new AdGroup[adGroupBundleList.size()];
|
||||||
|
for (int i = 0; i < adGroupBundleList.size(); i++) {
|
||||||
|
adGroups[i] = AdGroup.CREATOR.fromBundle(adGroupBundleList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long adResumePositionUs =
|
||||||
|
bundle.getLong(keyForField(FIELD_AD_RESUME_POSITION_US), /* defaultValue= */ 0);
|
||||||
|
long contentDurationUs =
|
||||||
|
bundle.getLong(keyForField(FIELD_CONTENT_DURATION_US), /* defaultValue= */ C.TIME_UNSET);
|
||||||
|
return new AdPlaybackState(
|
||||||
|
/* adsId= */ null,
|
||||||
|
adGroupTimesUs == null ? new long[0] : adGroupTimesUs,
|
||||||
|
adGroups,
|
||||||
|
adResumePositionUs,
|
||||||
|
contentDurationUs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String keyForField(@FieldNumber int field) {
|
||||||
|
return Integer.toString(field, Character.MAX_RADIX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,32 @@ public class AdPlaybackStateTest {
|
||||||
assertThat(state.adGroups[1].count).isEqualTo(0);
|
assertThat(state.adGroups[1].count).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void roundtripViaBundle_yieldsEqualFieldsExceptAdsId() {
|
||||||
|
AdPlaybackState originalState =
|
||||||
|
state
|
||||||
|
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
|
||||||
|
.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)
|
||||||
|
.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI)
|
||||||
|
.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 2)
|
||||||
|
.withSkippedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0)
|
||||||
|
.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1)
|
||||||
|
.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_URI)
|
||||||
|
.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI)
|
||||||
|
.withAdDurationsUs(new long[][] {{12}, {34, 56}})
|
||||||
|
.withAdResumePositionUs(123)
|
||||||
|
.withContentDurationUs(456);
|
||||||
|
|
||||||
|
AdPlaybackState restoredState = AdPlaybackState.CREATOR.fromBundle(originalState.toBundle());
|
||||||
|
|
||||||
|
assertThat(restoredState.adsId).isNull();
|
||||||
|
assertThat(restoredState.adGroupCount).isEqualTo(originalState.adGroupCount);
|
||||||
|
assertThat(restoredState.adGroupTimesUs).isEqualTo(originalState.adGroupTimesUs);
|
||||||
|
assertThat(restoredState.adGroups).isEqualTo(originalState.adGroups);
|
||||||
|
assertThat(restoredState.adResumePositionUs).isEqualTo(originalState.adResumePositionUs);
|
||||||
|
assertThat(restoredState.contentDurationUs).isEqualTo(originalState.contentDurationUs);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void roundtripViaBundle_ofAdGroup_yieldsEqualInstance() {
|
public void roundtripViaBundle_ofAdGroup_yieldsEqualInstance() {
|
||||||
AdPlaybackState.AdGroup adGroup =
|
AdPlaybackState.AdGroup adGroup =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue