DEV Community

Cover image for Control Android from your PC over USB: no root, no adb, no app
Nemarpuc
Nemarpuc

Posted on AI-assisted

Control Android from your PC over USB: no root, no adb, no app

I've released libaoahid, a library that lets a PC send keyboard, mouse, gamepad, and multi-touch input to an Android device over a USB cable. It's implemented in C++20 but exposes a stable C ABI, so it can be used from C, C++, or any language that can call C. It's MIT-licensed.

It started when I wanted to build something to automate Android. While looking for a way to do it I came across AOA's HID feature, but implementing it ran into bug after bug. So I set out to build a library that takes care of the complicated parts while keeping full flexibility and as little latency as possible.

The device needs no root and no app. To Android it looks like a USB keyboard or touchscreen has been plugged in, so the input is handled like any ordinary device's. It runs on Windows and Linux, and can also be used from Python, C#, and Rust.

Demo

This is aoahid_player, an app built with the library. It plays back a CSV script, then changes the volume and the track from the PC.

Compared with other approaches

The usual ways to drive Android from a PC are adb shell input and accessibility services. The first needs USB debugging and injects input in software; the second needs an app installed on the device and granted permissions.

With the HID feature of AOA 2.0, which libaoahid uses, you just plug the device in. No settings, no app.

How it works

Since Android 4.1, Android has had Android Open Accessory (AOA) 2.0. Its HID feature lets a USB-connected PC register a virtual input device on the phone and send input through it.

Building something practical on raw AOA is harder than it looks. The HID descriptor has to be in a shape Android accepts, and multi-touch only works if each finger's state is tracked properly. libaoahid takes care of that.

At the same time, the library never picks values such as resolution or bit width for you; the caller specifies all of them, so you always know exactly what is being sent.

Supported input

Kind Covers Tested on hardware
Touch Multi-touch Yes
Keyboard Every key at once Yes
Mouse Motion, buttons, wheel Yes
Gamepad Sticks, buttons, D-pad Yes
Media keys Volume, play/pause, next track Yes
Pen and others Pressure, hover, etc. Not yet

Tested on a Samsung Galaxy Tab S11 and a POCO F6 Pro, from both Windows 10 and Arch Linux.

Usage

Prebuilt archives are on Releases. To build from source you need CMake 3.20+, a C++20 compiler, and libusb 1.0.30 or later:

git clone https://github.com/nemarpuc/libaoahid
cd libaoahid
cmake -S . -B build -DAOAHID_BUILD_SHARED=ON
cmake --build build --config Release
Enter fullscreen mode Exit fullscreen mode

Moving a mouse looks like this (error handling left out):

/* Find and open the device */
aoahid_discover(ctx, 500, &found);
aoahid_device_open(ctx, aoahid_discovery_get(found, 0), &device_options, &dev);

/* Define a mouse and register it on the device */
mopt.button_count = 3;
mopt.x = (aoahid_integer_field){-127, 127, 8};
mopt.y = (aoahid_integer_field){-127, 127, 8};
aoahid_spec_create_mouse(&mopt, &spec);
aoahid_node_open(dev, spec, &node_options, &mouse);

/* Send input */
aoahid_mouse_move(mouse, 10, -5);
aoahid_node_submit_blocking(mouse, 500);
Enter fullscreen mode Exit fullscreen mode

Complete, runnable code and small programs for checking behavior on a real device are in examples. Setup steps are in the QUICKSTART.

A bridge for using adb at the same time

On Windows, only one process can open a USB device. So even with the driver on WinUSB or libusbK, AOA input and adb normally couldn't be used together.

That's why I made aoahid_adb_proxy. It relays adb traffic over the app's own USB connection to a local port, so while input is being sent you can still use adb and scrcpy with adb connect 127.0.0.1:6555.

Samsung on Windows

When a Samsung device is connected to Windows, Samsung's own USB driver gets installed. With it, input works but the adb bridge doesn't.

Replacing the driver for the whole device with WinUSB using Zadig fixes it. Regular adb keeps working on WinUSB, but tools that need the manufacturer's driver, such as Samsung Smart Switch, may stop working. The detailed steps are in aoahid_player's README.

aoahid_player

The app in the demo. It plays back actions written in CSV and can record real actions into CSV. It also supports looping, speed changes, live control with the PC's mouse and keyboard, and playback to several devices at once.

@screen 1080x2400
t,0,1,500,500,16
t,0,0,500,500,16
Enter fullscreen mode Exit fullscreen mode

This script taps the screen at (500, 500). Prebuilt downloads for Windows and Linux are on Releases.

What's next

Some input types, such as pen, haven't been tested on hardware yet. AOA is an Android feature, so iOS isn't supported.

I'd like to hear what you would use it for, and whether you've hit similar driver problems with other manufacturers on Windows. Let me know in the comments. Bug reports and feature requests are welcome as GitHub issues.

This article was written with the help of AI. Much of the code in these projects was also written with an AI coding assistant; the design, hardware testing, and review were done by me.

Top comments (0)