Found in code audit. Small remaining items, bundled.
Details
- No
isDisplayingAd guard in AdManager.showAd() (AdManager.kt:1194-1295, getAnyAvailableAd() 1178-1192): showAd() checks only isReady(). While an ad from the legacy mInterstitialAd fallback is on screen, isReady() is still true, so a second showInterstitialIfReady() retrieves the same InterstitialAd and calls show() again; the failure callback then sets isDisplayingAd = false and nulls state while the first showing is in progress, firing the second caller's onNextAction() prematurely. Note mInterstitialAd is mirrored on every pool load (line 433) and pool removal does not clear the mirror.
AdManageKitConfig.resetToDefaults() restores maxCacheMemoryMB = 50 while the declared default is 200 (line 423 vs 502) — calling reset silently quarters the native-ad cache budget versus a fresh process.
InterstitialAdBuilder maps onNextAction() directly to onAdDismissedCallback (lines 451-454): onNextAction() fires on every skip/failure/timeout path (premium user, no fill, interval skip), so .onAdDismissed reports "ad watched" false positives. Related: .force() has no effect unless minInterval() is also set (line 433 is the only read of forceShow), contradicting its documentation.
- Retry closures retain Activity contexts (
AdManager.kt:330-337, 458-465, 579-586): retry lambdas capture the caller's context/callback and are held by AdRetryManager's handler for up to maxRetryDelay.
Found in code audit. Small remaining items, bundled.
Details
isDisplayingAdguard inAdManager.showAd()(AdManager.kt:1194-1295,getAnyAvailableAd()1178-1192):showAd()checks onlyisReady(). While an ad from the legacymInterstitialAdfallback is on screen,isReady()is still true, so a secondshowInterstitialIfReady()retrieves the sameInterstitialAdand callsshow()again; the failure callback then setsisDisplayingAd = falseand nulls state while the first showing is in progress, firing the second caller'sonNextAction()prematurely. NotemInterstitialAdis mirrored on every pool load (line 433) and pool removal does not clear the mirror.AdManageKitConfig.resetToDefaults()restoresmaxCacheMemoryMB = 50while the declared default is 200 (line 423 vs 502) — calling reset silently quarters the native-ad cache budget versus a fresh process.InterstitialAdBuildermapsonNextAction()directly toonAdDismissedCallback(lines 451-454):onNextAction()fires on every skip/failure/timeout path (premium user, no fill, interval skip), so.onAdDismissedreports "ad watched" false positives. Related:.force()has no effect unlessminInterval()is also set (line 433 is the only read offorceShow), contradicting its documentation.AdManager.kt:330-337, 458-465, 579-586): retry lambdas capture the caller'scontext/callback and are held byAdRetryManager's handler for up tomaxRetryDelay.