Skip to main content

Overview

The Phone Usage module is the analytical heart of the application. It provides a multi-dimensional view of how a user interacts with their device, aggregating data across time (Daily, Weekly, Monthly) and metrics (Usage Time, Scroll Distance). Beyond simple reporting, it serves as a control center where users can observe patterns via a and immediately act on those insights by setting or adjusting app limits.

Architecture & Data Flow

This module follows a strict pattern, orchestrating data from three distinct repositories to build a cohesive UI state.

The State Pipeline

The PhoneUsageViewModel acts as a data synthesizer. It uses the combine operator to merge:
  1. Temporal Context: The selected date and period (Daily/Weekly/Monthly).
  2. Usage Statistics: Time and scroll data from the local database.
  3. App Metadata: Cached icons and labels to ensure the UI remains responsive without constant PackageManager queries.
  4. Limit Status: Real-time information on whether an app is currently restricted or if a limit is paused.

Key Components

ComponentResponsibility
PhoneUsageScreenThe entry point. It renders the metric header, heatmap, and the scrollable list of app usage cards.
PhoneUsageViewModelManages the business logic for switching time periods and calculating aggregate statistics. It leverages flatMapLatest to switch data sources based on the selected period.
AppUiModelMapperA specialized that enriches raw usage records with metadata and limit information.
LimitViewModelDelegateEncapsulates shared logic for the “Set Limit” bottom sheet, allowing the same limit-setting behavior to be reused across different screens.

Operational Logic

Initialization & Sync

When the module is accessed, the AppMetadataRepository ensures that the local cache of installed apps is synchronized with the system. This includes:
  • Detecting newly installed or uninstalled apps.
  • Caching app icons as local files to avoid overhead during list scrolling.
  • Determining “User Visibility” (filtering out background system services that don’t have launcher icons).

State Management: The Period Switch

The system handles three distinct views:
  • Daily: Shows exact usage for a specific 24-hour window.
  • Weekly/Monthly: Calculates Average Daily Usage across the selected range. The ViewModel dynamically adjusts the usageStat label and recalculates LimitInfo based on the current day’s progress, even when viewing historical averages.

Handling “Ghost” Apps

A unique feature of this module is its handling of Removed Apps. If a user deletes an app that has recorded usage data for the current period, the system:
  1. Retains the usage record in the database.
  2. Groups these apps into a specialized RemovedAppsCard.
  3. Allows the user to view their historical impact on total screen time even after the app is gone.

Data Engineering & Transformation

The data pipeline is optimized for performance using .
  • Source Tables: Data is pulled from daily_app_usage, app_metadata, and limit_groups.
  • Transformation Logic:
    • Aggregation: The AppUiModelMapper groups raw records by packageName and sums usageTimeMillis.
    • Limit Calculation: timeRemainingMillis is calculated by subtracting the current day’s usage (from todayUsageMap) from the group’s time_limit_minutes.
    • Heuristics: The system uses a launcher intent check (CATEGORY_LAUNCHER) to determine if an app should be visible in the primary usage list.

Dependencies

  • Coil: Used for asynchronous loading of cached app icons.
  • Hilt: Handles for the ViewModel and Repositories.
  • Timber: Provides structured logging for synchronization and metadata fetching events.
  • Material 3: The UI utilizes Expressive components and ExperimentalMaterial3Api for the bottom sheet and layout structures.
Last modified on January 22, 2026