Overview
The Android Bluetooth stack manages wireless communication across both Bluetooth Classic (BR/EDR) and Bluetooth Low Energy (BLE). It is responsible for device discovery, pairing, connection management, and audio streaming. Due to the complexity and historical baggage of the Bluetooth specification, the stack represents one of the most intricate native subsystems in Android.
Architecture: Fluoride and Gabeldorsche
Android's default Bluetooth stack has undergone significant evolution.
Fluoride
For many years, Android utilized "Fluoride," an open-source Bluetooth stack developed by Broadcom and Google. Fluoride is a monolithic C/C++ codebase that implements the core protocols (L2CAP, SDP, RFCOMM) and various profiles. While functional, its monolithic nature made it difficult to maintain and test.
Gabeldorsche (GD)
Google introduced "Gabeldorsche" (often abbreviated as GD), a completely rewritten, modern Bluetooth stack implemented largely in Rust and modern C++. Gabeldorsche aims to provide better modularity, stricter memory safety (crucial for wireless protocols), and improved testability. Android has been transitioning to Gabeldorsche, often running it alongside or underneath legacy Fluoride components during the migration.
Both stacks run within the com.android.bluetooth process (the Bluetooth APK).
The Framework API
Applications interact with Bluetooth via high-level Java APIs.
BluetoothManager and BluetoothAdapter
BluetoothManager is the system service providing access to the BluetoothAdapter. The adapter represents the local device's Bluetooth radio.
BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
// Check if Bluetooth is enabled
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
// Request user to enable Bluetooth
}
Binder IPC and the Bluetooth Process
Calls to the BluetoothAdapter are forwarded via Binder IPC to the BluetoothManagerService running in the system_server. This service manages the lifecycle of the actual Bluetooth process (com.android.bluetooth), which houses the native stack (Fluoride/GD). When Bluetooth is toggled on, the system server starts this process and binds to it.
Bluetooth Profiles
Bluetooth defines functionality through "Profiles," which dictate how devices interact for specific use cases. Android implements these profiles within the native stack and exposes them via proxy objects in the framework.
- A2DP (Advanced Audio Distribution Profile): Handles high-quality unidirectional audio streaming (e.g., to wireless headphones). The stack compresses audio using codecs like SBC, AAC, aptX, or LDAC before transmission.
- HFP (Hands-Free Profile): Handles bidirectional voice audio for phone calls and basic headset controls (answer/reject).
- HID (Human Interface Device): Allows Android to connect to keyboards, mice, and game controllers.
- GATT (Generic Attribute Profile): The foundation for all BLE data transfer. It organizes data into hierarchical Services and Characteristics.
// Connecting to an A2DP profile proxy
bluetoothAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.A2DP) {
BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
// Manage A2DP connections
}
}
// ...
}, BluetoothProfile.A2DP);
Bluetooth Low Energy (BLE)
BLE is optimized for extremely low power consumption and short bursts of data, crucial for wearables, IoT devices, and location beacons.
Scanning and Advertising
Devices broadcast their presence using Advertising packets. Other devices listen for these packets via Scanning.
// Initiating a BLE Scan
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
scanner.startScan(null, settings, new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
int rssi = result.getRssi(); // Signal strength
Log.d("BLE", "Found device: " + device.getAddress() + " RSSI: " + rssi);
}
});
GATT Client Operations
Once connected to a BLE device, an app acts as a GATT Client, reading, writing, and subscribing to characteristics on the GATT Server (the peripheral).
// Connecting to a GATT server
BluetoothGatt gatt = device.connectGatt(context, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices(); // Discover available data points
}
}
});
HCI Transport Layer and HAL
The Host Controller Interface (HCI) is the standardized boundary between the host software stack (Fluoride/GD) and the Bluetooth Controller (the actual hardware chip and firmware).
Bluetooth HAL
The Bluetooth HAL (defined via AIDL/HIDL) is relatively thin. Its primary job is to provide a conduit for HCI packets to flow between the native stack and the kernel driver.
- The stack constructs HCI command packets (e.g.,
HCI_Inquiryto scan for devices). - The HAL passes these to the kernel driver (often via a UART serial interface or USB).
- The controller firmware executes the command over the air.
- The controller sends HCI event packets back up the chain (e.g.,
HCI_Inquiry_Result).
Debugging the Bluetooth Stack
Debugging Bluetooth issues often requires analyzing the HCI traffic to see exactly what commands are failing or what over-the-air packets are corrupted.
HCI Snoop Log
Android includes a developer option to "Enable Bluetooth HCI snoop log". When enabled, the stack writes all HCI packets to a file (typically btsnoop_hci.log on the device).
This file can be pulled and opened in network analyzers like Wireshark. This provides deep visibility into pairing handshakes, L2CAP connections, and BLE attribute exchanges, making it the most powerful tool for diagnosing interoperability issues between Android and peripheral devices.
# Dump Bluetooth service state, including connected devices and active profiles
adb shell dumpsys bluetooth_manager