Android Notification History and notification_log.db
Android notification evidence: Android 11+ notification_history protobuf files with title and text, notification_log.db on 8 to 10, and dumpsys notification.
- Location
- /data/system_ce/<user>/notification_history/ (Android 11+), /data/system/notification_log.db (Android 8 to 10)
- Proves
- Which app posted a notification and when, and on Android 11+ with history enabled, the notification's title and text: message previews, sender names, one-time codes
- Timestamps
- notification_history: posted time in Unix milliseconds (UTC), files named by Unix milliseconds; notification_log.db: Unix milliseconds
- Access
- Full file system (root, exploit or agent). Android 11+ history is credential-encrypted, so AFU only; notification_log.db sits in device-encrypted /data/system. Logical and bugreport: dumpsys notification lists current and recently removed notifications. Not in ADB backup.
- Retention
- Android 11+ history: only when the user enabled Notification history, about the last 24 hours; notification_log.db: a bounded rolling window; dumpsys: in memory until reboot
- Collection
- Full file system extraction, adb shell dumpsys notification --noredact, adb bugreport
Tools
Compare all toolsWhat it is
Every notification an app posts passes through NotificationManagerService. Android keeps three traces of that traffic, each with different reach:
- Notification history (Android 11 and later): when the user turns on Settings > Notifications > Notification history, the system writes dismissed and expired notifications to protobuf files, including title and text. It is off by default, but some users enable it precisely to recover dismissed messages.
- notification_log.db (Android 8 to 10): a SQLite log of notification events kept for system metrics, mostly metadata.
- The live service state:
dumpsys notificationprints current notifications and an in-memory archive of recently removed ones.
Because messaging apps put sender names and message previews in notifications, these traces can preserve content that was later deleted from the app, or that sits in an app you cannot decrypt, such as Signal.
Where it lives
| Item | Path | Notes |
|---|---|---|
| History files | /data/system_ce/<user>/notification_history/history/<epoch-ms> | Protobuf, one file per period |
| Pending deletions | /data/system_ce/<user>/notification_history/ | Other bookkeeping files next to history/ |
| Event log (8 to 10) | /data/system/notification_log.db | SQLite, device-encrypted |
| Policy | /data/system/notification_policy.xml | Per-app channel settings, blocked apps, DND rules, snoozed notifications |
| Setting | settings_secure: notification_history_enabled | Whether history was enabled |
OEM skins keep the AOSP files; Samsung One UI exposes the same history feature. Verify the paths on your build.
What it proves
- An app posted a notification at a given time, identified by package, channel and user.
- On Android 11+ with history enabled: the notification title and text, which for messaging apps usually means the sender and the start of the message; for banks and services, one-time codes and transaction alerts.
- Conversation shortcuts and IDs for messaging-style notifications on recent releases.
- In
notification_policy.xml: which apps had notifications blocked, silenced or snoozed, and Do Not Disturb rules.
Notification text is what the app chose to show: many apps hide content on the lock screen or when the user asks them to, and a notification does not prove the user read it.
Key fields
| Field (history protobuf) | Meaning |
|---|---|
package, uid, user_id | Posting app |
channel_id, channel_name | Notification channel (for example "Messages", "Calls") |
posted_time_ms | When it was posted, Unix milliseconds |
title, text | Displayed title and text |
conversation_id | Conversation shortcut on messaging notifications |
icon | Small icon reference |
Strings such as package and channel names are stored once in a string pool at the start of the file and referenced by index. notification_log.db has a log table with the event time, package, notification ID, tag and event type (posted, clicked, dismissed) on most builds.
Timestamps
History files are named after a Unix millisecond timestamp, and each notification carries posted_time_ms. Both are UTC.
# Inspect a history file without the schema
protoc --decode_raw < notification_history/history/1789400592120 | head -60
# Android 8-10 event log
sqlite3 notification_log.db "SELECT datetime(event_time_ms/1000,'unixepoch'), pkg, event_type FROM log ORDER BY event_time_ms DESC LIMIT 20;"
Column names in notification_log.db vary; check .schema log first.
Retention
The Android 11+ history keeps roughly the last 24 hours, the window the Settings screen shows, and older files are deleted. Turning the feature off deletes the history. notification_log.db keeps a bounded window. The dumpsys archive is in memory and lost at reboot.
Collection
- Full file system extraction (AFU): copy
notification_history/andnotification_policy.xml, andnotification_log.dbon older releases. - Logical:
adb shell dumpsys notification --noredact > dumpsys_notification.txtas early as possible. Without--noredact, text is masked on recent releases. - Bugreport: includes a notification dump, usually redacted.
Parsing
- ALEAPP parses Android 11+ notification history and older notification databases.
- blackboxprotobuf or
protoc --decode_rawfor manual inspection when a parser is out of date. - Commercial suites include notification history in their timelines.
Investigator tips
- Check
notification_history_enabledin settings before concluding there is no history. - Compare message previews with Google Messages, Telegram or WhatsApp databases: a preview with no matching row suggests deletion.
- Pair a notification with the next usagestats foreground event of the same app to show the user opened it.
- Stalkerware often holds notification listener access to read other apps' notifications; see the malware triage guide.