This project is a DIY proxy tool that bridges a wireless Android phone with a USB-connected car head unit to enable the use of Android Auto.
Originally derived from the WirelessAndroidAutoDongle project (specifically as
a replacement for its aawgd
component), it has since evolved into an independent and self-contained solution with its own development direction.
As with the original project, our primary focus is on supporting the Raspberry Pi. However, other boards are also currently in development, including AAWireless TWO (thanks to collaboration with its creators) and the Radxa Zero 3W.
Sample Connection Diagram – Raspberry Pi Zero 2 W
- Reliable and safe – written in Rust, minimizing memory-related bugs and crashes
- High performance – uses modern io_uring kernel API for efficient I/O handling
- Automatic reconnection – attempts to recover Android Auto connection in all failure scenarios
- Transfer monitoring – displays bandwidth usage and real-time transfer statistics
- Embedded web interface – lightweight UI for status and control
- Stall detection – detects and handles stalled data transfers
- MITM (Man-in-the-Middle) mode – supports advanced tweaks and modifications:
- DPI change
- Remove tap restriction
- Disable media sink
- Disable TTS sink
- Video in motion
- Enable developer mode
- Google Maps EV Routing – allows EV-specific navigation features
- Wired USB phone mode – works without the Bluetooth handshake or Wi-Fi pairing
- Support for Google’s Desktop Head Unit (DHU) – ideal for debugging and development
After extensive stress testing and continuous development, the project has reached a level of stability that meets its original goals.
I now use it almost daily in my own car and continue to fix any issues that come up to ensure a smooth and reliable experience.
There's also a great and supportive community on Discord built around this project. If you'd like to join, ask questions, or get help,
feel free to connect with us on the aa-proxy-rs Discord server.
This project is currently tested and built for the following Raspberry Pi boards that support USB OTG:
- Raspberry Pi Zero W
- Raspberry Pi Zero 2 W
- Raspberry Pi 3 A+
- Raspberry Pi 4
Note
Raspberry Pi 3 B+ is not supported due to the lack of USB OTG support.
Warning
-
2.4GHz Wi-Fi is being deprecated by Google and is no longer a reliable long-term solution.
Newer head units with higher resolutions (e.g. Full HD displays in some Kia/Hyundai models) require 5GHz Wi-Fi to function with full resolution support.
Only boards with 5GHz-capable Wi-Fi chips will be able to utilize the full display resolution.
Simply changing the DPI will not solve this limitation. -
Additionally, 2.4GHz Wi-Fi can interfere with Bluetooth, since both operate on the same frequency band.
This can occasionally cause connection issues — especially during the initial pairing phase when both Wi-Fi and Bluetooth are active. The problem is particularly noticeable on devices like the Raspberry Pi Zero 2 W.
Work is currently in progress to support additional hardware platforms, including:
- AAWireless TWO – thanks to collaboration with its creators
- Radxa Zero 3W
In theory, support can be extended to other hardware platforms in the future, as long as the following basic requirements are met:
- USB OTG or USB Gadget mode support
- Wi-Fi and Bluetooth (either built-in or via external adapters)
The latest stable SD card images are available on the Releases page.
- Connect your phone to the car head unit using a USB cable and verify that Android Auto starts successfully. Then disconnect the phone.
- Connect the board to the car using a data-capable USB cable and ensure you use the USB OTG-enabled port on the board:
- Raspberry Pi Zero W and Raspberry Pi Zero 2 W: Use the second micro-USB port labeled "USB" (not the one labeled "PWR").
- Raspberry Pi 3 A+: Use the only USB-A port with a USB-A to USB-A cable.
- Raspberry Pi 4: Use the USB-C port normally used to power the board.
- Open Bluetooth settings on your phone and pair with the new device named
aa-proxy-rs-*
orAndroidAuto-*
. - After pairing, your phone should automatically connect via Wi-Fi, and the dongle will connect to the head unit via USB, starting Android Auto on the car screen.
From the next time onward, the system should automatically connect to your phone and start Android Auto without additional steps.
Warning
For convenience during the initial setup, SSH access is enabled by default and the device uses a predefined Wi-Fi password. It is strongly recommended to change these defaults and/or disable SSH access for security reasons.
Note
Default SSH credentials:
User: root
Password: password
Default Wi-Fi password:
aa-proxy-rs
See below for instructions on how to connect to the device's Wi-Fi network.
Setting these options via the web interface is planned for a future update.
For now, they can be configured manually in the /etc/aawgd.conf
file.
When you connect to the device's WiFi network, you can access the web interface, which is available by default at: http://10.0.0.1.
Warning
If you want to connect to the device (e.g. via the web interface or SSH) while Android Auto is running, it won't be accessible from your phone. In that case, you have two options:
- Use a different device, such as a laptop or another phone, to connect to the device’s Wi-Fi network.
- Or stop Android Auto temporarily, for example by:
- Enabling airplane mode, then enabling Wi-Fi only and connecting manually, or
- Disabling both Wi-Fi and Bluetooth, waiting a moment, then re-enabling Wi-Fi and connecting manually.
If you're still having trouble connecting, try disabling MAC address randomization. This guide provides clear instructions on how to do it on Android.
Using the web interface, you can configure all settings that are also available in /etc/aa-proxy-rs/config.toml
:
You can also download logs with a single click.
There are many commercial solutions available for wireless Android Auto, such as AAWireless or Motorola MA1. I even bought a clone from AliExpress — but unfortunately, it didn’t work in my car (I ended up giving it to a friend who had a compatible vehicle).
Thanks to Nicnl on Reddit, who commented under this post, I discovered a great open-source project based on Raspberry Pi hardware: WirelessAndroidAutoDongle by Nisarg Jhaveri.
The author did some excellent research and created a working DIY solution — and most importantly, he shared it openly with the community. That’s something I truly admire and appreciate!
Because the project is open source, I was even able to run additional LoRa hardware on the same Raspberry Pi for a completely different purpose.
The original project uses a daemon called aawgd
, which handles proxying data between the phone and the USB-connected head unit.
Unfortunately (or fortunately!), the original implementation wasn’t always reliable in my case — I experienced crashes, failed reconnections,
and the need to restart the service manually.
After submitting this pull request, I decided to create a Rust-based
alternative to aawgd
. That’s how this project started — by reimplementing the C++ code into a new, standalone application written in Rust.
From the beginning, I aimed to simplify parts of the original code wherever possible. This project also became a great opportunity (and a lot of fun!) to dive deeper into how the system was designed and how everything works under the hood.
One of the biggest challenges I faced was implementing reliable bidirectional I/O forwarding.
Since the entire application is asynchronous and uses Tokio, my first instinct was to use copy_bidirectional
.
However, this approach didn’t work as expected — likely due to how the USB socket for the usb-gadget
kernel module interacts with polling/epoll mechanisms.
I also experimented with running separate read/write operations inside Tokio tasks, but ultimately found a better solution:
using the modern io_uring interface via the tokio_uring
library.
This approach turned out to be both highly efficient and completely stable — solving the problem in a clean and performant way.
-
The project depends on the kernel-level io_uring API for its core data transfer functionality. As a result, Linux kernel version 5.10 or newer is required.
-
Please note: I work on this project in my free time as a hobby. While I do my best to respond and fix issues, I can't always guarantee quick replies or provide ETAs for requested features.
The connection process is quite complex and involves several carefully timed steps to establish a stable link between the phone and the car head unit. Below is an overview of what the app does from start to finish:
- USB: Disable all existing USB gadgets.
- USB: Register for uevents to monitor USB state changes.
- Start a local TCP server.
- Bluetooth: Power up the Bluetooth adapter and make it discoverable and pairable.
- Bluetooth: Register two profiles:
- One for Android Auto,
- One for a fake headset (to trick the phone into recognizing a wireless Android Auto head unit).
- When a phone connects to the Android Auto profile, the app sends two frames with specific Google protocol data:
WifiStartRequest
: includes the IP address and port of the TCP server the phone should connect to.WifiInfoResponse
: contains the Access Point information for the Wi-Fi connection.
- After receiving a successful response, the tool disables Bluetooth.
- The phone connects to the car’s Bluetooth (e.g., for phone calls).
- Simultaneously, the phone connects via Wi-Fi to our TCP server on the specified port.
- USB: Switch USB gadgets to “default” followed by “accessory” mode to enable proper USB data transmission to the car head unit (fooling the car into thinking the phone is connected via USB).
- Final stage: Bidirectional forwarding of data between the TCP client (phone) and USB port (car).
The USB side is the active initiator of data transmission, starting with sending a 10-byte first frame. Because of this, timing is critical:
- If the USB dongle connection starts too early (before the phone is connected), the transmission begins but the TCP socket isn’t ready yet.
- Conversely, if the phone starts too early and the USB connection is not ready, data cannot be sent to the phone, causing Android Auto to close or timeout the connection.
Proper synchronization between these steps ensures a stable and reliable connection.
If you'd like to build the SD card images yourself, head over to our Buildroot repository:
https://github.com/aa-proxy/buildroot
There you’ll find all the necessary tools and instructions to generate custom images tailored to your hardware or specific needs.
While the aa-proxy-rs binary is typically used as part of the prebuilt system image, it can also be run manually:
Usage: aa-proxy-rs [OPTIONS]
Options:
-c, --config <CONFIG> Config file path [default: /etc/aa-proxy-rs/config.toml]
-h, --help Print help
-V, --version Print version
Default startup config file is config.toml.
Configuration options are documented in comments, but these needs some more attention:
-
legacy
Originalaawgd
is using two USB gadgets: default and accessory. When connecting to car headunit, it switches first to default then to accessory. During my development I found out that my car headunit doesn't need this switching. It is working fine connecting directly to accessory gadget. Moreover with this approach it is much faster and doesn't need to wait for USB events in dedicated UEvent thread. As the result I decided to leave the old (legacy) code under this switch for compatibility with some headunits.
In short: if you have problems with USB connection try to enable the legacy mode. -
connect
By default without this option the aa-proxy-rs is starting but it is only visible as a bluetooth dongle, to which you have to connect manually from your phone to initiate AndroidAuto connection. If I am correct this was calleddongle mode
inaawgd
.
If you provideconnect
option with default00:00:00:00:00:00
wildcard address, then the daemon is trying to connect to known (paired?) bluetooth devices (phones) in a loop (the bluetoothd have a cached list of recently connected devices in /var/lib/bluetooth). This is the default mode foraawgd
for the time I am writing this.
If you set this option to specificMAC_ADDRESS
where MAC_ADDRESS is the MAC of your phone (bluetooth), then the aa-proxy-rs will try to connect only to this specified device in a loop (ignoring all bluetoothd cached devices).
Man-in-the-middle mode support has been added recently. This is the mode which allows to change the data passed between the HU and the phone.
Separate encrypted connections are made to each device to be able to see or modify the data passed between HU and MD.
This is opening new possibilities like, e.g., forcing HU to specific DPI, adding EV capabilities to HU/cars which doesn't support this Google Maps feature.
All the above is not currently supported but should be possible and easier with this mode now implemented.
To have this mode working you need enable mitm
option in configuration and provide certificate and private key for communication for both ends/devices.
Default directory where the keys are search for is: /etc/aa-proxy-rs/
, and the following file set needs to be there:
- hu_key.pem
- hu_cert.pem
- md_key.pem
- md_cert.pem
- galroot_cert.pem
I will not add these files into this repository to avoid potential problems. You can find it in other places, or even other git repos, like:
- https://github.com/tomasz-grobelny/AACS/tree/master/AAServer/ssl
- https://github.com/tomasz-grobelny/AACS/tree/master/AAClient/ssl
- https://github.com/lucalewin/vehiculum/tree/main/src/server/cert
- https://github.com/lucalewin/vehiculum/tree/main/src/client/cert
- https://github.com/borconi/headunit/blob/master/jni/hu_ssl.h#L29
Special thanks to @gamelaster for the help, support and his OpenGAL Proxy project.
Thanks to above MITM mode a DPI setting of the car HU can be forced/replaced. This way we can change the hardcoded value to our own. This is allowing to view more data (at cost of readability/font size).
Example with Google Maps, where a Report
button is available after changing this value:
160 DPI (default) | 130 DPI |
---|---|
![]() |
![]() |
Google introduced EV routing features at CES24. The first cars to support this via Android Auto are the Ford Mustang Mach-E and F-150 Lightning.
This clip shows how it works in the car:
The idea of using this feature with other cars started here: #19 in February 2025. After a long journey searching for someone with the knowledge and hardware that could help us obtain the logs, we finally, at the end of June 2025, thanks to @SquidBytes, got the sample data to analyze.
Thanks to many hours of work by @Deadknight and @gamelaster, we were finally
able to make some use of that data.
Unfortunately, the work is still in progress, but I am currently at a stage where, by customizing some parameters, I can provide real-time battery
level data to aa-proxy-rs
, and overall it makes correct estimates for my car.
aa-proxy-rs
has an embedded REST server for obtaining battery data from any source (I am using a slightly modified version of the
canze-rs app for this purpose).
It reads the data on the same Raspberry Pi (connecting wirelessly to the Bluetooth OBD dongle).
aa-proxy-rs
can be configured to execute a specific data collection script when Android Auto starts and needs the battery level data, and also when it stops.
The script can be configured in config.toml
and is executed with the arguments start
and stop
accordingly.
Thanks to the power of open source, even older EVs can now enjoy modern features and a much better navigation experience!
Sometimes deleting the system Bluetooth cache at /var/lib/bluetooth and restarting bluetoothd fixes persistent issues with device connectivity. Consider also using "Forget" of bluetooth device in the Android phone.
By default, the application logs to the file:
/var/log/aa-proxy-rs.log
This log can be useful for troubleshooting and diagnosing issues.
You can easily download the log file via the embedded web interface.
- https://github.com/nisargjhaveri/WirelessAndroidAutoDongle
- https://github.com/nisargjhaveri/AAWirelessGateway
- https://github.com/openDsh/openauto
- https://github.com/qhuyduong/AAGateway
- https://github.com/Demon000/web-auto
- https://github.com/f1xpl/openauto
- https://github.com/gamelaster/opengal_proxy
- https://github.com/tomasz-grobelny/AACS