Present a connected game controller to an Android device and set its state. The device sees a REAL controller — a kernel-level input device that native games and apps receive exactly as they would a pad plugged into the phone.
HOW TO FIRE INPUT PROPERLY:
• One call = ONE frame = one instant in time. A button stays pressed until you send a frame WITHOUT it, so every press needs a matching release frame — keydown then keyup. Press after press just holds them all down.
• For anything that should look played rather than stepped — mashing, combos, a stick sweep — pass `frames` instead of calling repeatedly. The sequence plays out device-side at `intervalMs` (default 33 ms ≈ 30 fps). A round trip per frame cannot reach that cadence, so a rapid sequence built from single calls always reads as held buttons.
• Alternate press and release inside `frames`: [{buttons:[1]}, {}, {buttons:[1,1]}, {}] is tap A, release, tap A+B, release.
• Axes are [leftX, leftY, rightX, rightY], -1..1. Sweep them across frames to roll a stick; omitted axes read as centred.
• Confirm with device_gamepad_status.
Buttons and axes use W3C standard order, identical to the iOS gamepad tools — the mapping onto whatever the chosen controller reports is done for you. Pick `profile` to match the hardware you want the device to believe is attached; it changes both the reported identity and the button layout, so a game showing on-screen prompts shows the right ones. This is the tool to reach for. device_uhid_gamepad_state is the raw twin — it takes the fixed-format report directly (one profile, rotated bit order) instead of translating from W3C arrays; use it only to send an exact report byte-for-byte.
ConnectorOAuth