Stop counting locked phones, keyboards and home screens as screen time - #54
Merged
Merged
Conversation
A parent saw fourteen hours of screen time in a day, and a browser that was barely counted at all. Three separate causes, all in how time is attributed: The tick credited apps while the phone was locked. It flushes the app in front every thirty seconds, and it kept doing so with the screen off - so whatever was open when the phone was put down accrued time all night. Nothing in the accessibility service ever heard the screen go off. It now listens for screen off and unlock itself, stops crediting anyone while the screen is off, and on unlock asks which window is in front rather than waiting for an event that unlocking back into the same app does not always produce. Sessions leaked. Screen time is counted from unlock to screen off, and if the screen-off went unheard - its service killed, which some phones do routinely - the session stayed open and counted every locked hour. Midnight made it worse: the rollover cleared the day's totals but not the open session's start, so a new day could begin with the previous evening already on the clock. A session now only counts while the screen is actually on, and one still open at midnight counts on the new day from midnight. Windows that are not apps were credited as apps. Android reports the keyboard, the notification shade and the home screen as windows coming to the front, and each one took the credit from the app underneath. Typing a search opened the keyboard and the browser stopped counting until it closed. Keyboards and system UI now leave the credit with the app they are drawn over; the home screen counts as screen time but as nobody's app. Separately, leaving the calm notification list took one Back press per time it had been opened. Every route to it pushed another copy of the screen, and the "open the calm list" intent extra survived activity recreation, so a theme change or the app lock added yet another. The extra is consumed once, and the screen is never stacked on itself. Nine new tests pin the tracking causes, each of which fails against the old code. All 290 shared tests pass. Co-Authored-By: Claude Opus 5.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.
Fixes three bugs reported from real use of the parent app. A fourth, the crash on removing a blocked website, still needs a stack trace; it's not in this PR.
Fourteen hours in a day, and an undercounted browser
Three separate causes, all in how time gets attributed:
The report guessed the 14 hours came from system apps. The evidence points at the first two rows instead — though the third row is real too, just as the reason the browser looked undercounted.
Leaving the calm notification list took several Back presses
Every route to it (the dashboard card, the calm notification, the Quick Settings tile) pushed another copy of the screen, and the
open_digestintent extra survived activity recreation, so a theme change or the app lock pushed yet another. The extra is now consumed once, and the screen is never stacked on itself (launchSingleTop). The kid app uses a state switch rather than a navigation stack, so it never had this.Tests
OvercountTestadds nine cases, each of which fails against the old code: a missed screen-off, a session across midnight, a new day starting with yesterday's evening on it, an unlock after a missed screen-off, and the window classification. All 290 shared unit tests pass; every variant builds.Not verifiable without a phone: the screen-off receiver and
rootInActiveWindowon unlock. Test APKs are built for a device check before merge.🤖 Generated with Claude Code