AndroidIntermediateMessaging

Google Messages database (bugle_db)

Google Messages app store: one parts row per text or attachment, joined to its message, sender and conversation; timestamps in Unix milliseconds.

01Location

  • */com.google.android.apps.messaging/databases/bugle_db (with any -wal, -shm or -journal companion files)

02Questions it answers

  • Which texts and attachments were exchanged in Google Messages, with whom, and when?
  • Which conversation does a given part belong to, and under what name?
  • Was a part sent from this device or received from another participant, according to the sub_id rule?

03Format and versions

FormatSQLite database. ALEAPP reads the tables parts, messages, participants and conversations: parts.message_id = messages._id, messages.sender_id = participants._id and parts.conversation_id = conversations._id. The result has one row per part, that is, per text or attachment, not per message.
Applies toALEAPP's test images cover Android 13 to 16 and Google Messages version codes from 161637900 to 311755063. Older bugle_db generations lack parts.file_size_bytes and parts.local_cache_path; ALEAPP reads those columns as NULL when absent.

04Key fields

FieldWhat it tells you
parts.textText of the part.
parts.content_typeContent type of the part; ALEAPP reports it as the message type.
parts.file_size_bytes / parts.local_cache_pathAttachment size and local cache path. A size of -1 is shown by ALEAPP as N/A. These columns are absent in older generations.
participants.display_destinationSender as ALEAPP reports it in the Message Sender column.
participants.sub_idALEAPP derives direction from it: -2 marks a participant other than the device's own, any other value is treated as the self participant, and NULL leaves direction blank.
conversations.name / parts.conversation_idConversation name and the identifier that groups parts into a conversation.

05Timestamps

FieldEncodingNote
parts.timestampUnix epoch, millisecondsALEAPP divides by 1000 and renders the value as UTC.

Decode raw values with the Timestamp decoder and convert local wall-clock times with the Local time to UTC.

06Examination workflow

  1. Preserve bugle_db together with its -wal, -shm and -journal companion files.
  2. Record the schema first: check whether parts.file_size_bytes and parts.local_cache_path exist before relying on them.
  3. Convert parts.timestamp from milliseconds to UTC and keep the raw value beside it.
  4. Count messages by messages._id, not by the number of rows, because each text or attachment is its own row.
  5. Correlate senders with the contacts and call-log databases and with the telephony provider's SMS/MMS store.

07Interpretation pitfalls

  • The direction rule comes from the AOSP Messaging source; the Google Messages build is not open source, so report direction as a parser inference.
  • A row with a NULL sub_id has no direction in ALEAPP's output; do not fill it in.
  • In WAL mode recent changes may exist only in the -wal file until a checkpoint; reading the main file alone can miss or misstate records.

09Sources

  1. ALEAPP — scripts/artifacts/googleMessages.py Alexis Brignoni et al. (GitHub) · checked 2026-10-23
  2. SQLite — Write-Ahead Logging SQLite · checked 2026-10-14

Contact and service requests

Contact us about examination services related to this page, support for expert witnesses, or collaboration. Please do not attach evidence files or personal data to your email.

Contact page →