fix(android): Samsung One UI stale cover-content filter + v0.1.8 - #5
Merged
Merged
Conversation
…on Samsung One UI v0.1.7's `exclude2 = coverContent` only filtered the *current* SCVH-hosted content instance from `topmostHostViewFor`. On Samsung Galaxy A05 (SM-A057F, Android 14, One UI), `LockCover`'s mount sequence triggers 2-3 rapid attach cycles in ~280ms — `enable()` runs `ensurePreMounted`, then `refreshCoverContentIfMounted` fires when JS subsequently calls `setColor` / `setImage` against the already-mounted cover. Each attach creates a new `FreezableFrameLayout` instance; the previous one lingers briefly in `WindowManagerGlobal.mViews` between `detachCoverView` returning and Samsung's WindowManager finishing the underlying `removeView`. The host walk picks the stale instance, `attachCover` tries to attach as a sub-window of an invalidated token, and `WindowManager.addView` throws BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@... is not valid; is your activity running? The cover never appears in the Recents thumbnail. Add a class-based filter in `CoverWindowAttachment.topmostHostViewFor`: `if (v is FreezableFrameLayout) continue`. Class match catches every cover-content instance, current or stale, regardless of which attach cycle created it. `FreezableFrameLayout` is widened from `private` to `internal` so `CoverWindowAttachment` can reference the type — strictly broader visibility, no callers affected. Existing instance-match `exclude2 = coverContent` is preserved as the fast path. The class-based filter is the safety net for the stale- instance window. Safety: the filter is strictly subtractive. It can never return an invalid candidate, only exclude one. On every non-Samsung device the SCVH-hosted content never appears in `WindowManagerGlobal.mViews` to begin with (it lives inside the SCVH's own ViewRootImpl), so the new check is a no-op there. The original `Invalid window token` crash from `WindowlessWindowManager.relayout` (v0.1.6) is unrelated to attach-side target selection and remains fixed by the teardown defences: `FreezableFrameLayout` freeze, `removeViewImmediate`, `deferredReleaseScvh`, `coverDetaching` re-entrance guard, and the API 30 `INTERNAL_SYSTEM_WINDOW` pre-check — all unchanged. Verified: - Samsung Galaxy A05 / SM-A057F (Android 14, One UI): cover paints in Recents with the configured `#5F8AFA` background and splash icon. Logcat shows clean `topmost=DecorView` host selection across multiple rapid `ensureCoverOnTopmost` cycles, two consecutive `attachCover` succeed, broadcast pipeline fires (`broadcast: fast scvh=false dt=0ms` → `setCoverVisibility: visible=true`), no `BadTokenException` or `Invalid window token` anywhere in `logcat *:E`. - Pixel_9 emulator (Android 16, API 37): 9/9 maestro flows pass in 3m 28s, identical to v0.1.6 baseline. SCVH SurfaceFlinger-direct alpha toggle still wins the Home-press snapshot race. - Favvy_Android_30 / API 30 (Android 11): app PID stable through 5× home/app-switcher + 10× rapid enable/disable toggle stress, API 30 `INTERNAL_SYSTEM_WINDOW` pre-check still fires, legacy attach path works, no `Invalid window token` in logcat.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
v0.1.8 — completes the Samsung One UI Recents-cover fix from v0.1.7. v0.1.7 fixed the first host-walk wrong-pick (
exclude2 = coverContent), but rapidsetColor/setImage/enableJS calls duringLockCovermount trigger 2–3 sequential attach cycles in ~280 ms. Each one creates a newFreezableFrameLayout; the previous instance lingers inWindowManagerGlobal.mViewsbriefly after teardown on Samsung One UI. v0.1.7's instance-only filter missed those stale entries; the walk picked one,addViewthrewBadTokenException: Unable to add window — token … is not valid; is your activity running?, and the cover never made it to the Recents thumbnail.Fix
Add a class-based filter in
CoverWindowAttachment.topmostHostViewFor:Class match catches every cover-content instance regardless of which attach cycle created it. Instance-based
exclude2 = coverContent(from v0.1.7) is preserved as the fast path; class filter is the safety net for the stale-instance window.FreezableFrameLayoutwidened fromprivatetointernalsoCoverWindowAttachmentcan name the type (strictly broader visibility, no callers affected).Safety review (done before merge)
null→ callers fall back todecor(every callsite has?: decorand adecor.windowToken == nullguard).FreezableFrameLayoutfreeze,removeViewImmediate,deferredReleaseScvh,coverDetachingre-entrance guard, and the API 30INTERNAL_SYSTEM_WINDOWpre-check are all unchanged. The originalInvalid window tokencrash fromWindowlessWindowManager.relayoutremains fixed.WindowManagerGlobal.mViews(it lives inside the SCVH's own ViewRootImpl). The new check matches zero times.<Modal>Dialog windows are notFreezableFrameLayout, so cover still z-orders above them.CoverBlurRenderer.renderuses the same walk and is now also protected from picking a stale cover bitmap as its source.Verified end-to-end
#5F8AFAcover with splash icon. Logcat:topmost=DecorView, 2 consecutiveattachCoversucceed (the exact case that hitBadTokenExceptionbefore),broadcast: fast scvh=false dt=0ms→setCoverVisibility: visible=true. Zero crash signatures inlogcat *:E.INTERNAL_SYSTEM_WINDOWpre-check still fires. Legacy attach path works. ZeroInvalid window token/IllegalArgumentException.Files changed
android/src/main/java/com/margelo/nitro/cover/CoverWindowAttachment.kt— +14 lines: class filter + comment explaining the stale-instance scenario.android/src/main/java/com/margelo/nitro/cover/HybridCover.kt— 1 line:private class→internal class FreezableFrameLayout.package.json—0.1.7→0.1.8.CHANGELOG.md— new0.1.8 - 2026-06-01entry.