Overnight dark window: a deliberate wake keeps control (fixes #138)#141
Merged
Conversation
In the dark overnight window the screen is off via lockNow. A tap to wake fires ACTION_DREAMING_STOPPED; classifyDreamStop sees the device is interactive and returns REDREAM, so handleRedreamDuringOvernight runs. With no night session active it hit REBLANK and slept the screen again the instant it lit up. The catch: every redream that reaches this path is already interactive (that is what makes the verdict REDREAM), so interactivity alone cannot tell a real user wake from a stray sibling/system dream cycle (issue #73). Use the real user-input signal instead: - onInteraction (USER_PRESENT / a launcher touch) now STARTS a night session when inside the window with none active, instead of only renewing an existing one - handing the user the device on a dark-window wake. - A lastUserWakeAt timestamp feeds a new userWokeRecently input to classifyOvernightRedream: a redream within USER_WAKE_GRACE_MS of a real wake LEAVEs (and the caller starts the session) rather than reblanking, covering the race where the dream-stop broadcast beats USER_PRESENT. Stray cycles (no recent user wake) still REBLANK, so #73 stays fixed. Pure-classifier unit tests cover both the #138 wake case and the #73 stray-cycle case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4SmhtgSd5B5sdTiV216XM
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.
Problem
Reported in #138 (fresh on 1.60). With overnight screen-off (dark mode) enabled, tapping to wake the device inside the window wakes the screen and then it "turns off the instant it lights up."
Root cause
The dark window ends in
ScreenControl.sleep(device-adminlockNow), with no night session active. A tap firesACTION_DREAMING_STOPPED:classifyDreamStopseespm.isInteractive == true(the user just woke it) → verdictREDREAM(PresenceState.kt, "force-woken but still awake → someone's here").REDREAMroutes intoSleepScheduler.handleRedreamDuringOvernight.classifyOvernightRedream(inWindow=true, nightSessionActive=false, nightClock=false)→REBLANK→ScreenControl.sleep.The subtlety: every redream that reaches this path is already
interactive— that is precisely what makes the verdictREDREAM— so interactivity alone can't distinguish a real user wake from a stray sibling/system dream cycle (the #73 case). The old code treated the whole class as a stray cycle and reblanked, which is why the deliberate wake got slammed off. #87's "keep control" session is normally started byHomeActivity.onResume, but in dark mode the reblank wins the race before the launcher resumes (night-clock mode is unaffected because the clock Activity holds the screen).Fix
Use the real user-input signal (
USER_PRESENT/ a launcher touch) to tell a wake from a stray cycle:onInteractionnow starts a night session when inside the window with none active, instead of only renewing an existing one — handing the user the device on a dark-window wake.lastUserWakeAttimestamp feeds a newuserWokeRecentlyinput toclassifyOvernightRedream: a redream withinUSER_WAKE_GRACE_MS(4s) of a real wakeLEAVEs (and the caller starts the session) rather than reblanking, covering the race where the dream-stop broadcast beatsUSER_PRESENT.REBLANK, so Screensaver during sleep hours flickers on every few mins briefly. #73 stays fixed.Testing
LEAVE) and the Screensaver during sleep hours flickers on every few mins briefly. #73 stray-cycle case (REBLANK), plus night-clock precedence.SleepSchedulerTestgreen.:app:testDebugUnitTestcompiles and passes locally.Needs on-device confirmation
The pure logic is unit-tested, but the wake-event sequence on hardware is device-specific — in particular whether a dark-window tap emits
ACTION_USER_PRESENT(which this fix keys on) and its ordering vs. the dream-stop. @leapon0507-alt — if you're able, a logcat of a wake during the window, or just a retest once this lands, would confirm it. The change degrades safely (stray-cycle behaviour is unchanged).Closes #138.
🤖 Generated with Claude Code
Generated by Claude Code