termux / termux/termux-api

[Feature Request] Persistent USB permission: declare USB_DEVICE_ATTACHED intent filter + device_filter.xml

Open
#917 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
4.3k
Forks
920
PR merge metrics
No merged PRs in 30d

Description

Summary

termux-usb permission is granted per device instance, so it must be re-granted by hand every time a device re-enumerates. Termux:API has no USB_DEVICE_ATTACHED intent filter and no device_filter.xml, which is what makes Android offer the "Use by default for this USB device" checkbox. Without it that checkbox can never appear, and there is no setting that changes this.

Why it matters

This affects any termux-usb workflow, not one tool. Anything libusb-based — USB-serial and UART adapters, microcontroller flashing (dfu-util, esptool, avrdude), SDR receivers, smartcard and NFC readers, cameras via gphoto2, and adb/fastboot via termux-adb — goes through termux-usb -r and therefore through a fresh dialog on every re-enumeration.

The workflows hit hardest are the ones where re-enumeration is a normal part of the job:

  • a microcontroller that reboots into a bootloader or DFU mode mid-flash, often reappearing under a different VID/PID
  • adb root / adb reboot, which restart adbd and bring the target back on a new /dev/bus/usb/BBB/DDD path
  • any device that resets itself after a firmware write
  • simply unplugging and replugging

In each case the permission granted moments earlier no longer applies, so a scripted or unattended sequence stops dead waiting for a tap. A push → reboot → verify loop needs a manual tap every single cycle.

Verification

Checked against the installed APK rather than the repo — com.termux.api 0.53.0, versionCode 1002:

  • the manifest is 287 lines and contains exactly two USB references: uses-feature android.hardware.usb.host, and the UsbAPI$UsbService declaration (exported=false, no intent-filter)
  • USB_DEVICE_ATTACHED appears zero times anywhere in the APK — manifest or dex — so it isn't registered at runtime either
  • the only device_filter-ish resource is res/drawable/ic_usb_black_24dp.xml, an icon
Proposal

Declare the attach intent filter so Android is able to grant persistently:

<activity android:name=".UsbAttachActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
               android:resource="@xml/device_filter" />
</activity>

with a filter that matches any device:

<resources>
    <usb-device />
</resources>

This is a supported wildcard, not a syntax trick. In frameworks/base/core/java/android/hardware/usb/DeviceFilter.java, unset attributes default to -1 in read():

int vendorId = -1;
int productId = -1;

and matches() treats -1 as "match anything":

if (mVendorId != -1 && device.getVendorId() != mVendorId) return false;
if (mProductId != -1 && device.getProductId() != mProductId) return false;

with the same pattern for class/subclass/protocol:

return ((mClass == -1 || usbClass == mClass)
        && (mSubclass == -1 || subclass == mSubclass)
        && (mProtocol == -1 || protocol == mProtocol));

So <usb-device /> and <usb-device vendor-id="-1" product-id="-1" /> are equivalent — omitting an attribute simply leaves it at the wildcard value.

Why enumeration isn't an option here

Comparable F-Droid apps all enumerate VID/PIDs instead, and it works for them because their hardware domain is bounded: APRSdroid ships 800+ generated <usb-device vendor-id= product-id=> entries, SimpleUsbTerminal a curated FTDI/CP210x/PL2303/CH34x list, Octo4a a list of 3D-printer boards.

Termux:API is a general-purpose API. It cannot know what its users will attach — that's the point of exposing libusb — so any curated list would be permanently incomplete and permanently in need of maintenance. The wildcard exists in the platform for exactly this case.

References

Open-source apps already ship exactly this. In each case both halves are present — the filter resource and the manifest wiring:

  • hutorny/usbuart — a libusb-based USB-UART service that relays bulk endpoint data to pipes. Architecturally the closest analogue to termux-usb: a general service handing USB to other programs. service/res/xml/device_filter.xml is exactly <usb-device />, wired via USB_DEVICE_ATTACHED + meta-data in service/AndroidManifest.xml.
  • devunwired/accessory-samples (UsbMonitor) — widely-referenced Android USB sample code, same bare filter, same wiring.
  • mikereidis/headunitusb_device_filter.xml carries the bare element under the comment <!-- Match all devices -->, wired identically.

Platform documentation and source:

  • Android USB host guide — the official example of declaring USB_DEVICE_ATTACHED with a device_filter.xml resource, including the note that a filter with no attributes matches any device.
  • DeviceFilter.java (AOSP) — the -1 wildcard semantics quoted above.
Handling the breadth

A match-everything filter means Android may offer to open Termux:API whenever any USB device is attached. Reasonable ways to handle that, in rough order of preference:

  1. make it opt-in — ship the filter but let the user enable the behaviour in Termux:API settings
  2. let the user supply their own device_filter.xml, so they can scope it to hardware they actually use
  3. ship a narrower default that can be widened, e.g. <usb-device class="255" subclass="66" protocol="1" /> for the ADB interface

Any of these beats the current situation, where the persistent-grant path is unreachable regardless of what the user wants.

Notes
  • #432 asked for something adjacent but proposed patching out getPermission() and hardcoding approval; it was closed. This request is different — it keeps the user in control. The grant stays an explicit, revocable, per-device choice made through the standard Android dialog; Android is simply allowed to remember it.
  • Happy to test a build. I have a reproducible setup (Galaxy Z Fold 5 on Android 16, an LG US998 target behind a USB hub) where the prompt reappears on every re-enumeration.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Inspect the Android manifest and the existing UsbAPI$UsbService declaration, then compare the proposed UsbAttachActivity wiring with the referenced device_filter.xml examples. Determine how the persistent-grant flow should be scoped or made opt-in, and verify the resulting build and USB re-enumeration behavior on the reported setup.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, java
Domain
mobile
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.