mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add adId to AdGroup
PiperOrigin-RevId: 706761644
This commit is contained in:
parent
d5d85558c1
commit
3fe1f2a734
@ -41,6 +41,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents ad group times and information on the state and URIs of ads within each ad group.
|
||||
@ -90,6 +91,9 @@ public final class AdPlaybackState {
|
||||
/** The durations of each ad in the ad group, in microseconds. */
|
||||
public final long[] durationsUs;
|
||||
|
||||
/** The optional IDs of the ads. */
|
||||
public final @NullableType String[] ids;
|
||||
|
||||
/**
|
||||
* The offset in microseconds which should be added to the content stream when resuming playback
|
||||
* after the ad group.
|
||||
@ -114,7 +118,8 @@ public final class AdPlaybackState {
|
||||
/* mediaItems= */ new MediaItem[0],
|
||||
/* durationsUs= */ new long[0],
|
||||
/* contentResumeOffsetUs= */ 0,
|
||||
/* isServerSideInserted= */ false);
|
||||
/* isServerSideInserted= */ false,
|
||||
/* ids= */ new String[0]);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Intentionally assigning deprecated field
|
||||
@ -126,7 +131,8 @@ public final class AdPlaybackState {
|
||||
@NullableType MediaItem[] mediaItems,
|
||||
long[] durationsUs,
|
||||
long contentResumeOffsetUs,
|
||||
boolean isServerSideInserted) {
|
||||
boolean isServerSideInserted,
|
||||
@NullableType String[] ids) {
|
||||
checkArgument(states.length == mediaItems.length);
|
||||
this.timeUs = timeUs;
|
||||
this.count = count;
|
||||
@ -140,6 +146,7 @@ public final class AdPlaybackState {
|
||||
for (int i = 0; i < uris.length; i++) {
|
||||
uris[i] = mediaItems[i] == null ? null : checkNotNull(mediaItems[i].localConfiguration).uri;
|
||||
}
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,7 +218,8 @@ public final class AdPlaybackState {
|
||||
&& Arrays.equals(states, adGroup.states)
|
||||
&& Arrays.equals(durationsUs, adGroup.durationsUs)
|
||||
&& contentResumeOffsetUs == adGroup.contentResumeOffsetUs
|
||||
&& isServerSideInserted == adGroup.isServerSideInserted;
|
||||
&& isServerSideInserted == adGroup.isServerSideInserted
|
||||
&& Arrays.equals(ids, adGroup.ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -224,6 +232,7 @@ public final class AdPlaybackState {
|
||||
result = 31 * result + Arrays.hashCode(durationsUs);
|
||||
result = 31 * result + (int) (contentResumeOffsetUs ^ (contentResumeOffsetUs >>> 32));
|
||||
result = 31 * result + (isServerSideInserted ? 1 : 0);
|
||||
result = 31 * result + Arrays.hashCode(ids);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -238,7 +247,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Returns a new instance with the ad count set to {@code count}. */
|
||||
@ -247,6 +257,7 @@ public final class AdPlaybackState {
|
||||
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count);
|
||||
long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count);
|
||||
@NullableType MediaItem[] mediaItems = Arrays.copyOf(this.mediaItems, count);
|
||||
@NullableType String[] ids = Arrays.copyOf(this.ids, count);
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
count,
|
||||
@ -255,7 +266,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,6 +293,9 @@ public final class AdPlaybackState {
|
||||
@NullableType MediaItem[] mediaItems = Arrays.copyOf(this.mediaItems, states.length);
|
||||
mediaItems[index] = mediaItem;
|
||||
states[index] = AD_STATE_AVAILABLE;
|
||||
@NullableType
|
||||
String[] ids =
|
||||
this.ids.length == states.length ? this.ids : Arrays.copyOf(this.ids, states.length);
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
count,
|
||||
@ -289,7 +304,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,6 +333,9 @@ public final class AdPlaybackState {
|
||||
this.mediaItems.length == states.length
|
||||
? this.mediaItems
|
||||
: Arrays.copyOf(this.mediaItems, states.length);
|
||||
@NullableType
|
||||
String[] ids =
|
||||
this.ids.length == states.length ? this.ids : Arrays.copyOf(this.ids, states.length);
|
||||
states[index] = state;
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
@ -326,7 +345,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Returns a new instance with the specified ad durations, in microseconds. */
|
||||
@ -345,7 +365,37 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Returns a new instance with the specified ID for the given ad index. */
|
||||
@CheckResult
|
||||
public AdGroup withAdId(String adId, @IntRange(from = 0) int index) {
|
||||
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, index + 1);
|
||||
long[] durationsUs =
|
||||
this.durationsUs.length == states.length
|
||||
? this.durationsUs
|
||||
: copyDurationsUsWithSpaceForAdCount(this.durationsUs, states.length);
|
||||
@NullableType
|
||||
MediaItem[] mediaItems =
|
||||
this.mediaItems.length == states.length
|
||||
? this.mediaItems
|
||||
: Arrays.copyOf(this.mediaItems, states.length);
|
||||
@NullableType
|
||||
String[] ids =
|
||||
this.ids.length == states.length ? this.ids : Arrays.copyOf(this.ids, states.length);
|
||||
ids[index] = adId;
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
count,
|
||||
originalCount,
|
||||
states,
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified {@link #contentResumeOffsetUs}. */
|
||||
@ -359,7 +409,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified value for {@link #isServerSideInserted}. */
|
||||
@ -373,7 +424,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified value for {@link #originalCount}. */
|
||||
@ -386,7 +438,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/** Removes the last ad from the ad group. */
|
||||
@ -398,6 +451,7 @@ public final class AdPlaybackState {
|
||||
if (durationsUs.length > newCount) {
|
||||
newDurationsUs = Arrays.copyOf(durationsUs, newCount);
|
||||
}
|
||||
@NullableType String[] newIds = Arrays.copyOf(ids, newCount);
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
newCount,
|
||||
@ -406,7 +460,8 @@ public final class AdPlaybackState {
|
||||
newMediaItems,
|
||||
newDurationsUs,
|
||||
/* contentResumeOffsetUs= */ Util.sum(newDurationsUs),
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
newIds);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -424,7 +479,8 @@ public final class AdPlaybackState {
|
||||
/* mediaItems= */ new MediaItem[0],
|
||||
/* durationsUs= */ new long[0],
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
int count = this.states.length;
|
||||
@AdState int[] states = Arrays.copyOf(this.states, count);
|
||||
@ -441,7 +497,8 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,7 +527,21 @@ public final class AdPlaybackState {
|
||||
mediaItems,
|
||||
durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the ad with the given ad ID, or {@link C#INDEX_UNSET} if the ad ID can't
|
||||
* be found.
|
||||
*/
|
||||
public int getIndexOfAdId(String adId) {
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
if (Objects.equals(ids[i], adId)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@ -500,6 +571,7 @@ public final class AdPlaybackState {
|
||||
private static final String FIELD_IS_SERVER_SIDE_INSERTED = Util.intToStringMaxRadix(6);
|
||||
private static final String FIELD_ORIGINAL_COUNT = Util.intToStringMaxRadix(7);
|
||||
@VisibleForTesting static final String FIELD_MEDIA_ITEMS = Util.intToStringMaxRadix(8);
|
||||
static final String FIELD_IDS = Util.intToStringMaxRadix(9);
|
||||
|
||||
// Intentionally assigning deprecated field.
|
||||
// putParcelableArrayList actually supports null elements.
|
||||
@ -516,6 +588,7 @@ public final class AdPlaybackState {
|
||||
bundle.putLongArray(FIELD_DURATIONS_US, durationsUs);
|
||||
bundle.putLong(FIELD_CONTENT_RESUME_OFFSET_US, contentResumeOffsetUs);
|
||||
bundle.putBoolean(FIELD_IS_SERVER_SIDE_INSERTED, isServerSideInserted);
|
||||
bundle.putStringArrayList(FIELD_IDS, new ArrayList<>(Arrays.asList(ids)));
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@ -536,6 +609,7 @@ public final class AdPlaybackState {
|
||||
@Nullable long[] durationsUs = bundle.getLongArray(FIELD_DURATIONS_US);
|
||||
long contentResumeOffsetUs = bundle.getLong(FIELD_CONTENT_RESUME_OFFSET_US);
|
||||
boolean isServerSideInserted = bundle.getBoolean(FIELD_IS_SERVER_SIDE_INSERTED);
|
||||
@Nullable ArrayList<String> ids = bundle.getStringArrayList(FIELD_IDS);
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
count,
|
||||
@ -544,7 +618,8 @@ public final class AdPlaybackState {
|
||||
getMediaItemsFromBundleArrays(mediaItemBundleList, uriList),
|
||||
durationsUs == null ? new long[0] : durationsUs,
|
||||
contentResumeOffsetUs,
|
||||
isServerSideInserted);
|
||||
isServerSideInserted,
|
||||
ids == null ? new String[0] : ids.toArray(new String[0]));
|
||||
}
|
||||
|
||||
private ArrayList<@NullableType Bundle> getMediaItemsArrayBundles() {
|
||||
@ -914,6 +989,17 @@ public final class AdPlaybackState {
|
||||
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified ad ID for the given ad. */
|
||||
@CheckResult
|
||||
public AdPlaybackState withAdId(
|
||||
@IntRange(from = 0) int adGroupIndex, @IntRange(from = 0) int adIndexInAdGroup, String adId) {
|
||||
int adjustedIndex = adGroupIndex - removedAdGroupCount;
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adjustedIndex] = adGroups[adjustedIndex].withAdId(adId, adIndexInAdGroup);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance with all ads in the specified ad group skipped (except for those already
|
||||
* marked as played or in the error state).
|
||||
@ -1074,7 +1160,7 @@ public final class AdPlaybackState {
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a live postroll placeholder ad group to the ad playback state.
|
||||
* Appends a live post roll placeholder ad group to the ad playback state.
|
||||
*
|
||||
* <p>Adding such a placeholder is only required for periods of server side ad insertion live
|
||||
* streams. A player is not expected to play this placeholder. It is only used to indicate that
|
||||
@ -1110,6 +1196,18 @@ public final class AdPlaybackState {
|
||||
return adGroupIndex == adGroupCount - 1 && getAdGroup(adGroupIndex).isLivePostrollPlaceholder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the ad with the given ad ID in the given ad group, or {@link
|
||||
* C#INDEX_UNSET} if the ad ID can't be found.
|
||||
*
|
||||
* @param adGroupIndex The ad group index.
|
||||
* @param adId The ad ID.
|
||||
* @return The ad index in the ad group, or {@link C#INDEX_UNSET} if the ad ID is not found.
|
||||
*/
|
||||
public int getAdIndexOfAdId(int adGroupIndex, String adId) {
|
||||
return getAdGroup(adGroupIndex).getIndexOfAdId(adId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the ad playback state with the given ads ID.
|
||||
*
|
||||
@ -1131,7 +1229,8 @@ public final class AdPlaybackState {
|
||||
Arrays.copyOf(adGroup.mediaItems, adGroup.mediaItems.length),
|
||||
Arrays.copyOf(adGroup.durationsUs, adGroup.durationsUs.length),
|
||||
adGroup.contentResumeOffsetUs,
|
||||
adGroup.isServerSideInserted);
|
||||
adGroup.isServerSideInserted,
|
||||
adGroup.ids);
|
||||
}
|
||||
return new AdPlaybackState(
|
||||
adsId,
|
||||
|
@ -44,9 +44,18 @@ public class AdPlaybackStateTest {
|
||||
new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US).withRemovedAdGroupCount(1);
|
||||
|
||||
assertThat(state.getAdGroup(1).count).isEqualTo(C.LENGTH_UNSET);
|
||||
state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1);
|
||||
assertThat(state.getAdGroup(1).states).hasLength(0);
|
||||
assertThat(state.getAdGroup(1).mediaItems).hasLength(0);
|
||||
assertThat(state.getAdGroup(1).durationsUs).hasLength(0);
|
||||
assertThat(state.getAdGroup(1).ids).hasLength(0);
|
||||
|
||||
assertThat(state.getAdGroup(1).count).isEqualTo(1);
|
||||
state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 4);
|
||||
|
||||
assertThat(state.getAdGroup(1).count).isEqualTo(4);
|
||||
assertThat(state.getAdGroup(1).states).hasLength(4);
|
||||
assertThat(state.getAdGroup(1).mediaItems).hasLength(4);
|
||||
assertThat(state.getAdGroup(1).durationsUs).hasLength(4);
|
||||
assertThat(state.getAdGroup(1).ids).hasLength(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -488,9 +497,12 @@ public class AdPlaybackStateTest {
|
||||
.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0)
|
||||
.withAvailableAdMediaItem(
|
||||
/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, TEST_MEDIA_ITEM)
|
||||
.withAdId(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, "ad-1-0")
|
||||
.withAdCount(/* adGroupIndex= */ 2, /* adCount= */ 2)
|
||||
.withSkippedAd(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0)
|
||||
.withPlayedAd(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1)
|
||||
.withAdId(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, "ad-2-0")
|
||||
.withAdId(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, "ad-2-1")
|
||||
.withAvailableAdMediaItem(
|
||||
/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, TEST_MEDIA_ITEM)
|
||||
.withAvailableAdMediaItem(
|
||||
@ -528,7 +540,9 @@ public class AdPlaybackStateTest {
|
||||
.withAdMediaItem(new MediaItem.Builder().setUri(Uri.EMPTY).build(), /* index= */ 1)
|
||||
.withAdDurationsUs(new long[] {1234, 5678})
|
||||
.withContentResumeOffsetUs(4444)
|
||||
.withIsServerSideInserted(true);
|
||||
.withIsServerSideInserted(true)
|
||||
.withAdId("id-0", 0)
|
||||
.withAdId("id-1", 1);
|
||||
|
||||
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle())).isEqualTo(adGroup);
|
||||
}
|
||||
@ -540,6 +554,8 @@ public class AdPlaybackStateTest {
|
||||
.withAdCount(2)
|
||||
.withAdState(AD_STATE_AVAILABLE, /* index= */ 0)
|
||||
.withAdState(AD_STATE_PLAYED, /* index= */ 1)
|
||||
.withAdId("ad-0", /* index= */ 1)
|
||||
.withAdId("ad-1", /* index= */ 1)
|
||||
.withAdMediaItem(
|
||||
new MediaItem.Builder().setUri("https://www.google.com").build(), /* index= */ 0)
|
||||
.withAdMediaItem(new MediaItem.Builder().setUri(Uri.EMPTY).build(), /* index= */ 1)
|
||||
@ -857,4 +873,39 @@ public class AdPlaybackStateTest {
|
||||
/* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ C.TIME_UNSET))
|
||||
.isEqualTo(C.INDEX_UNSET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAdIndexOfAdId() {
|
||||
AdPlaybackState state =
|
||||
new AdPlaybackState("adsId", /* adGroupTimesUs...= */ 0L, 1L, 2L)
|
||||
.withAdCount(0, 1)
|
||||
.withAdCount(1, 3)
|
||||
.withAdCount(2, 2)
|
||||
.withAdId(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, "ad-0-0")
|
||||
.withAdId(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 0, "ad-1-0")
|
||||
.withAdId(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, "ad-1-2")
|
||||
.withAdId(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 0, "ad-2-0")
|
||||
.withAdId(/* adGroupIndex= */ 2, /* adIndexInAdGroup= */ 1, "ad-2-1")
|
||||
.withRemovedAdGroupCount(/* removedAdGroupCount= */ 1);
|
||||
|
||||
assertThat(state.getAdIndexOfAdId(/* adGroupIndex= */ 0, "ad-0-0")).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.getAdIndexOfAdId(/* adGroupIndex= */ 1, "ad-1-0")).isEqualTo(0);
|
||||
assertThat(state.getAdIndexOfAdId(/* adGroupIndex= */ 1, "ad-1-1")).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.getAdIndexOfAdId(/* adGroupIndex= */ 1, "ad-1-2")).isEqualTo(2);
|
||||
assertThat(state.getAdIndexOfAdId(/* adGroupIndex= */ 2, "ad-2-0")).isEqualTo(0);
|
||||
assertThat(state.getAdIndexOfAdId(/* adGroupIndex= */ 2, "ad-2-1")).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromBundle_withNullElements_correctlyBundledUnbundled() {
|
||||
AdPlaybackState.AdGroup adGroup =
|
||||
new AdPlaybackState.AdGroup(/* timeUs= */ 0L)
|
||||
.withAdCount(3)
|
||||
.withAdId(/* adId= */ "0", /* index= */ 0)
|
||||
.withAdId(/* adId= */ "2", /* index= */ 2);
|
||||
|
||||
// Asserts that the missing @NullableType in fromBundle() isn't harmful.
|
||||
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle()).ids[1]).isNull();
|
||||
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle())).isEqualTo(adGroup);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user