Skip to content

Android App Usage and Pattern of Life Forensics

Prove when an Android phone was used and which app was on screen: usagestats, Digital Wellbeing, batterystats, recent tasks and notifications, combined.

Published on 9 min read

"Was the phone in use at 23:10, and what was on screen?" is one of the most common questions in mobile casework: it places a person at a device, supports or undermines an alibi, and ties a sent message to a moment when the app was open. Android answers it better than most people expect, because the OS records app activity for its own battery, scheduling and wellbeing features. This guide explains each source, what it can and cannot prove, and how to combine them into a pattern of life.

The sources

SourceWhat it recordsTypical windowAccess
usagestatsForeground and background per activity, screen on and off, keyguard shown and hidden, startup and shutdownAbout 10 days of events, aggregates for monthsFFS (AFU on 11+), dumpsys usagestats, bugreport
Digital WellbeingCopy of foreground and background events, on Android 9+About 1 to 2 weeksFFS, AFU
batterystatsScreen, charging, top app, wakelocks, radios, GPSSince the last full chargedumpsys batterystats, bugreport, FFS
Recent tasks and snapshotsTasks in Overview, last time moved to front, screenshot of the appUntil removedFFS (AFU), dumpsys activity recents
Notification historyNotifications posted, with text on Android 11+ if enabledAbout 24 hours (11+ history)FFS, dumpsys notification
Installed packagesInstall and update times, installerCurrent appsFFS (BFU), pm, dumpsys package

Each covers a different window and is written by a different system component, which is exactly why combining them is powerful: agreement between independent writers is hard to fake and easy to explain.

Capture the volatile layer first

Several of these sources are in memory or roll over quickly. If the phone is unlocked and you are authorised to use ADB, capture them before anything else, because every minute of handling adds events and pushes old ones out:

mkdir -p case0142/usage && cd case0142/usage
date -u +%FT%TZ > capture_start_utc.txt
adb shell date -u >> capture_start_utc.txt
adb shell dumpsys usagestats > dumpsys_usagestats.txt
adb shell dumpsys batterystats --history > batterystats_history.txt
adb shell dumpsys batterystats --checkin > batterystats_checkin.txt
adb shell dumpsys activity recents > dumpsys_recents.txt
adb shell dumpsys notification --noredact > dumpsys_notification.txt
adb shell getprop persist.sys.timezone > timezone.txt
sha256sum * > SHA256SUMS

Then take a bugreport, which repeats most of these dumps with more context, and proceed to the full file system extraction if the case needs the on-disk files. The bugreport and dumpsys guide explains each section.

Remember that your own actions create events: unlocking, opening Settings to enable debugging, accepting the RSA prompt. Note the times so you can exclude them.

Usagestats: the backbone

Usagestats is the most complete record. The events that matter most:

  • ACTIVITY_RESUMED (1) and ACTIVITY_PAUSED (2) or ACTIVITY_STOPPED (23): an activity of a package came to the front and left it. The class name tells you which screen, for example a chat screen versus the settings of an app.
  • SCREEN_INTERACTIVE (15) and SCREEN_NON_INTERACTIVE (16): screen on and off.
  • KEYGUARD_SHOWN (17) and KEYGUARD_HIDDEN (18): lock screen displayed and dismissed.
  • DEVICE_STARTUP (27), DEVICE_SHUTDOWN (26) and USER_UNLOCKED (28): power cycles and first unlock after boot.
  • NOTIFICATION_INTERRUPTION (12): a notification made noise, vibrated or peeked.

A typical "user picked up the phone and replied" sequence looks like: notification interruption for the messaging app, screen interactive, keyguard hidden, messaging app activity resumed, then paused a minute later. Each step is a separate event with its own millisecond timestamp.

Remember that event times in the files are offsets from the file's base time (its name, in Unix milliseconds). Parsers add them; if you decode protobuf by hand and see dates in 1970, you forgot the base.

Digital Wellbeing: the second writer

On phones with Google's Digital Wellbeing, the app_usage database holds its own copy of foreground and background events. It is simple SQL, it can cover a slightly different window than the usagestats daily files, and, being written by a different app, it corroborates them. Samsung phones use Samsung's own wellbeing app with different databases; check which package is installed.

Match events by package and time. Differences of a few milliseconds are normal; an event present in one store and missing from the other deserves an explanation (rollover, storage cleared, usage access revoked).

Battery history: device state without root

Battery history is a compact stream of state changes since the last full charge. For pattern of life, the useful tokens are +screen/-screen, +plugged/-plugged, and +top=u0a123:"package" for the app on top. Because it is available through dumpsys without root, it is sometimes the only usage evidence from a phone you cannot fully extract.

Its timestamps need care: each line is an offset from the reset point, and the absolute anchors (RESET:TIME:, TIME:) are printed in the device's local time. Convert with the device time zone and document it.

Recent tasks and snapshots: last use per app

