Android Bluetooth is easier to debug once you stop treating it as one service. A scan request crosses process, language, protocol, vendor, and hardware boundaries; a failure at each boundary leaves different evidence. This guide gives those boundaries names and shows where to look.
The short architectural answer
An app uses android.bluetooth APIs. Binder carries privileged work into Android’s Bluetooth process/module. Java services and profile implementations cross JNI into the native host stack, which implements Bluetooth protocols and talks through the device’s vendor HAL/transport to the controller using HCI commands, events, and data.
Current AOSP layer map
App / system component
android.bluetooth APIs
│ Binder IPC + permission checks
▼
Bluetooth framework/process/module
AdapterService + profile services
│ JNI callbacks and native calls
▼
Native Bluetooth host stack
GAP/GATT, SDP, L2CAP, RFCOMM, profiles, security
│ Bluetooth HAL / vendor boundary
▼
Vendor transport integration
UART / USB / shared transport, firmware, power control
│ HCI commands, events, ACL/SCO/ISO data
▼
Bluetooth controller + radioConceptual call path; exact processes and interface versions depend on the Android branch and product.
How to read this map
Binder is the application/framework process boundary; JNI is the Java/native boundary. They are not interchangeable terms.
The host stack runs on the application processor; the controller executes link-layer/radio work and reports events over HCI.
A public API returning an error does not prove the radio failed—the request may have been rejected by permissions, state, policy, service lifecycle, or a profile.
Vendor integration and HAL transport differ by release and product. Inspect source, VINTF manifest, running services, and logs on the exact build.
1. App-facing framework APIs
Applications normally enter through classes such as BluetoothManager, BluetoothAdapter, BluetoothDevice, BluetoothGatt, and profile proxies. These objects do not drive UART or issue HCI commands directly. They validate state and arguments, enforce SDK-visible behavior, and invoke system-owned interfaces.
Classic Bluetooth: discovery, bonding, sockets, and profiles such as A2DP, HFP, HID, and PAN.
Bluetooth Low Energy: scanning, advertising, GATT client/server operations, PHY/data-length features, and newer LE Audio capabilities when supported.
Permissions: behavior is release- and target-SDK-sensitive. Modern Android uses nearby-device permissions such as
BLUETOOTH_SCANandBLUETOOTH_CONNECT; older releases tied some scans to location permissions.Asynchrony: most meaningful results arrive through callbacks, broadcasts, Binder callbacks, or profile state changes—not from the initiating method alone.
2. Binder and the Bluetooth process
Binder separates app callers from privileged Bluetooth implementation code. The Bluetooth side owns adapter state, bonding, discovery, profile services, database/state coordination, and permission/policy enforcement. AdapterService remains a useful orientation point in current AOSP, but it is not the whole stack.
scan request
app → API proxy → Binder → Bluetooth service
→ JNI → native scanning/GAP logic → HAL/HCI command
controller result
HCI event → vendor/HAL → native stack → JNI callback
→ service filtering/state → Binder callback → appA successful operation crosses down the stack and reports state back asynchronously.
What the return path teaches
The callback path is as important as the request path; missing results can be caused by filtering, permissions, process death, or callback registration even when HCI traffic exists.
Binder transaction failures point above the native protocol stack; HCI command timeout/reset evidence points near the controller path.
Framework-visible device data may be transformed, cached, redacted, or permission-filtered before reaching the app.
Correlate one user action with timestamps across app logs, Bluetooth service dumps, system logs, and—when authorized—HCI capture.
3. JNI and the native host stack
JNI code under the Bluetooth module connects Java service objects and callbacks to native interfaces. Below it, the AOSP host stack handles protocol state machines, security, discovery, connections, GATT, L2CAP, SDP, RFCOMM, and profiles. Fluoride is commonly used as the modern name; GD refers to newer modularized components within its evolution, not a second physical controller.
JNI bugs often look like lost callbacks, stale native handles, lifecycle races, conversion errors, or exceptions around service restart.
Native stack bugs often expose state-machine transitions, protocol status codes, queue congestion, timeouts, or peer interoperability patterns.
Profile behavior can involve audio, telephony, media, networking, or companion services outside the Bluetooth module boundary.
Never assume a source filename observed on
mainexists unchanged on a vendor branch; search the checked-out tree and record its build fingerprint/tag.
4. HAL, vendor implementation and HCI
The vendor boundary connects the AOSP host stack to chipset-specific implementation, firmware loading, power sequencing, and transport. Current AOSP Bluetooth documentation still describes the Bluetooth vendor interface using HIDL, even though Android’s general HAL direction favors stable AIDL and HIDL is deprecated for new HAL design. The device manifest and branch are authoritative.
Android host stack
│
├─ Android HAL/interface lifecycle, errors, callbacks
│
Vendor implementation / transport driver
│
├─ HCI command packets ───────────────► controller
├─ HCI event packets ◄─────────────── controller
└─ ACL / SCO / ISO data ◄──────────────► controllerHCI is a protocol boundary; HAL is an Android software integration boundary.
Keep these boundaries separate
A HAL service can be registered while the controller transport is broken. Service presence is necessary evidence, not proof of radio health.
HCI snoop logs show host/controller protocol traffic, not over-the-air packets and not every vendor-internal diagnostic.
UART framing, USB enumeration, shared-transport arbitration, firmware download, GPIO/regulator sequencing, and sleep/wake faults sit below normal profile logic.
Vendor-specific commands and events require chipset documentation; do not guess opcodes or replay captures on production hardware.
Android release map: what moved
Early Android / BlueDroid era: documentation referenced
packages/apps/Bluetooth,external/bluetooth/bluedroid, legacyhardware/libhardwareheaders, andlibbt-vendor. Preserve these paths only for matching historical branches.Modern source tree: AOSP places the app/JNI code under
packages/modules/Bluetooth/android/appand the native stack underpackages/modules/Bluetooth/system.Android 13: Bluetooth was introduced as an optional Mainline module using an APEX package boundary.
Android 16 and later: AOSP documentation describes the module as updatable and containing a certified dual-mode host stack. Product packaging can still differ, so verify the installed module rather than inferring from OS version alone.
Find the implementation in an AOSP checkout
rg -n 'class AdapterService|class BluetoothManagerService' packages/modules/Bluetooth frameworks/base
rg -n 'android.hardware.bluetooth|IBluetoothHci' hardware/interfaces packages/modules/Bluetooth
rg -n 'libbluetooth_jni|bluetooth.default' packages/modules/Bluetooth hardwareWhy source search beats memorized paths
rg -nreports the file and line containing each symbol; results describe the checked-out branch, not a generic online branch.BluetoothManagerServiceand module services live on different sides of framework/module boundaries, so search both roots.HAL interface names and build targets reveal what the branch supports, but product manifests and runtime service registration decide what the device uses.
Generated files and vendor repositories may be outside these roots. Extend the search deliberately rather than assuming no implementation exists.
Inspect a running Android device
adb shell getprop ro.build.fingerprint
adb shell dumpsys bluetooth_manager
adb shell service list | grep -i bluetooth
adb shell dumpsys package com.android.bluetoothRead the evidence in order
Record the build fingerprint first; Bluetooth behavior and source paths are meaningless without a release/product identity.
dumpsys bluetooth_manageris privileged diagnostic state whose fields vary by release. Capture it before and after one reproduced action.The Binder service list confirms registered framework services, not successful HAL/controller operation.
Package output can reveal APK/APEX placement and versioning, but package names differ on AOSP, GMS, and vendor products.
Diagnostics may contain device names, addresses, account/package data, and connection history. Redact before sharing.
Correlate logs without drowning in noise
adb logcat -c
adb logcat -v threadtime | grep -Ei 'Bluetooth|bt_stack|btif|hci|AdapterService'A disciplined trace is more useful than a huge log
Clearing logcat discards the current volatile buffer; use it only on an authorized test device after preserving evidence you need.
Start capture immediately before one action, note the exact time, stop after the failure, and keep an unfiltered copy when possible.
Tag names change across releases and vendor builds; broad filtering is discovery, not a permanent diagnostic recipe.
Never publish raw logs containing Bluetooth addresses, names, serials, phone data, or application identifiers.
Symptom-to-layer debugging
SecurityException before scanning: begin with app permissions, attribution, target SDK, foreground/background rules, and policy—not the controller.
Bluetooth service absent or repeatedly restarts: inspect Binder/service lifecycle, crashes, tombstones, module/package state, SELinux denials, and dependencies.
Native enable timeout or controller reset: inspect HAL service, transport, firmware, power sequencing, HCI timeouts, and vendor logs.
Discovery runs but one peer is missing: separate Classic inquiry from LE scan; check filters, PHY/advertising mode, privacy/address rotation, controller capabilities, and peer behavior.
Pairs but profile fails: pairing/security success does not prove A2DP, HFP, GATT, or another profile is enabled, compatible, connected, and routed.
HCI shows events but app sees nothing: follow JNI callbacks, service filtering/cache, Binder callbacks, permissions, app lifecycle, and scan/profile filters.
A repeatable investigation workflow
Identify device, build fingerprint, Android version, module/package version, chipset, transport, and exact peer.
Define one failing operation and its expected observable result.
Locate the corresponding public/System API and Binder-facing service on the matching source branch.
Capture framework/service state and timestamped logs around one reproduction.
Decide whether evidence crosses Binder, JNI, native stack, HAL, and HCI boundaries.
Change one variable—peer, app, profile, cable/transport condition, build, or controller firmware—and compare.
Confirm the fix at the user-visible layer and ensure it survives Bluetooth toggle, process restart, reboot, suspend, and reconnect as relevant.
Before calling the issue fixed
Retest the exact peer and operation that originally failed, then test one known-good peer to separate interoperability from regression.
Verify adapter toggle, process restart, reboot, suspend/resume, reconnect, and airplane-mode transitions relevant to the product.
Confirm that logs are free of new crashes, repeated resets, permission denials, and silent fallback—not merely that the UI appears connected.
Document the build, module version, controller firmware, reproduction, evidence boundary, code change, and regression test so the diagnosis survives the next rebase.
Related Android Bluetooth guides
Capture controller traffic with the Android Bluetooth HCI snoop log guide.
Trace profile startup in how Android enables Bluetooth profiles and services.
Use the ADB over Bluetooth workflow only on supported, authorized development devices.
Primary references
AOSP’s Bluetooth architecture documents the app, Binder, JNI, native stack, and vendor layers.
AOSP’s Bluetooth Mainline module documents its Android 13 introduction, APEX boundary, dependencies, and Android 16+ update model.
The live AOSP Bluetooth module source tree is the branch-level authority for paths and implementations.
AOSP’s HAL overview explains binderized HAL boundaries and the platform-wide AIDL direction.
Comments and corrections