Open glenngartner opened 2 years ago
Here for the same issue!
have you made any progress @jessebraham ?
My understanding is that serial ports, as we know them from UNIX, are not available to Android apps (at this time). However USB is available if you get permissions and pass the file descriptor down into native code.
The reason the Kotlin drivers work is because they're really USB Serial drivers implemented in userspace, since the kernelspace drivers expose /dev/ serial ports (apps don't have permissions to these).
To get access to USB serial ports on an unrooted android, we'd need a rust implementation of USB serial in userspace. This would not give you access to native serial ports on android however, for example if you have some direct serial interface on inside your android phone.
Enumerating USB devices (and therefore USB serial ports) would still not be possible from Rust, since you must use android's APIs to do this.
I'm using this lib on Android, when when I pass a port name from Java to this lib, I receive "Error opening port Permission denied". Just wondering to what degree Android is supported (I know device enumeration isn't, that's why I'm passing available devices from the Java layer). Some specifics:
Android SDK / NDK targets:
Android Manifest, giving access to certain devices
Device filters, which when connected, prompt the user for permission to access the particular USB device (which, in my case, is a 232 to USB FTDI chip (vendorId: 0403, Product Id: 6001):
When the device is connected, Android OS prompts me to open the device in my app. When it's first connected, it asks me for permission to access it. That permission is granted, saved, and seems to persist (see below):
When app starts MainActivity.onCreate()
or when a device is connected, the user is prompted for permission to access it. The user gives permission. If I enumerate the devices in Java, with something like this, and in this enumeration, I check if the USB service / manager has permission to open the device (it does), so I proceed to open it via java, then rust lib. I've thought to myself, well, what if I don't open the device in Java, but only in rust, and perhaps that's why I don't have permission? Nope. Whether I open the device in java, or not, I'm still not permitted to access the device from rust.
simple rust lib code
Finally, the rust function that receives the string from java, prints some helpful logs, to prove the communication between layers is functional (because debugging is a bit of a pain), and attempts to open the port_name provided. When this code is run from a Linux machine, the device is opened just fine. When opened from an Android app, I don't have permissions to open the port. In all cases, with just 1 usb devices connected to the Android phone, the path is "/dev/bus/usb/002/002", FWIW
AVC prompts
Sometimes (but not every time) I'll see LogCat print a AVC permissions issue, like this:
SELinux permissions
I understand, from Google knowledge, that the above comes from the SELinux layer, basically saying I don't have permission to access this device. My USB Service says I have permission to access to the USB, but perhaps the path for the usb is permitted, and the serial protocol requires something different. This is where I'm unsure.
My question:
Does my android device have to be rooted for this library to work? It's not, currently. I'd prefer it not have to be. I know there are java libraries for accessing serial devices on Android specifically (like here https://github.com/mik3y/usb-serial-for-android), because device drivers on stock (unrooted) Android need to be provided on the app, because they're not provided by the OS. I can integrate an entirely different serial lib for Android, and abstract the parsing of each sensor in rust by passing buffers from the above lib into rust, but I'd prefer to use one lib across devices, if possible.
I've seen the clever folks over at libusb resolve this issue for unrooted Android devices with instructions like this: https://github.com/libusb/libusb/blob/master/android/README (if you're still reading, it begins at line 35) where they request permission at the Java layer, and pass the fileDescriptor from java to the libusb native code. I'm not that familiar with this level of detail yet, but perhaps there's something to it. Or, perhaps that's just a USB interop thing, not related to serial devices. This is where I can use some help.
My goal: open a serial port from Android using this lib, parse and handle all the data in rust, as I'm doing with my desktop apps, without having to write too much more interop in Java, so this works on android.
Thanks!