Each task in Overview has an XML record with last_time_moved, the last time the task came to the front, and a snapshot image of what the app showed when it was left. For pattern of life, last_time_moved gives a "last used" time per app even beyond the usagestats window, and the snapshot can show exactly what the user was looking at: a chat, a map, a search result.

Snapshots are overwritten each time the app goes to the background again and deleted when the task is swiped away. Apps with screen security produce none.

Notifications: what prompted use

Notifications explain why the phone was picked up. With notification history enabled (Android 11+), the protobuf files keep about 24 hours of posted notifications with title and text; dumpsys notification --noredact shows current and recently removed ones. Pair a notification with the next foreground event of the same app to show the user reacted to it.

Installs and first use

A new app's first ACTIVITY_RESUMED should follow its install time (it) in packages.xml. The pair answers questions such as "when did the user start using this app" and "was this app ever opened". An app with foreground services and wakelocks but no activity events at all is typical of background malware; see the malware triage guide.

Building the pattern of life

  1. Normalise times. Convert everything to UTC and keep a column with the source and the original value. Usagestats and Digital Wellbeing are UTC milliseconds; battery anchors are local; notification history is UTC milliseconds. The timeline analysis guide lists the formats.
  2. Establish power and lock state. Mark boots, shutdowns and first unlocks. Gaps between shutdown and startup are gaps in every source.
  3. Screen sessions. Pair screen on and off events into sessions. Everything the user did happened inside one.
  4. Foreground apps per session. Within each session, list resumed and paused activities. Cross-check with battery +top and Digital Wellbeing.
  5. Triggers and outputs. Add notifications (inputs) and messages sent, visits, photos taken (outputs) from the app databases.
  6. Habits. Over the full window, compute when the phone is usually first used in the morning, last used at night, and which apps dominate. Deviations from the habit on the day of interest are often the finding.

A small script over ALEAPP's TSV output or a Timesketch sketch makes this manageable; the timeline guide shows both.

Worked example: was the phone used at 23:10?

A question from a case file: the suspect says the phone was on the bedside table, untouched, from 22:30 to 07:00. The merged sources, in UTC with the local time (UTC+2) in brackets, show:

UTCSourceEvent
21:08:41notification historyWhatsApp notification from a contact, preview visible
21:08:42usagestatsNOTIFICATION_INTERRUPTION for com.whatsapp
21:09:55usagestatsSCREEN_INTERACTIVE
21:09:57usagestatsKEYGUARD_HIDDEN
21:10:02usagestats, Digital Wellbeingcom.whatsapp activity resumed (conversation screen)
21:10:02batterystats+top=u0a187:"com.whatsapp"
21:11:30msgstore.dbOutgoing message in the same chat
21:12:14usagestatsactivity paused, then SCREEN_NON_INTERACTIVE

(21:10 UTC is 23:10 local.) Four independent writers agree that the screen was turned on, the lock screen was dismissed and WhatsApp was on screen for about two minutes, and the app database shows a message sent inside that window. What the sources cannot say is who held the phone; the report should state that explicitly and point to other evidence for attribution.

Multiple users and profiles

Android supports secondary users and work profiles, and each has its own usage record. usagestats, recent tasks and notification history are stored per user ID (/data/system_ce/0/ for the owner, 10, 11 and so on for others), and app UIDs encode the user (u10a123 is app 123 of user 10). A work profile's apps are separate package instances with their own events. Check which users exist (adb shell pm list users), collect each one, and never merge events from different users without labelling them: a work profile's messaging app in the foreground is a different fact from the personal one.

What this evidence cannot prove

  • Who used the phone. Usage events are per user profile, not per person. Face unlock, smart lock and shared passcodes are common. Combine with other evidence (CCTV, witness statements, typing patterns in content).
  • What the user did inside an app. An activity name narrows it; content comes from the app's own data.
  • Intent. A foreground event can be triggered by another app, a notification trampoline or an accidental tap. Short sessions of one or two seconds need caution.
  • Absence beyond the window. No events older than ten days does not mean no use; it means rollover.

Pitfalls

  • Clock changes. If auto_time was off in settings or the clock was changed, local events can be shifted. Battery history prints a new TIME: anchor after a clock change; look for it.
  • Time zones and travel. The device time zone may have changed during the period. Usagestats UTC values are unaffected; local-time sources are.
  • Examiner activity. Your own unlock, Settings navigation and ADB authorisation appear in every source. Exclude them explicitly.
  • Work profiles and secondary users. Each has its own usagestats and recents. Check /data/system_ce/10/ and similar.
  • OEM variations. Samsung, Xiaomi and others add their own usage and battery databases; they can extend windows but need validation.

Summary

  • Capture dumpsys usage, battery, recents and notification output first, with the device clock and time zone.
  • Take a bugreport, then a full file system extraction while the phone is AFU.
  • Use usagestats as the backbone, Digital Wellbeing and battery history as independent confirmation, recents and notifications for context and content.
  • Normalise to UTC, build screen sessions, and report only what two sources support when the stakes are high.