Google Messages: bugle_db, SMS, MMS and RCS Chats
Google Messages' bugle_db database: RCS chats that never reach mmssms.db, SMS and MMS copies, participants, parts and attachments, timestamps and access.
- Location
- /data/data/com.google.android.apps.messaging/databases/bugle_db
- Proves
- SMS, MMS and RCS conversations handled by Google Messages, their participants, message text and attachments, direction, send and receive times, read and delivery state
- Timestamps
- Unix milliseconds (UTC): messages.sent_timestamp, messages.received_timestamp, parts.timestamp, conversations.sort_timestamp
- Access
- Full file system (root, exploit or agent); credential-encrypted sandbox, so AFU only. Logical: not reachable, and agents that read the SMS provider miss RCS entirely. Not in ADB backup on current app versions.
- Retention
- Until the user deletes the message or conversation, or the app data is cleared; RCS content is not mirrored to the SMS provider, so deleting it here removes the main local copy
- Collection
- Full file system extraction, adb shell dumpsys activity (process state only)
Tools
Compare all toolsWhat it is
Google Messages (com.google.android.apps.messaging) is the default SMS app on Pixel phones and on many other Android devices, including a large share of Samsung handsets sold since 2021 in some regions. Besides sending SMS and MMS through the telephony provider, it is the main client for RCS chat: typing indicators, read receipts, high-resolution media and, for chats between Google Messages users, end-to-end encryption.
The app keeps its own SQLite database, bugle_db (the internal project name was "Bugle"). SMS and MMS messages exist twice: in the system mmssms.db and in bugle_db. RCS messages, on the builds examined publicly, exist only in bugle_db. An extraction that stops at the SMS provider therefore misses every RCS conversation, which on a modern phone can be most of the native messaging.
Where it lives
| Item | Path | Notes |
|---|---|---|
| Messages database | /data/data/com.google.android.apps.messaging/databases/bugle_db (+ -wal, -shm) | Conversations, messages, parts, participants |
| Preferences | /data/data/com.google.android.apps.messaging/shared_prefs/ | RCS provisioning state, selected SIM, feature flags |
| Attachments | Inside the app sandbox (files/, cache/) or referenced as content:// URIs | Exact folders vary between app versions: follow the parts rows |
| SMS and MMS copy | /data/data/com.android.providers.telephony/databases/mmssms.db (or /data/user_de/0/...) | Linked from bugle_db through sms_message_uri |
The paths are the same on Android 8 to 16 because the database belongs to the app, not the OS. Other OEM messaging apps (Samsung Messages, for example) keep RCS in their own stores with different schemas: verify on your build.
What it proves
- Every conversation shown in Google Messages, including RCS one-to-one and group chats with their names.
- For each message: the conversation, the sender participant, whether it was incoming or outgoing, the text, attachments, and when it was sent and received.
- Read and delivery state, including RCS read receipts where both parties allow them.
- Which SIM (subscription) a message used on dual-SIM phones.
- The link between an SMS or MMS in
bugle_dband its row inmmssms.db, which helps detect a message deleted in one store but not the other.
It does not prove the device owner typed a message, and end-to-end encryption does not hide anything here: E2EE protects RCS in transit, while the local database is plain SQLite protected by credential-encrypted storage.
Key fields
| Table | Columns | Meaning |
|---|---|---|
conversations | _id, name, latest_message_id, sort_timestamp, participant_normalized_destination | One row per thread |
messages | _id, conversation_id, sender_id, sent_timestamp, received_timestamp, message_protocol, message_status, read, seen, sms_message_uri | One row per message |
parts | message_id, text, content_type, uri, width, height, timestamp | Text body and attachments (one message can have several parts) |
participants | _id, normalized_destination, display_destination, full_name, contact_id, sub_id | Phone numbers and names, with the device contact ID |
conversation_participants | conversation_id, participant_id | Membership of each conversation |
message_protocol separates SMS, MMS and RCS, and message_status encodes sent, delivered, failed and received states. The numeric codes are not documented and have changed between app versions: calibrate them against messages whose type you know. Column names also drift, so run .schema before reusing a query.
Timestamps
All times are Unix epoch milliseconds in UTC.
SELECT m._id, c.name AS conversation,
p.display_destination AS sender, p.full_name,
datetime(m.sent_timestamp/1000, 'unixepoch') AS sent_utc,
datetime(m.received_timestamp/1000, 'unixepoch') AS received_utc,
m.message_protocol, m.message_status, pa.text, pa.content_type
FROM messages m
JOIN conversations c ON c._id = m.conversation_id
LEFT JOIN participants p ON p._id = m.sender_id
LEFT JOIN parts pa ON pa.message_id = m._id
ORDER BY m.received_timestamp;
On outgoing messages received_timestamp is usually the local creation time; on incoming RCS messages sent_timestamp comes from the sender's side and can differ from the device clock.
Retention
Messages remain until the user deletes them or the conversation, or clears the app's storage. Google Messages can auto-delete one-time passwords after 24 hours when that option is on, and some builds offer a trash for recently deleted conversations. Deleted rows often survive for a while in the WAL and in free pages of bugle_db, so collect all three files.
Collection
- Full file system extraction (AFU): the only reliable route to
bugle_dband attachments. - Logical: an agent reading
content://smsandcontent://mmsreturns SMS and MMS only. Document that RCS was not covered if that is all you have. - Google Messages for web and Google account backups are separate, cloud-side sources with their own legal process.
Parsing
- ALEAPP has a Google Messages module that reads
bugle_dband joins participants and parts. sqlite3or DB Browser for SQLite with the query above for review and validation.- Commercial suites parse Google Messages as a separate app from the SMS provider; check that their RCS section is populated.
Investigator tips
- Diff
bugle_dbagainst mmssms.db: an SMS present in one and not the other points to deletion or to a period when another app was the default SMS handler. - Resolve
participants.contact_idthrough contacts2.db instead of trusting a cachedfull_name. - RCS messages that arrive while the phone is locked may still show up in notification history after the chat is deleted.
- Use usagestats to show Messages was in the foreground when an outgoing message was created.
- The messaging apps guide compares Google Messages with WhatsApp, Signal and Telegram.