Commit ad500ca8 by andrewlewis Committed by Oliver Woodman

Replace IMA ad state booleans with an @IntDef

imaPausedInAd could only be true when imaPlayingAd was true, so there are only
three possible states.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=170827974
parent 5baddfb5
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.ext.ima; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.ext.ima;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.annotation.IntDef;
import android.util.Log; import android.util.Log;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.webkit.WebView; import android.webkit.WebView;
...@@ -49,6 +50,8 @@ import com.google.android.exoplayer2.source.ads.AdPlaybackState; ...@@ -49,6 +50,8 @@ import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.AdsLoader; import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -88,6 +91,25 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -88,6 +91,25 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
private static final String FOCUS_SKIP_BUTTON_WORKAROUND_JS = "javascript:" private static final String FOCUS_SKIP_BUTTON_WORKAROUND_JS = "javascript:"
+ "try{ document.getElementsByClassName(\"videoAdUiSkipButton\")[0].focus(); } catch (e) {}"; + "try{ document.getElementsByClassName(\"videoAdUiSkipButton\")[0].focus(); } catch (e) {}";
/**
* The state of ad playback based on IMA's calls to {@link #playAd()} and {@link #pauseAd()}.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({IMA_AD_STATE_NONE, IMA_AD_STATE_PLAYING, IMA_AD_STATE_PAUSED})
private @interface ImaAdState {}
/**
* The ad playback state when IMA is not playing an ad.
*/
private static final int IMA_AD_STATE_NONE = 0;
/**
* The ad playback state when IMA has called {@link #playAd()} and not {@link #pauseAd()}.
*/
private static final int IMA_AD_STATE_PLAYING = 1;
/**
* The ad playback state when IMA has called {@link #pauseAd()} while playing an ad.
*/
private static final int IMA_AD_STATE_PAUSED = 2;
private final Uri adTagUri; private final Uri adTagUri;
private final Timeline.Period period; private final Timeline.Period period;
private final List<VideoAdPlayerCallback> adCallbacks; private final List<VideoAdPlayerCallback> adCallbacks;
...@@ -117,15 +139,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -117,15 +139,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
*/ */
private boolean imaPausedContent; private boolean imaPausedContent;
/** /**
* If {@link #playingAd} is set, stores whether IMA has called {@link #playAd()} and not * The current ad playback state based on IMA's calls to {@link #playAd()} and {@link #stopAd()}.
* {@link #stopAd()}.
*/
private boolean imaPlayingAd;
/**
* If {@link #playingAd} is set, stores whether IMA has called {@link #pauseAd()} since a
* preceding call to {@link #playAd()} for the current ad.
*/ */
private boolean imaPausedInAd; private @ImaAdState int imaAdState;
/** /**
* Whether {@link com.google.ads.interactivemedia.v3.api.AdsLoader#contentComplete()} has been * Whether {@link com.google.ads.interactivemedia.v3.api.AdsLoader#contentComplete()} has been
* called since starting ad playback. * called since starting ad playback.
...@@ -439,21 +455,23 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -439,21 +455,23 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
playWhenReadyOverriddenForAds = true; playWhenReadyOverriddenForAds = true;
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
} }
if (imaPlayingAd && !imaPausedInAd) { switch (imaAdState) {
// Work around an issue where IMA does not always call stopAd before resuming content. case IMA_AD_STATE_PLAYING:
// See [Internal: b/38354028, b/63320878]. // IMA does not always call stopAd before resuming content.
Log.w(TAG, "Unexpected playAd without stopAd"); // See [Internal: b/38354028, b/63320878].
} Log.w(TAG, "Unexpected playAd without stopAd");
if (!imaPlayingAd) { break;
imaPlayingAd = true; case IMA_AD_STATE_NONE:
for (int i = 0; i < adCallbacks.size(); i++) { imaAdState = IMA_AD_STATE_PLAYING;
adCallbacks.get(i).onPlay(); for (int i = 0; i < adCallbacks.size(); i++) {
} adCallbacks.get(i).onPlay();
} else if (imaPausedInAd) { }
imaPausedInAd = false; break;
for (int i = 0; i < adCallbacks.size(); i++) { case IMA_AD_STATE_PAUSED:
adCallbacks.get(i).onResume(); imaAdState = IMA_AD_STATE_PLAYING;
} for (int i = 0; i < adCallbacks.size(); i++) {
adCallbacks.get(i).onResume();
}
} }
} }
...@@ -466,7 +484,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -466,7 +484,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
// Sometimes messages from IMA arrive after detaching the player. See [Internal: b/63801642]. // Sometimes messages from IMA arrive after detaching the player. See [Internal: b/63801642].
Log.w(TAG, "Unexpected stopAd while detached"); Log.w(TAG, "Unexpected stopAd while detached");
} }
if (!imaPlayingAd) { if (imaAdState == IMA_AD_STATE_NONE) {
Log.w(TAG, "Unexpected stopAd"); Log.w(TAG, "Unexpected stopAd");
return; return;
} }
...@@ -478,11 +496,11 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -478,11 +496,11 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "pauseAd"); Log.d(TAG, "pauseAd");
} }
if (!imaPlayingAd) { if (imaAdState == IMA_AD_STATE_NONE) {
// This method is called after content is resumed. // This method is called after content is resumed.
return; return;
} }
imaPausedInAd = true; imaAdState = IMA_AD_STATE_PAUSED;
for (int i = 0; i < adCallbacks.size(); i++) { for (int i = 0; i < adCallbacks.size(); i++) {
adCallbacks.get(i).onPause(); adCallbacks.get(i).onPause();
} }
...@@ -514,9 +532,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -514,9 +532,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
return; return;
} }
if (!imaPlayingAd && playbackState == Player.STATE_BUFFERING && playWhenReady) { if (imaAdState == IMA_AD_STATE_NONE && playbackState == Player.STATE_BUFFERING
&& playWhenReady) {
checkForContentComplete(); checkForContentComplete();
} else if (imaPlayingAd && playbackState == Player.STATE_ENDED) { } else if (imaAdState != IMA_AD_STATE_NONE && playbackState == Player.STATE_ENDED) {
// IMA is waiting for the ad playback to finish so invoke the callback now. // IMA is waiting for the ad playback to finish so invoke the callback now.
// Either CONTENT_RESUME_REQUESTED will be passed next, or playAd will be called again. // Either CONTENT_RESUME_REQUESTED will be passed next, or playAd will be called again.
for (int i = 0; i < adCallbacks.size(); i++) { for (int i = 0; i < adCallbacks.size(); i++) {
...@@ -603,7 +622,8 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -603,7 +622,8 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
} }
private void resumeContentInternal() { private void resumeContentInternal() {
if (imaPlayingAd) { if (imaAdState != IMA_AD_STATE_NONE) {
imaAdState = IMA_AD_STATE_NONE;
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "Unexpected CONTENT_RESUME_REQUESTED without stopAd"); Log.d(TAG, "Unexpected CONTENT_RESUME_REQUESTED without stopAd");
} }
...@@ -613,10 +633,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -613,10 +633,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
adGroupIndex = C.INDEX_UNSET; adGroupIndex = C.INDEX_UNSET;
updateAdPlaybackState(); updateAdPlaybackState();
} }
clearFlags();
} }
private void pauseContentInternal() { private void pauseContentInternal() {
imaAdState = IMA_AD_STATE_NONE;
if (sentPendingContentPositionMs) { if (sentPendingContentPositionMs) {
pendingContentPositionMs = C.TIME_UNSET; pendingContentPositionMs = C.TIME_UNSET;
sentPendingContentPositionMs = false; sentPendingContentPositionMs = false;
...@@ -624,24 +644,16 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -624,24 +644,16 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
// IMA is requesting to pause content, so stop faking the content position. // IMA is requesting to pause content, so stop faking the content position.
fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET; fakeContentProgressElapsedRealtimeMs = C.TIME_UNSET;
fakeContentProgressOffsetMs = C.TIME_UNSET; fakeContentProgressOffsetMs = C.TIME_UNSET;
clearFlags();
} }
private void stopAdInternal() { private void stopAdInternal() {
Assertions.checkState(imaPlayingAd); Assertions.checkState(imaAdState != IMA_AD_STATE_NONE);
imaAdState = IMA_AD_STATE_NONE;
adPlaybackState.playedAd(adGroupIndex); adPlaybackState.playedAd(adGroupIndex);
updateAdPlaybackState(); updateAdPlaybackState();
if (!playingAd) { if (!playingAd) {
adGroupIndex = C.INDEX_UNSET; adGroupIndex = C.INDEX_UNSET;
} }
clearFlags();
}
private void clearFlags() {
// If an ad is displayed, these flags will be updated in response to playAd/pauseAd/stopAd until
// the content is resumed.
imaPlayingAd = false;
imaPausedInAd = false;
} }
private void checkForContentComplete() { private void checkForContentComplete() {
...@@ -663,6 +675,15 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -663,6 +675,15 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
} }
} }
private void focusSkipButton() {
if (playingAd && adUiViewGroup != null && adUiViewGroup.getChildCount() > 0
&& adUiViewGroup.getChildAt(0) instanceof WebView) {
WebView webView = (WebView) (adUiViewGroup.getChildAt(0));
webView.requestFocus();
webView.loadUrl(FOCUS_SKIP_BUTTON_WORKAROUND_JS);
}
}
private static long[] getAdGroupTimesUs(List<Float> cuePoints) { private static long[] getAdGroupTimesUs(List<Float> cuePoints) {
if (cuePoints.isEmpty()) { if (cuePoints.isEmpty()) {
// If no cue points are specified, there is a preroll ad. // If no cue points are specified, there is a preroll ad.
...@@ -679,13 +700,4 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A ...@@ -679,13 +700,4 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
return adGroupTimesUs; return adGroupTimesUs;
} }
private void focusSkipButton() {
if (playingAd && adUiViewGroup != null && adUiViewGroup.getChildCount() > 0
&& adUiViewGroup.getChildAt(0) instanceof WebView) {
WebView webView = (WebView) (adUiViewGroup.getChildAt(0));
webView.requestFocus();
webView.loadUrl(FOCUS_SKIP_BUTTON_WORKAROUND_JS);
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment