Fix handling of fetch errors for post-rolls

The ad break time in seconds from IMA was "-1" for postrolls, but this didn't
match C.TIME_END_OF_SOURCE in the ad group times array.

Handle an ad break time of -1 directly by mapping it onto the last ad group,
instead of trying to look it up in the array.

PiperOrigin-RevId: 312064886
This commit is contained in:
andrewlewis 2020-05-18 14:05:47 +01:00 committed by Andrew Lewis
parent 786edf8ecd
commit ef615754db
4 changed files with 46 additions and 2 deletions

View File

@ -50,6 +50,7 @@ dependencies {
androidTestImplementation 'com.android.support:multidex:1.0.3'
androidTestCompileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
testImplementation project(modulePrefix + 'testutils')
testImplementation 'com.google.guava:guava:' + guavaVersion
testImplementation 'org.robolectric:robolectric:' + robolectricVersion
}

View File

@ -1114,7 +1114,9 @@ public final class ImaAdsLoader
}
int adGroupTimeSeconds = Integer.parseInt(adGroupTimeSecondsString);
int adGroupIndex =
Arrays.binarySearch(
adGroupTimeSeconds == -1
? adPlaybackState.adGroupCount - 1
: Util.linearSearch(
adPlaybackState.adGroupTimesUs, C.MICROS_PER_SECOND * adGroupTimeSeconds);
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex];
if (adGroup.count == C.LENGTH_UNSET) {

View File

@ -56,6 +56,7 @@ import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
@ -105,6 +106,7 @@ public final class ImaAdsLoaderTest {
@Mock private ImaFactory mockImaFactory;
@Mock private AdPodInfo mockAdPodInfo;
@Mock private Ad mockPrerollSingleAd;
@Mock private AdEvent mockPostrollFetchErrorAdEvent;
private ViewGroup adViewGroup;
private View adOverlayView;
@ -252,6 +254,23 @@ public final class ImaAdsLoaderTest {
.withAdResumePositionUs(/* adResumePositionUs= */ 0));
}
@Test
public void playback_withPostrollFetchError_marksAdAsInErrorState() {
setupPlayback(CONTENT_TIMELINE, ADS_DURATIONS_US, new Float[] {-1f});
// Simulate loading an empty postroll ad.
imaAdsLoader.start(adsLoaderListener, adViewProvider);
imaAdsLoader.onAdEvent(mockPostrollFetchErrorAdEvent);
assertThat(adsLoaderListener.adPlaybackState)
.isEqualTo(
new AdPlaybackState(/* adGroupTimesUs...= */ C.TIME_END_OF_SOURCE)
.withContentDurationUs(CONTENT_PERIOD_DURATION_US)
.withAdDurationsUs(ADS_DURATIONS_US)
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0));
}
@Test
public void playback_withAdNotPreloadingBeforeTimeout_hasNoError() {
// Simulate an ad at 2 seconds.
@ -378,6 +397,10 @@ public final class ImaAdsLoaderTest {
when(mockAdPodInfo.getAdPosition()).thenReturn(1);
when(mockPrerollSingleAd.getAdPodInfo()).thenReturn(mockAdPodInfo);
when(mockPostrollFetchErrorAdEvent.getType()).thenReturn(AdEventType.AD_BREAK_FETCH_ERROR);
when(mockPostrollFetchErrorAdEvent.getAdData())
.thenReturn(ImmutableMap.of("adBreakTime", "-1"));
}
private static AdEvent getAdEvent(AdEventType adEventType, @Nullable Ad ad) {

View File

@ -767,6 +767,24 @@ public final class Util {
return C.INDEX_UNSET;
}
/**
* Returns the index of the first occurrence of {@code value} in {@code array}, or {@link
* C#INDEX_UNSET} if {@code value} is not contained in {@code array}.
*
* @param array The array to search.
* @param value The value to search for.
* @return The index of the first occurrence of value in {@code array}, or {@link C#INDEX_UNSET}
* if {@code value} is not contained in {@code array}.
*/
public static int linearSearch(long[] array, long value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) {
return i;
}
}
return C.INDEX_UNSET;
}
/**
* Returns the index of the largest element in {@code array} that is less than (or optionally
* equal to) a specified {@code value}.