Skip to content

Commit 404d989

Browse files
committed
chore: v0.1.6
1 parent 14d0cef commit 404d989

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## 0.1.6 - 2026-06-01
4+
5+
- Android: eliminate the `IllegalArgumentException: Invalid window token (never added or removed already)` crash from `WindowlessWindowManager.relayout` reported on production devices (NEAR Mobile Play Console and others). v0.1.5's reflective traversal cancel only works on Android versions that don't block the hidden-API probe; Android 14+ hidden-API enforcement leaves the crash unfixed there. Five new layered defences in `detachCoverView` close the race deterministically without sacrificing the snapshot-race fix:
6+
- `FreezableFrameLayout` cover-content root whose `requestLayout()` / `invalidate()` no-op while a `frozen` flag is set. Set first thing in `detachCoverView`; from that point on no `requestLayout` reaches `ViewRootImpl.scheduleTraversals`, so no new `TraversalRunnable` can be queued during teardown.
7+
- Snapshot-then-null-out of shared state plus a `coverDetaching` re-entrance guard. Any synchronous re-entrant call (animation cancel listener, `dispatchDetachedFromWindow`) sees cleared fields and bails before double-removing or double-releasing.
8+
- `WindowManager.removeViewImmediate` so `dispatchDetachedFromWindow` runs inline while the freeze is active; falls back to async `removeView` on OEM impls that reject immediate removal in transitional states.
9+
- `setCoverVisibility` validity-checks `view.windowToken != null` before `updateViewLayout` — same WMS/WWM path that throws when the token is gone.
10+
- `deferredReleaseScvh` schedules `safeReleaseScvh` via `Choreographer.postFrameCallback` (animation phase) → nested `mainHandler.post`, so it runs strictly AFTER the next frame's traversal callbacks. Any `TraversalRunnable` already in the queue (including ones reflection couldn't cancel) fires with the WWM token still valid; release happens after, removing the token only when nothing is left to relayout. `ViewRootImpl.mTraversalScheduled` guarantees at most one queued runnable per ViewRootImpl, so one frame's wait drains it. Wired into all six release call sites — five SCVH attach recovery branches in `tryAttachCoverViaScvh` plus the teardown in `detachCoverView`.
11+
- Android: skip SCVH entirely on Android 11 (API 30) when `INTERNAL_SYSTEM_WINDOW` is denied (signature-level permission no normal app holds). On this AOSP release the SCVH path through `WindowManagerService.addWindow` enforces this permission and `host.setView` throws `SecurityException` AFTER `ViewRootImpl.setView` has already called `requestLayout()` — queuing a `TraversalRunnable` that fires the same vsync (TRAVERSAL phase, before any deferred work) on a token that was never registered with the WWM, throwing the "never added" variant of `Invalid window token` from `Looper.loop`. The deferred release can't help in this case (the runnable fires in the same vsync's traversal phase, before our queued Handler message); the only safe path is to never call `setView` on these devices. Scoped to API 30 only — Android 12+ dropped the permission check for SCVH's `addToDisplay` path, so SCVH and the SurfaceFlinger-direct alpha toggle continue to work unmodified on every modern device.
12+
- Android: real frosted-glass blur on Android 11 (API 30) instead of a flat tint. `RenderEffect.createBlurEffect` requires API >= 31, and the previous fallback dropped the captured bitmap and painted a flat ~80% white tint, leaving underlying app content fully readable through the cover — broken privacy on every Android 11 host. The fallback now reuses the captured bitmap at 1/12 in each dimension (1/144 pixels) and lets `ImageView`'s bilinear filter smudge it back to display size on draw, layered with the style tint as foreground exactly like the API >= S path. The visual contract matches across versions and the cover obscures content to a similar degree as iOS's `UIBlurEffect`.
13+
14+
`minSdkVersion=23`, public API, and iOS behavior unchanged.
15+
316
## 0.1.5 - 2026-05-22
417

518
- Android: cancel pending Choreographer traversals on the SCVH's internal `ViewRootImpl` before every release. Without this, a `TraversalRunnable` queued by the partial `setView` could fire after the windowless window token was removed, throwing `IllegalArgumentException: Invalid window token (never added or removed already)` from `WindowlessWindowManager.relayout` on a later vsync, outside any try/catch of ours because the runnable is dispatched from `Looper.loop`. Implemented as a reflective call to `ViewRootImpl.unscheduleTraversals()` via a field probe (the SCVH field name has not been stable across Android versions); on reflection failure the helper latches off so subsequent calls don't keep retrying.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-cover",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"description": "🔒 Native privacy cover for React Native. Hides your app behind an overlay in the iOS App Switcher and Android Recents screen.",
55
"main": "./lib/commonjs/index.js",
66
"module": "./lib/module/index.js",

0 commit comments

Comments
 (0)