Bluetooth bugs have an awkward habit: the UI says “connected,” the accessory disagrees, and logcat records only the aftermath. An HCI snoop log captures the commands, events, ACL data, and other traffic exchanged between Android’s Bluetooth host stack and controller, giving you the timeline that ordinary application logs often miss.

What this capture sees—and what it does not

  • It records Android host/controller traffic, so it is ideal for pairing, discovery, GATT, L2CAP, RFCOMM, A2DP signaling, controller errors, and timing analysis.

  • It is not an over-the-air RF capture. Packets lost before the controller receives them and low-level radio interference may require a dedicated Bluetooth sniffer.

  • Bluetooth link-layer encryption does not necessarily hide payloads at the HCI boundary because the host and controller exchange data on their internal interface. Treat the file as sensitive.

  • Some vendor builds change storage paths, rotate logs, omit payloads, or restrict retrieval. A successful toggle does not guarantee a directly readable /sdcard file.

Prerequisites

  • An Android device you are authorized to debug, with Developer options and USB debugging enabled.

  • A current Android SDK Platform Tools installation; verify that the adb binary comes from the expected SDK.

  • A known, narrow reproduction sequence and timestamps so you can correlate HCI traffic with app and system logs.

  • Wireshark for interactive analysis; BlueZ btmon or Wireshark CLI tools are optional on Linux.

1. Authorize and identify the device

Terminalbash
adb version
adb devices -l

Read the device state before capturing

  • adb version records the client/server version for reproducibility. Update Platform Tools if the host is unexpectedly old.

  • adb devices -l lists serials and connection details; use -s SERIAL on every later command when more than one device appears.

  • unauthorized means the device has not accepted this host’s RSA key. Unlock it and approve only a trusted workstation.

  • A missing device is an ADB transport/driver problem, not a Bluetooth logging failure.

2. Enable the Bluetooth HCI snoop log

On the device, open Settings → System → Developer options (the exact menu varies), enable Bluetooth HCI snoop log, then turn Bluetooth off and on. Current AOSP guidance explicitly requires restarting Bluetooth for full logging to take effect.

Create a clean reproduction window

  • Note the wall-clock start time and device timezone.

  • Perform only the pairing, connection, playback, or GATT action that triggers the fault.

  • Note the failure time and stop interacting with Bluetooth. Short captures are faster to interpret and safer to retain.

  • Turn snoop logging off after collection, then restart Bluetooth again.

3. Try the direct file path first

~/captures/android-btbash
adb shell ls -l /sdcard/btsnoop_hci.log
adb pull /sdcard/btsnoop_hci.log ./btsnoop_hci.log

Why this may or may not work

  • Android’s developer-options documentation names /sdcard/btsnoop_hci.log, and some devices expose it there.

  • AOSP also says most devices store logs under protected /data/misc/bluetooth/logs; production ADB shells normally cannot read that directory.

  • The legacy /sdcard/btlog/ location is vendor-specific. Do not parse bt_stack.conf and assume its path is externally readable on every Android release.

  • If the pull says “No such file” or “Permission denied,” use the bug-report path rather than weakening device security or rooting a production phone.

4. Collect an ADB bug report when direct pull fails

~/captures/android-btbash
adb bugreport ./android-bugreport

Risk level: caution. Review the command before running it.

What the command collects

  • adb bugreport DIRECTORY asks Android to generate a diagnostic archive and saves it on the host; collection can take several minutes.

  • The archive includes far more than Bluetooth data—system state, logs, identifiers, installed-package information, and possibly user-sensitive diagnostics.

  • Use a dedicated access-controlled directory and never attach the unreviewed archive to a public issue.

  • Keep Bluetooth snoop logging enabled until the bug report finishes so the relevant in-memory/log data is captured.

5. Locate the text bug report

~/captures/android-btbash
unzip -l android-bugreport/*.zip | grep -E 'bugreport.*\.txt$'

Use the actual archive layout

  • Modern adb bugreport commonly creates a directory containing a ZIP; device builds can name artifacts differently.

  • unzip -l lists content without extracting sensitive files.

  • The regular expression narrows the listing to the main text report used by AOSP’s extraction tool.

  • If your shell path differs, substitute the exact ZIP shown by find ./android-bugreport -maxdepth 2 -type f; do not blindly copy a wildcard that matches multiple reports.

6. Extract BTSnoop data with AOSP btsnooz

Obtain btsnooz.py from the system/bt/tools/scripts directory in the matching Android Open Source Project source tree. Review the script and keep its provenance with the incident. Extract the text report using the exact member name found above, then convert it.

~/captures/android-btbash
unzip -p android-bugreport/BUGREPORT.zip BUGREPORT.txt > bugreport.txt
python3 ./btsnooz.py bugreport.txt > btsnoop_hci.log

Risk level: caution. Review the command before running it.

Understand the placeholders and output

  • Replace BUGREPORT.zip and BUGREPORT.txt with the literal archive and member names from your collection.

  • unzip -p streams one archive member to standard output; the redirection writes a sensitive local copy.

  • AOSP’s btsnooz.py decodes the Bluetooth section embedded in the text report into BTSnoop format. It does not magically recover traffic that was never logged.

  • A zero-byte or error-filled output means extraction failed; preserve the original archive and inspect the script’s diagnostic output before retrying.

7. Validate and open the capture

~/captures/android-btbash
capinfos btsnoop_hci.log
wireshark btsnoop_hci.log

What validation tells you

  • capinfos identifies the capture format, packet count, timestamps, and duration without requiring you to trust a filename.

  • Wireshark decodes HCI commands/events and higher Bluetooth protocols when enough context exists. Use a display filter; never delete packets from the evidentiary original.

  • Keep an immutable original and analyze a working copy if the capture supports a formal incident or vendor escalation.

  • If Wireshark reports an unsupported/corrupt file, confirm btsnooz.py completed and that shell errors were not redirected into the output.

Useful Wireshark starting points

  • Filter btatt for Bluetooth Low Energy Attribute Protocol exchanges and inspect request/response handles and error codes.

  • Filter bthci_evt for controller events, including connection-complete and disconnection reasons.

  • Filter bthci_cmd to see what Android asked the controller to do.

  • Use frame.time_relative and your reproduction timestamps to find the first unexpected response, not merely the final disconnect.

  • Correlate the capture with adb logcat -b all -v threadtime collected over the same narrow window when framework/app context matters.

When the capture is empty or missing

  • Toggle snoop logging off/on, restart Bluetooth, reproduce again, and collect the bug report before rebooting the phone.

  • Confirm the issue occurred after logging began; historical packets cannot be reconstructed.

  • Check whether enterprise policy or the OEM build disables full HCI logging.

  • On userdebug/eng AOSP builds, platform engineers may inspect protected logs with authorized elevated access; this is not an instruction to root consumer devices.

  • For intermittent failures, automate timestamps and related logcat collection, but keep retention and consent boundaries explicit.

Primary references