diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 46a1117202..42b9449410 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -5,6 +5,8 @@ * DRM: * Allow DrmInitData to carry a license server URL ([#3393](https://github.com/google/ExoPlayer/issues/3393)). +* IMA: Fix behavior when creating/releasing the player then releasing + `ImaAdsLoader` ((#3879)[https://github.com/google/ExoPlayer/issues/3879]). ### 2.8.2 ### diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java index 3256da21dd..9045ee777a 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java @@ -267,13 +267,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A /** The expected ad group index that IMA should load next. */ private int expectedAdGroupIndex; - /** - * The index of the current ad group that IMA is loading. - */ + /** The index of the current ad group that IMA is loading. */ private int adGroupIndex; - /** - * Whether IMA has sent an ad event to pause content since the last resume content event. - */ + /** Whether IMA has sent an ad event to pause content since the last resume content event. */ private boolean imaPausedContent; /** The current ad playback state. */ private @ImaAdState int imaAdState; @@ -285,9 +281,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A // Fields tracking the player/loader state. - /** - * Whether the player is playing an ad. - */ + /** Whether the player is playing an ad. */ private boolean playingAd; /** * If the player is playing an ad, stores the ad index in its ad group. {@link C#INDEX_UNSET} @@ -310,13 +304,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A * content progress should increase. {@link C#TIME_UNSET} otherwise. */ private long fakeContentProgressOffsetMs; - /** - * Stores the pending content position when a seek operation was intercepted to play an ad. - */ + /** Stores the pending content position when a seek operation was intercepted to play an ad. */ private long pendingContentPositionMs; - /** - * Whether {@link #getContentProgress()} has sent {@link #pendingContentPositionMs} to IMA. - */ + /** Whether {@link #getContentProgress()} has sent {@link #pendingContentPositionMs} to IMA. */ private boolean sentPendingContentPositionMs; /** @@ -509,6 +499,11 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A adsManager.destroy(); adsManager = null; } + imaPausedContent = false; + imaAdState = IMA_AD_STATE_NONE; + pendingAdLoadError = null; + adPlaybackState = AdPlaybackState.NONE; + updateAdPlaybackState(); } @Override @@ -558,7 +553,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A Log.d(TAG, "onAdEvent: " + adEventType); } if (adsManager == null) { - Log.w(TAG, "Dropping ad event after release: " + adEvent); + Log.w(TAG, "Ignoring AdEvent after release: " + adEvent); return; } try { @@ -654,6 +649,13 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A @Override public void loadAd(String adUriString) { try { + if (DEBUG) { + Log.d(TAG, "loadAd in ad group " + adGroupIndex); + } + if (adsManager == null) { + Log.w(TAG, "Ignoring loadAd after release"); + return; + } if (adGroupIndex == C.INDEX_UNSET) { Log.w( TAG, @@ -662,9 +664,6 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A adGroupIndex = expectedAdGroupIndex; adsManager.start(); } - if (DEBUG) { - Log.d(TAG, "loadAd in ad group " + adGroupIndex); - } int adIndexInAdGroup = getAdIndexInAdGroupToLoad(adGroupIndex); if (adIndexInAdGroup == C.INDEX_UNSET) { Log.w(TAG, "Unexpected loadAd in an ad group with no remaining unavailable ads"); @@ -693,6 +692,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A if (DEBUG) { Log.d(TAG, "playAd"); } + if (adsManager == null) { + Log.w(TAG, "Ignoring playAd after release"); + return; + } switch (imaAdState) { case IMA_AD_STATE_PLAYING: // IMA does not always call stopAd before resuming content. @@ -736,6 +739,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A if (DEBUG) { Log.d(TAG, "stopAd"); } + if (adsManager == null) { + Log.w(TAG, "Ignoring stopAd after release"); + return; + } if (player == null) { // Sometimes messages from IMA arrive after detaching the player. See [Internal: b/63801642]. Log.w(TAG, "Unexpected stopAd while detached"); @@ -1083,6 +1090,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A Log.d( TAG, "Prepare error for ad " + adIndexInAdGroup + " in group " + adGroupIndex, exception); } + if (adsManager == null) { + Log.w(TAG, "Ignoring ad prepare error after release"); + return; + } if (imaAdState == IMA_AD_STATE_NONE) { // Send IMA a content position at the ad group so that it will try to play it, at which point // we can notify that it failed to load. @@ -1165,7 +1176,7 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A Log.e(TAG, message, cause); // We can't recover from an unexpected error in general, so skip all remaining ads. if (adPlaybackState == null) { - adPlaybackState = new AdPlaybackState(); + adPlaybackState = AdPlaybackState.NONE; } else { for (int i = 0; i < adPlaybackState.adGroupCount; i++) { adPlaybackState = adPlaybackState.withSkippedAdGroup(i);