attempting to mimic the disconnect/reconnect of USB from inside my application - android

I am working on a project where I need to put a USB device in to a reprogramming state and then send a software update to the device. I have been able to make this work by having the user disconnect and reconnect the USB cable between the android device and the USB device I am reprogramming. I have attempted many combinations of releasing interface and then trying to loop through the USBManager getDeviceList and then requestPermission on that device again. I have tried modifying the PendingIntent to be different than the original PendingIntent. I thought I had it once but it seems to have been a faulty OTG cable. In a last ditch effort I tried to craft my own android.hardware.usb.action.USB_DEVICE_ATTACH/DETACH message (which I got a Permission Denial on) Any other ideas out there or is it just not possible?

Related

Android Save permission for a USB device across detach, re-attach

Struggling a bit with Android >=10's UsbDevice class and detecting re-attachment of the same USB device. Prior to Android 10, I could use UsbDevice.getSerialNumber to get a unique handle for a USB device (if it had one). UsbDevice.getDeviceName tends to change from attach to attach e.g. /dev/bus/usb/001/002, /dev/bus/usb/001/003. For Android >=10 you need to ask for user USB permission before calling getSerialNumber. Without having a manifest intent filter for the USB device type and saving the App as the preferred client this is now very messy - a new Permission Request dialogue is needed for each re-attach. Has anyone found a workaround for this? USB OTG connectors are not the most secure so yank then re-plug is a reasonable thing to want to do.

Persisting USB permission after reboot without replugging device

