Summary
The app relies on two persistent foreground services to monitor user activity, track scrolling distances, and enforce usage limits in real-time. These services run continuously when the app is in the background to ensure that screen time data is accurate and that blocking overlays appear immediately when a limit is reached.Overview Diagram
Foreground Services
These services run continuously with a visible notification to prevent the Android system from killing them.ScrollTrackService
This is the core engine of the application. It utilizes Android’s Accessibility Services to detect what is on screen and how much the user is scrolling. What it does: Monitors active apps, calculates physical scroll distance, and draws blocking overlays over restricted apps.| Property | Value |
|---|---|
| Notification | ”Monitoring usage” |
| Starts when | User manually enables Accessibility permission |
| Stops when | User disables permission or Force Stops app |
| Key Triggers | Scroll events, Window state changes, Screen On/Off |
Event Detection
The service receives an event from the system (e.g., the user scrolled a list or opened a new app).
Classification
The AppScrollClassifier determines if the app reports precise pixel data or if distance must be estimated based on list index changes.
Processing
If scrolling, the physics engine converts pixels to physical distance (meters/micrometers). If the app changed, the ActiveSessionTracker updates the current session timer.
AppTrackerService
This service acts as a fallback and validator for app usage. What it does: Polls system usage statistics to detect app switches that the Accessibility Service might miss (e.g., if the service is briefly interrupted or specific UI events don’t fire).| Property | Value |
|---|---|
| Notification | ”Monitoring app switches” |
| Starts when | App launch (if permissions granted) |
| Stops when | App is killed |
| Interval | Polls every ~750 milliseconds |
Real-Time Logic Engines
These components run within the services to calculate usage without database latency.Usage Projection Engine
To decide if an app should be blocked right now, the app cannot rely solely on the database, which might be a few seconds behind. This engine calculates usage using a zero-latency formula:Total Usage = Historical (Saved in DB) + Buffer (Finished sessions not yet saved) + Live (Current open session)This ensures that if a user has a 15-minute limit and they are at 14:59, the block triggers the exact second they cross the threshold.
App Scroll Classifier
Not all apps behave the same way. This logic determines how to track scrolling for a specific app:| Type | Description |
|---|---|
| Precise | The app reports exact pixel movement (e.g., standard Android lists). The service calculates exact physical distance. |
| Estimated | The app hides pixel data (e.g., some web views or custom game engines). The service infers distance based on list item changes or content updates. |
Active Session Tracker
A singleton that acts as a stopwatch for the currently open app. It uses a to track duration. It handles pausing when the screen turns off and resuming when the screen turns on.Internal Receivers
TheScrollTrackService registers internal broadcast receivers to handle system state changes dynamically.
| Receiver | Listens For | What It Does |
|---|---|---|
| ScreenReceiver | SCREEN_OFF | Pauses the active session timer and stops tracking to save battery. |
| ScreenReceiver | SCREEN_ON | Resumes the session timer for the foreground app. |
| BlockingReceiver | ACTIVITY_DISMISSED | Detects when the user dismisses the blocking screen (e.g., via an emergency unlock) to reset internal flags. |