android-auto
A Rust implementation of the Android Auto protocol — both a reusable library and a working head unit application. Connect an Android phone to a Linux host and get a full Android Auto experience, including wireless connection via Bluetooth.
Table of Contents
- What is this?
- How it works
- Features
- Prerequisites
- Building
- Running the head unit
- Using the library
- Architecture
- Contributing
- License
What is this?
android-auto is two things in one repository:
- A library crate (
android-autoon crates.io) that implements the Android Auto wire protocol. You can embed it in your own Rust application to build a custom head unit. - A head unit example application (
examples/main/) that demonstrates the library in action, allowing a Linux machine to act as an Android Auto head unit for a connected phone.
How it works
Android Auto uses a binary framing protocol over a TLS-secured transport. The phone (acting as the server) and the head unit (acting as the client) exchange protobuf-encoded messages. At a high level:
- Transport layer — wired USB (via the
usbfeature) or wireless (Wi-Fi + Bluetooth for handoff, via thewirelessfeature). Bluetooth is used to advertise the head unit and negotiate the wireless connection; actual media data flows over Wi-Fi. - TLS handshake — the head unit authenticates using an X.509 client certificate. This library handles the full TLS negotiation via
rustls. - Frame layer — messages may be split across multiple frames (
FrameHeaderType). The library reassembles them transparently. - Channel layer — Android Auto multiplexes multiple logical channels over a single connection (video, audio, input, sensors, etc.). Each channel has its own message types, encoded with protobuf.
The library exposes this through a clean async trait interface so that integrators only need to handle the application-level events they care about.
Features
- Wired USB Android Auto connections (enable with the
usbfeature) - Wireless (Bluetooth-initiated) Android Auto connections (enable with the
wirelessfeature) - Full TLS client support via
rustls - Protobuf message encoding/decoding for all standard Android Auto channels
- Async-first API built on
tokio - Configurable head unit identity (
HeadUnitInfo,AndroidAutoConfiguration) - Video channel trait (
AndroidAutoVideoChannelTrait) for custom video rendering backends - Audio output and input channel traits (
AndroidAutoAudioOutputTrait,AndroidAutoAudioInputTrait) - Input channel trait (
AndroidAutoInputChannelTrait) for touchscreen and keycode support - Sensor channel trait (
AndroidAutoSensorTrait) for reporting sensor data to the phone - Navigation channel trait (
AndroidAutoNavigationTrait) for receiving turn-by-turn updates
Prerequisites
- Rust (stable, recent version recommended — see
rust-versioninCargo.toml) - Tokio async runtime (pulled in automatically as a dependency)
- For wired USB support: enable the
usbfeature (uses thenusbcrate) - For wireless support: enable the
wirelessfeature (uses thebluetooth-rustcrate) and ensure a system Bluetooth stack is accessible - A phone running Android with the Android Auto app installed
Building
Clone the repository and build with Cargo:
To enable wired USB support:
To enable wireless (Bluetooth-initiated) Android Auto support:
To enable both:
Running the head unit
The head unit is provided as an example application. Run it with:
Note: the example uses several dev-dependencies (e.g.
eframe,openh264,cpal). Make sure all system libraries they require are installed.
Wired connection: plug your phone in via USB and build with the usb feature. The head unit will detect the connection and initiate the Android Auto handshake automatically.
Wireless connection: build with the wireless feature and ensure Bluetooth is enabled on both your host machine and phone. The library starts a Bluetooth server that advertises the head unit; the phone will discover it and negotiate a Wi-Fi session.
Using the library
Add android-auto to your Cargo.toml:
[]
= "0.3.3"
# For wired (USB) support:
= { = "0.3.3", = ["usb"] }
# For wireless (Bluetooth-initiated) support:
= { = "0.3.3", = ["wireless"] }
# For both:
= { = "0.3.3", = ["usb", "wireless"] }
Initialization
Call android_auto::setup() once at program startup before doing anything else. It installs the TLS crypto provider and returns an AndroidAutoSetup token that must be passed to run() (and related methods). Requiring this token at the call site is a compile-time guarantee that initialisation is never accidentally skipped:
Minimal example
use ;
;
async
See the docs.rs documentation and the examples/main/ directory for a complete, working reference implementation.
Architecture
android-auto/
├── src/
│ ├── lib.rs # Library entry point and protocol logic
│ ├── control.rs # Control channel handler
│ ├── video.rs # Video channel handler
│ ├── mediaaudio.rs # Media audio channel handler
│ ├── speechaudio.rs # Speech audio channel handler
│ ├── sysaudio.rs # System audio channel handler
│ ├── avinput.rs # AV input channel handler
│ ├── input.rs # Input channel handler
│ ├── sensor.rs # Sensor channel handler
│ ├── navigation.rs # Navigation channel handler
│ ├── mediastatus.rs # Media status channel handler
│ ├── bluetooth.rs # Bluetooth channel handler
│ ├── common.rs # Shared utilities
│ ├── cert.rs # Built-in TLS certificate
│ └── usb.rs # USB transport (usb feature)
├── examples/
│ └── main/ # Full head unit example application
│ └── main.rs
├── protobuf/ # Protobuf definitions (Bluetooth.proto, Wifi.proto)
└── Cargo.toml
Key types
| Type | Role |
|---|---|
AndroidAutoSetup |
Proof-of-initialisation token returned by setup(); must be passed to run() and related methods — ensures initialisation is never skipped |
AndroidAutoConfiguration |
Top-level configuration for the head unit (unit: HeadUnitInfo, optional custom certificate) |
HeadUnitInfo |
Static identity information sent to the phone during handshake |
BluetoothInformation |
Bluetooth adapter MAC address used for wireless negotiation |
NetworkInformation |
Wi-Fi network details relayed to the phone for the wireless session |
SensorInformation |
Set of sensor types the head unit reports to the phone |
VideoConfiguration |
Desired video resolution, FPS, and display DPI |
InputConfiguration |
Supported keycodes and optional touchscreen dimensions |
AudioChannelType |
Discriminates between Media, System, and Speech audio channels |
AndroidAutoMessage |
Enum of all message types that can be received over the link |
SendableAndroidAutoMessage |
Wire-ready message sent from the application back to the phone |
SendableChannelType |
Identifies which channel a SendableAndroidAutoMessage targets |
FrameHeaderType |
Whether a packet fits in a single frame or is fragmented (Single, First, Middle, Last) |
Key traits
| Trait | Purpose |
|---|---|
AndroidAutoMainTrait |
Core trait — implement to handle connect/disconnect and provide the message sender; requires all channel traits below |
AndroidAutoVideoChannelTrait |
Receive and render H.264 video frames from the phone |
AndroidAutoAudioOutputTrait |
Receive and play audio for media, system, and speech channels |
AndroidAutoAudioInputTrait |
Capture and stream microphone audio to the phone |
AndroidAutoInputChannelTrait |
Handle touch and keycode input binding |
AndroidAutoSensorTrait |
Report sensor data (e.g. night mode, driving status) to the phone |
AndroidAutoNavigationTrait |
Receive turn-by-turn navigation events from the phone |
AndroidAutoWiredTrait |
Marker trait indicating the implementation supports USB connections (usb feature) |
AndroidAutoWirelessTrait |
Bluetooth + Wi-Fi negotiation for wireless connections (wireless feature) |
AndroidAutoBluetoothTrait |
Low-level Bluetooth adapter configuration |
Dependencies
The library relies on:
tokio— async runtimerustls— TLS 1.2/1.3 for the secure channelaws-lc-rs— cryptographic backend used by rustlsprotobuf— message encoding/decodingasync-trait— async trait supportfutures— async combinatorsserde— serialization for message typeslog— structured loggingnusb(optional,usbfeature) — USB device accessbluetooth-rust(optional,wirelessfeature) — Bluetooth RFCOMM for wireless handoff
Contributing
Contributions are welcome! A few guidelines:
- Fork the repository and create a feature branch.
- Run the tests before submitting:
cargo test - Keep it async — the library is built around Tokio; new I/O code should follow the same pattern.
- Protobuf changes — if you modify
.protofiles underprotobuf/, regenerate the Rust bindings withprotobuf-codegenbefore committing. - Open a pull request with a clear description of what you changed and why.
If you find a bug or want to request a feature, please open an issue.
License
Licensed under the GNU Lesser General Public License v3.0 or later. See LICENSE for the full text.
This means you can use this library in your own applications — including proprietary or closed-source ones — without being required to release your application's source code. The library itself must remain LGPL.