fix: permanent island disappearing after notifications/unlock (#237)#243
Open
noelpatata2 wants to merge 1 commit into
Open
fix: permanent island disappearing after notifications/unlock (#237)#243noelpatata2 wants to merge 1 commit into
noelpatata2 wants to merge 1 commit into
Conversation
…f#237) Root cause (confirmed on-device, HyperOS / Redmi Note 15 Pro 5G): the island swipe gesture is an expand/collapse toggle handled entirely in systemui - it never cancels the underlying focus notification and no listener callback fires. Bridged notifications therefore outlive their islands as invisible "zombies" (worst with removeOriginalNotification, whose islands are exempted from the stuck-notification sync cleanup), so activeIslands never drops back to 0 and the permanent island can never return. Fixes, in layers: - PermanentIslandManager: serialize all state access (it was mutated from main/Default/IO with no synchronization); debounce dispatch by 700ms so a cancel->post pair is not swallowed by HyperOS; reconcile cached state against the actually-posted notification on listener connect / screen on / unlock, re-asserting the island in place. - Keep the permanent island posted while bridged islands are active: HyperOS shows the newest focus island on top, so the permanent island reappears instantly when a bridged island collapses instead of leaving a gap (it previously stayed gone forever). - Give MESSAGE/STANDARD islands a 60s TTL (same mechanism live updates already use) and reap own-package notifications that are no longer tracked (e.g. after a service restart), so zombies are bounded. - Skip the 1-minute periodic sync while the screen is off; SCREEN_ON already triggers a full refresh sync on wake. Also adds an optional "watch relay": when the original notification is removed, post a silent short-lived mirror so companion apps (Mi Fitness etc.) can still forward it to a smartwatch. Happy to split this into its own PR or gate it behind a setting if preferred. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What this fixes
Fixes #237 (permanent island getting removed after receiving notifications and never coming back). Likely also improves #227.
Root cause (confirmed on a real device)
Debugged on-device (Redmi Note 15 Pro 5G, HyperOS, global ROM) with logcat +
dumpsys notification:The island swipe gesture is an expand/collapse toggle handled entirely by systemui. It never cancels the underlying focus notification and no
onNotificationRemovedcallback ever fires. After the user swipes an island away, its bridged notification stays posted (ONGOING_EVENT,focusType=PARAMS) as an invisible zombie — verified indumpsysminutes after the swipe, with zero removal events in the app's logs.Consequences:
activeIslandsnever drops back to 0, soPermanentIslandManager.updateState()keeps the permanent island suppressed forever.removeOriginalNotificationmode is hit worst, becausesyncNotifications()deliberately exempts those islands from the stuck-notification cleanup (their original key is expected to be missing).PermanentIslandManagerstate is mutated from three different threads with no synchronization, and a cancel→post pair issued in the same instant can be swallowed by HyperOS, leaving notification 9999 posted but its island hidden.The fix, in layers
PermanentIslandManager): all state access serialized (@Synchronized/monitor); on listener connect, screen-on and unlock the cachedisIslandActivebelief is reconciled against whether ID 9999 is actually posted, re-asserting the island in place when needed.SCREEN_ONalready triggers a full refresh sync on wake, so nothing is lost.Also included (happy to split into a separate PR and/or gate behind a setting — say the word): a "watch relay" — when
removeOriginalNotificationcancels the original, companion apps that mirror notifications to smartwatches (Mi Fitness etc.) lose the relay. This posts a silent, 10-second, low-importance mirror they can forward. Tested with a Redmi Watch 5: watch vibrates again while the phone shows only the island.Testing
All verified on-device (Redmi Note 15 Pro 5G, HyperOS, v0.5.5 base):
Not tested: CNROM, other device models, widget islands (code paths untouched), non-Shizuku mode.
Full disclosure
This fix was developed AI-assisted (Claude Code / Anthropic) — "vibecoded", as the kids say — driving a real device over adb: the diagnosis came from logcat/dumpsys evidence, and every layer was tested on-device by a human before landing here. Review with whatever extra skepticism that deserves; happy to iterate on anything.
🤖 Generated with Claude Code