Android Call Log: calllog.db
Where Android stores incoming, outgoing, missed and blocked calls: calllog.db columns, call types, SIM and VoIP accounts, Samsung logs.db and limits.
- Location
- /data/user_de/0/com.android.providers.contacts/databases/calllog.db
- Proves
- Which calls the device placed, received, missed, rejected or blocked, with which number, when, for how long, and through which SIM or calling app
- Timestamps
- calls.date (call start) and last_modified in Unix milliseconds (UTC); duration in seconds
- Access
- Full file system (root, exploit or agent); DE storage, so readable in BFU by a privileged extraction. Logical: provider view through an agent app or, on some builds, adb shell content query. Bugreport: short masked history only. Not in ADB backup.
- Retention
- AOSP trims the log to about the 500 most recent entries; the exact rule varies by release and OEM. Deleted rows can persist in the WAL and freelist
- Collection
- Full file system extraction, Agent-based logical extraction, adb shell content query, SMS Backup & Restore XML (user export)
Tools
Compare all tools- ALEAPPCLI · open source
- AndrillerGUI · open source
- AutopsyGUI · open source
- sqlite3CLI · open source
- DB Browser for SQLiteGUI · open source
- contentCLI · on the device
- Cellebrite UFEDPlatform · commercial
- Magnet AXIOMPlatform · commercial
- Oxygen Forensic DetectivePlatform · commercial
- MSAB XRYPlatform · commercial
What it is
The Android call log is maintained by the Telecom framework and stored by the contacts provider's CallLogProvider. Every call handled by the system dialer path (SIM calls, and calls from VoIP apps that integrate with Telecom as a phone account) becomes a row in the calls table, exposed to apps as content://call_log/calls. It is the phone-side counterpart of carrier call detail records, with the advantage of including blocked and rejected calls and the handset's own view of the duration.
Since Android 7 the call log has its own database, calllog.db. Before that, the same calls table lived inside contacts2.db.
Where it lives
| Build | Path | Notes |
|---|---|---|
| AOSP-based, Android 8 to 16 | /data/user_de/0/com.android.providers.contacts/databases/calllog.db | Device-encrypted storage (the call log is available during direct boot). Some tools list /data/data/com.android.providers.contacts/databases/: search for calllog.db* anywhere in the extraction |
| Upgraded devices | contacts2.db, table calls | Legacy table from before the migration, usually empty; check it on phones upgraded from Android 6 or earlier |
| Many Samsung builds | /data/data/com.sec.android.provider.logsprovider/databases/logs.db | Samsung's logs provider keeps its own logs table (calls and message logs) alongside the AOSP store |
| Dialer apps | e.g. /data/data/com.google.android.dialer/databases/ | Google Phone keeps caches and annotations; the authoritative record stays in calllog.db |
Secondary users and work profiles have their own provider under /data/user_de/<user>/.
What it proves
- That the device registered a call to or from a number, with the direction and outcome.
- When the call started (
date) and how long it lasted in seconds (duration, 0 for missed, rejected or blocked calls). - Which phone account handled it: a specific SIM (
subscription_id,phone_account_address) or a calling app (subscription_component_name). - Whether it was a video call (
featuresbit 0x1), whether the number was withheld (presentation), and, on recent releases, why a call was blocked or missed.
It does not prove who spoke, and an entry can be deleted by the user or rewritten by an app holding WRITE_CALL_LOG.
Key fields
| Column | Meaning |
|---|---|
number, presentation | Dialled or caller number; 1 allowed, 2 restricted, 3 unknown, 4 payphone |
type | 1 incoming, 2 outgoing, 3 missed, 4 voicemail, 5 rejected, 6 blocked, 7 answered on another device |
date, duration | Start time (ms) and duration (s) |
subscription_component_name | Telecom connection service, e.g. com.android.phone/com.android.services.telephony.TelephonyConnectionService for SIM calls |
subscription_id, phone_account_address | Phone account (SIM) identifier and its number where known |
name, numbertype, numberlabel | Contact name and label cached at call time |
geocoded_location, countryiso | Region guessed from the number prefix, not the caller's location |
features, data_usage | Bitmask (video, Wi-Fi calling, HD audio on newer builds) and bytes used |
new, is_read, last_modified | Missed-call notification state, read flag, last change (ms) |
block_reason, call_screening_app_name, missed_reason | Present on newer releases: why the call was blocked or missed and by which screening app |
Timestamps
date and last_modified are Unix milliseconds in UTC; duration is seconds. The end of a call is date + duration*1000.
SELECT _id, number,
CASE type WHEN 1 THEN 'in' WHEN 2 THEN 'out' WHEN 3 THEN 'missed' WHEN 4 THEN 'voicemail'
WHEN 5 THEN 'rejected' WHEN 6 THEN 'blocked' WHEN 7 THEN 'answered elsewhere' END AS kind,
datetime(date/1000, 'unixepoch') AS start_utc,
duration,
datetime((date + duration*1000)/1000, 'unixepoch') AS end_utc,
name, subscription_component_name, subscription_id,
datetime(last_modified/1000, 'unixepoch') AS modified_utc
FROM calls ORDER BY date;
last_modified much later than the call's end is worth a look: the row was edited (read flag, cached name) or rewritten.
Retention
AOSP caps the call log: when a new call is added, the provider deletes the oldest entries beyond roughly 500. How the cap is applied (globally or per phone account) has varied between releases, and OEM builds can change it, so never infer "no calls before X" from the oldest row alone. Users can delete single entries or clear the log, and apps with WRITE_CALL_LOG can modify it. Deleted rows may remain in the WAL and in free pages of calllog.db for a while.
Collection
- Full file system extraction gives
calllog.dbwith its sidecars. As with SMS, it sits in device-encrypted storage, so it is reachable in BFU by a privileged extraction. - Logical: agents read
content://call_log/calls. On some builds the ADB shell is allowed to query it directly:adb shell content query --uri content://call_log/calls --projection number:date:duration:type. Expect no deleted rows. - Bugreport:
dumpsys telecomkeeps a short in-memory history of recent calls with timings and masked numbers, useful to corroborate but not a replacement. - User export: SMS Backup & Restore writes
calls-<date>.xml, which Messaging Forensics can read along with SMS.
Parsing
ALEAPP, Andriller and Autopsy report the call log directly; commercial suites merge it with Samsung logs.db and dialer caches. For custom work, sqlite3 or DB Browser for SQLite with the query above is enough. When both calllog.db and Samsung's logs.db exist, parse both and compare: the OEM store sometimes keeps entries the AOSP store trimmed.
Investigator tips
type = 6(blocked) andtype = 5(rejected) rows show contact attempts the user never saw ring: valuable in harassment cases.- Calls from WhatsApp, Signal or Telegram normally do not appear here; they live in each app's own database (WhatsApp's
call_logtable in msgstore.db). - The cached
namereflects the contact at call time. Compare with the current contacts entry to show a contact was renamed or deleted afterwards. - Pair each call with SMS threads to the same number in mmssms.db to reconstruct a conversation across channels.
- A cluster of old calls inserted with consecutive
_idvalues and identicallast_modifiedsuggests a restore from backup rather than real activity.