Skip to content

Communications

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)

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

BuildPathNotes
AOSP-based, Android 8 to 16/data/user_de/0/com.android.providers.contacts/databases/calllog.dbDevice-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 devicescontacts2.db, table callsLegacy 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.dbSamsung's logs provider keeps its own logs table (calls and message logs) alongside the AOSP store
Dialer appse.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 (features bit 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

ColumnMeaning
number, presentationDialled or caller number; 1 allowed, 2 restricted, 3 unknown, 4 payphone
type1 incoming, 2 outgoing, 3 missed, 4 voicemail, 5 rejected, 6 blocked, 7 answered on another device
date, durationStart time (ms) and duration (s)
subscription_component_nameTelecom connection service, e.g. com.android.phone/com.android.services.telephony.TelephonyConnectionService for SIM calls
subscription_id, phone_account_addressPhone account (SIM) identifier and its number where known
name, numbertype, numberlabelContact name and label cached at call time
geocoded_location, countryisoRegion guessed from the number prefix, not the caller's location
features, data_usageBitmask (video, Wi-Fi calling, HD audio on newer builds) and bytes used
new, is_read, last_modifiedMissed-call notification state, read flag, last change (ms)
block_reason, call_screening_app_name, missed_reasonPresent 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.db with 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 telecom keeps 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) and type = 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_log table in msgstore.db).
  • The cached name reflects 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 _id values and identical last_modified suggests a restore from backup rather than real activity.

See also