diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1a31fb06cf..99f6c7549e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,6 +47,8 @@ be directly made with the `Player.EventListener` interface. * Deprecate `DefaultAnalyticsListener` as selective listener overrides can be directly made with the `AnalyticsListener` interface. +* 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 fe6d50a068..afb8a31c37 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 @@ -281,13 +281,9 @@ public final class ImaAdsLoader /** 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; @@ -299,9 +295,7 @@ public final class ImaAdsLoader // 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} @@ -324,13 +318,9 @@ public final class ImaAdsLoader * 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; /** @@ -526,6 +516,11 @@ public final class ImaAdsLoader adsManager.destroy(); adsManager = null; } + imaPausedContent = false; + imaAdState = IMA_AD_STATE_NONE; + pendingAdLoadError = null; + adPlaybackState = AdPlaybackState.NONE; + updateAdPlaybackState(); } @Override @@ -575,7 +570,7 @@ public final class ImaAdsLoader 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 { @@ -671,6 +666,13 @@ public final class ImaAdsLoader @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, @@ -679,9 +681,6 @@ public final class ImaAdsLoader 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"); @@ -710,6 +709,10 @@ public final class ImaAdsLoader 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. @@ -753,6 +756,10 @@ public final class ImaAdsLoader 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"); @@ -1099,6 +1106,10 @@ public final class ImaAdsLoader 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. @@ -1181,7 +1192,7 @@ public final class ImaAdsLoader 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);