In an Android app, I need permission for a specific USB device (known vendor/product ID), which is permanently plugged on the Android device.
So far I've made the following observations:
when using UsbManager.requestPermission() the permission is dismissed when replugging/rebooting and the popup's checkbox seems to have no effect at all on this behavior
when using intent filters, the permission is properly re-granted when replugging the USB device (even when replugging after a reboot, if the popup's checkbox was checked) BUT the permission is not re-granted after reboot unless I unplug & replug the USB device.
Is it possible to make sure that the permission popup is displayed only once ? (especially in the scenario when the Android device is rebooted and the USB device remains plugged in)
NB: the app isn't installed in the system folder and therefore cannot use the MANAGE_USB permission.
The solution is to use intent filters and add the android:directBootAware="true" attribute on the associated activity so that the USB_DEVICE_ATTACHED event is correctly received after boot.
Persisting USB Permission is not possible, as the reboot option is stopping everything forcefully generally it makes the USB also unplugged.
There is one possibility to ask for replugging USB on reboot.
Is it possible to make sure that the permission popup is displayed only once? No
Because If your are connecting the usb which makes a deadlock situation for taking care of that they make it unplugged, rather than disturbing the system.
So it is not possible to make it USB Plugged-in.

USB OTG device does not work after unplugging and replugging

I am trying to interface with a USB OTG device on Android. Since code is a bit lengthy, I will just outline the basics:
There’s an activity with an Intent filter for USB_DEVICE_ATTACHED (filtered for the device IDs I am interested in) declared in the manifest.
When the activity is launched with that particular intent, it starts a service and passes the USB device as an argument.
When the servie starts, it registers a broadcast receiver for USB_DEVICE_DETACHED, then connects to the device and starts interacting with it (which currently generates some log output).
When the USB disconnect broadcast is received and the device is the one currently in use, close() is called on the USB device connection and the service stops.
The device is a Si4701 USB FM tuner, which presents itself as a USB HID device.
When I first plug in the device, I see my service connects to it, can change channels and receives RDS data.
However, when I unplug it and plug it back in, I see the service connecting to it again (and again apparently successfully reading the device registers), but it fails to change frequencies and I never see any RDS data.
If I force the app to stop between unplugging and replugging the device, the device works normally after geing plugged back in.
This suggests some cleanup fails to take place, or some resource isn’t being released properly. However:
I don’t keep any data structures related to the device between connects. Everything related to the USB connection is in class instances which get created when a device is detected, and all static members of these classes are final.
Some things work after replugging the device, such as reading registers for device types and firmware version (which works by getting a USB HID feature report). Initialization also sets a few registers (through sending a USB feature report), which does not return an error—but changing frequency (which also involves setting registers) does not work.
A ~15-minute interval between unplugging and replugging has no effect (device doesn’t work). On the other hand, if I unplug the device, kill the service and plug it back in, it works instantly—so the issue is definitely on the Android side, not on the device side.
What do I need to do to make the USB device work after an unplug/replug cycle?
I still don’t fully understand what is happening here, but it seems to work now.
I should mention that the app is multi-threaded and the Si470x wrapper class is getting called from multiple threads.
Since this has resulted in race conditions (one thread accessing the device when another thread had just closed it), I properly declared all methods as synchronized so that no two threads can access methods of the tuner class at the same time. Plugged the device in, unplugged it, plugged it back in—and lo and behold, it changes frequencies and spits out RDS data the way it is supposed to.
Suspicion:
UsbDeviceConnection#close() might not be thread-safe.
Conclusions:
Always call UsbDeviceConnection#close() when you’re done with the device (including when the device is detached).
If your app is multithreaded, make sure that everything which accesses your USB connection (directly or indirectly) is properly synchronized.

How android system autoconnects to paired device?

What I want to know:
I'm wondering how the android system (like Android smart phone) auto-connects to devices which is paired before.
For example, I pair my bluetooth headset with my android smartphone in the procedure of "turn on scanning/advertising -> click pairing" on day 1. And when I turn on advertising on my headset, it connects automatically on day 2, 3, 4, and so on. The point is, I don't have to make my smartphone scan again to find my (paired) headset.
I can't understand how android system finds that the paired device is turned on. Does the android system scan periodically in background? Even if I don't click "scan" button?
Why I ask:
I want to make my app autoconnect to customized BLE device, after make pairing. I succeed to make pairing(bonding) with createBond() method, but after that, I couldn't find how to make autoconnect. I know I can turn on autoconnect function like this way, connectGatt(XXX, true, XXX), but this autoconnect function doesn't work when the BLE device is disconnected a few days.
So I want to make my app works like android system and Bluetooth headset. But I couldn't find how android bluetooth system works even I dig AOSP codes.
I found many questions (here and here) about problems like mine but there were no answers.
Thanks in advance.
Update:
I found that bt_btif gets activated (with LG smartphone and Nexus 5) when the paired headset is turned on (start advertising). But bt_btif doesn't get activated with my custom BLE device... What can I do?
Executing connectGatt(XXX, true, XXX) is the correct way to go. gatt.connect() also starts an auto connect. Once you execute that, your phone will scan for the device and once it appears it connects to it. The only thing that interrupt this call is either if Bluetooth is turned off on the phone or if your app process is being killed. To avoid your process from being killed, let your app have a foreground service.
One gotcha however, there is a bug in Android which will sometimes make auto connect do a direct connect instead (and cancel after 30 seconds or so). See https://code.google.com/p/android/issues/detail?id=69834. You need to use reflection to avoid this bug.
I think I found a solution.
First, the solution for my question: Android smartphone seems to detect state changes of nearby bluetooth devices from the hardware sides. When the paired bluetooth headset starts to advertise, a callback in HAL (I think) is called.
So I made my app to connectGatt with autoConnection=True to the device that I want, by using MAC address, when the activity is started (in onResume() of MainActivity).
The connection would fail if my BLE peripheral device is not advertising. But the device auto-connects when it starts advertising, because the autoConnection parameter was set to true.
I've done a similar app and i didn't have problem with that. As a last resort for your problem, i would suggest writing the BLE Device Address in a simple DB table and manually connect to it. I've made something like this here
. It is no best practice code, but i hope you can find ideas for you solution.

Android, Bluetooth, BTLE, GATT reading characteristic fails?

I have an android app i am developing. It's a BTLE app, i have some BTLE tags i need to talk to.
I do all by the book, discover device, GATT connect (subsequent bonding), write/read characteristics... it works.
Now the weird is that it will stop working if i close and open the application two times.
Let's say i have already one tag correctly connected, bonded and working properly.
phone reboot.
Open app the first time -> everything works.
close app, open again -> everything works.
close app again, open -> unable to receive any readCharacteristic from the GATT callbacks.
In the logs, there is NOTHING DIFFERENT from each attempt. I log each call and print return statuses: no difference. Just the readChar callback is never called.
Android is 4.3, same issue on different phones (S3, S4, Note3)
(note: on app shutdown i properly disconnect all the GATT stuff)
Do you have any ideas on what to check? Or is this a known android bug? I have searched, but could not find anything....
The bluetooth stack on Android 4.3(at least) specially for BTLE definitely has quite some issues. I don't know if it's a specific vendor implementation, driver issues, or what else, but it's honestly a nightmare for developers.
This is what i found out does help to improve things:
- disable Wifi
- forcefully enable/disable bluetooth by code (BluetoothAdapter methods enable() and disable())
In fact, cyclying bluetooth on and off when things start getting "unstable" do fix it. This requires the BLUETOOTH_ADMIN capability and might clearly not be desired, since it will briefly shut down ALL you bluetooth conencted gadgets AND will popup some dialogs to the user where he/she can disable the ongoing restart.
Now i am getting more stable results.
Still, shame on Google (or whoever i don't know) for letting such poor software out in the wild.

Categories

Resources