| Summary: | Exception when connecting a HID Joystick device to an Android device. | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Gerhard Stein <gerstrong> |
| Component: | joystick | Assignee: | Sam Lantinga <slouken> |
| Status: | NEW --- | QA Contact: | Sam Lantinga <slouken> |
| Severity: | critical | ||
| Priority: | P2 | CC: | alynx.zhou, auahdark687291 |
| Version: | 2.0.12 | ||
| Hardware: | ARM | ||
| OS: | Android (All) | ||
Got similar problem when a USB Type-C earphone is plugged, app crashed on start with following expection:
java.lang.RuntimeException: Unable to start activity ComponentInfo{one.alynx.flipclock/one.alynx.flipclock.MainActivity}: java.lang.SecurityException: User has not given 10348/one.alynx.flipclock permission to access device /dev/bus/usb/001/002
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3324)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3473)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2060)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:238)
at android.app.ActivityThread.main(ActivityThread.java:7619)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.SecurityException: User has not given 10348/one.alynx.flipclock permission to access device /dev/bus/usb/001/002
at android.os.Parcel.createException(Parcel.java:2074)
at android.os.Parcel.readException(Parcel.java:2042)
at android.os.Parcel.readException(Parcel.java:1990)
at android.hardware.usb.IUsbSerialReader$Stub$Proxy.getSerial(IUsbSerialReader.java:123)
at android.hardware.usb.UsbDevice.getSerialNumber(UsbDevice.java:143)
at org.libsdl.app.HIDDeviceUSB.getSerialNumber(HIDDeviceUSB.java:56)
at org.libsdl.app.HIDDeviceManager.connectHIDDeviceUSB(HIDDeviceManager.java:362)
at org.libsdl.app.HIDDeviceManager.handleUsbDeviceAttached(HIDDeviceManager.java:324)
at org.libsdl.app.HIDDeviceManager.initializeUSB(HIDDeviceManager.java:228)
at org.libsdl.app.HIDDeviceManager.<init>(HIDDeviceManager.java:152)
at org.libsdl.app.HIDDeviceManager.acquire(HIDDeviceManager.java:36)
at org.libsdl.app.SDLActivity.onCreate(SDLActivity.java:248)
at android.app.Activity.performCreate(Activity.java:7894)
at android.app.Activity.performCreate(Activity.java:7881)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3299)
... 11 more
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.usb.UsbUserSettingsManager.checkPermission(UsbUserSettingsManager.java:177)
at com.android.server.usb.UsbSerialReader.getSerial(UsbSerialReader.java:96)
at android.hardware.usb.IUsbSerialReader$Stub.onTransact(IUsbSerialReader.java:84)
at android.os.Binder.execTransactInternal(Binder.java:1030)
at android.os.Binder.execTransact(Binder.java:1003)
My app does not need USB support, I also commented out usb permissions in Manifest, why this happened?
Hi Gerhard, is your `targetSdkVersion` is 29 or higher? I found some reason here: https://developer.android.com/reference/android/hardware/usb/UsbDevice#getSerialNumber() Because I submitted my apk to Play Store and it asked me to update `targetSdkVersion` to 29, so I changed from 26 to 29. And according to the doc, this method, is the only one that throws Exception when app have no permission to USB device, and this only happens when `targetSdkVersion` is 29 or higher. Since original getSerialNumber returns "" when no SerialNumber returns, I think it's not important so I use the following patch to ignore this Exception: ``` diff --git a/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java b/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java index 33816e3..98c0f9d 100644 --- a/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java +++ b/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java @@ -53,7 +53,14 @@ class HIDDeviceUSB implements HIDDevice { public String getSerialNumber() { String result = null; if (Build.VERSION.SDK_INT >= 21) { - result = mDevice.getSerialNumber(); + // If `targetSdkVersion` is 29 or higher, `getProductName()` will + // throw `SecurityException` when no permission requested. Not sure + // why SDL2 needs this but it seems not important so just ignore it. + try { + result = mDevice.getSerialNumber(); + } catch (SecurityException e) { + + } } if (result == null) { result = ""; ``` Need some devs to tell us how to handle it properly, it sounds like that SDL just want to see how many usb devices attached when it starts (but not interact so no permission needed here), and SDL gets some info of them, then Google suddenly say that you need to ask permission for one of the info... (In reply to Alynx Zhou from comment #1) > Got similar problem when a USB Type-C earphone is plugged, app crashed on > start with following expection: > > java.lang.RuntimeException: Unable to start activity > ComponentInfo{one.alynx.flipclock/one.alynx.flipclock.MainActivity}: > java.lang.SecurityException: User has not given 10348/one.alynx.flipclock > permission to access device /dev/bus/usb/001/002 > at > android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3324) > at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3473) > at > android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem. > java:83) > at > android.app.servertransaction.TransactionExecutor. > executeCallbacks(TransactionExecutor.java:135) > at > android.app.servertransaction.TransactionExecutor. > execute(TransactionExecutor.java:95) > at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2060) > at android.os.Handler.dispatchMessage(Handler.java:107) > at android.os.Looper.loop(Looper.java:238) > at android.app.ActivityThread.main(ActivityThread.java:7619) > at java.lang.reflect.Method.invoke(Native Method) > at > com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java: > 539) > at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) > Caused by: java.lang.SecurityException: User has not given > 10348/one.alynx.flipclock permission to access device /dev/bus/usb/001/002 > at android.os.Parcel.createException(Parcel.java:2074) > at android.os.Parcel.readException(Parcel.java:2042) > at android.os.Parcel.readException(Parcel.java:1990) > at > android.hardware.usb.IUsbSerialReader$Stub$Proxy.getSerial(IUsbSerialReader. > java:123) > at android.hardware.usb.UsbDevice.getSerialNumber(UsbDevice.java:143) > at org.libsdl.app.HIDDeviceUSB.getSerialNumber(HIDDeviceUSB.java:56) > at > org.libsdl.app.HIDDeviceManager.connectHIDDeviceUSB(HIDDeviceManager.java: > 362) > at > org.libsdl.app.HIDDeviceManager.handleUsbDeviceAttached(HIDDeviceManager. > java:324) > at org.libsdl.app.HIDDeviceManager.initializeUSB(HIDDeviceManager.java:228) > at org.libsdl.app.HIDDeviceManager.<init>(HIDDeviceManager.java:152) > at org.libsdl.app.HIDDeviceManager.acquire(HIDDeviceManager.java:36) > at org.libsdl.app.SDLActivity.onCreate(SDLActivity.java:248) > at android.app.Activity.performCreate(Activity.java:7894) > at android.app.Activity.performCreate(Activity.java:7881) > at > android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307) > at > android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3299) > ... 11 more > Caused by: android.os.RemoteException: Remote stack trace: > at > com.android.server.usb.UsbUserSettingsManager. > checkPermission(UsbUserSettingsManager.java:177) > at com.android.server.usb.UsbSerialReader.getSerial(UsbSerialReader.java:96) > at > android.hardware.usb.IUsbSerialReader$Stub.onTransact(IUsbSerialReader.java: > 84) > at android.os.Binder.execTransactInternal(Binder.java:1030) > at android.os.Binder.execTransact(Binder.java:1003) > > My app does not need USB support, I also commented out usb permissions in > Manifest, why this happened? Can use your earphone for listening and speaking? There are the audio subsystems, SDL2 uses. (In reply to Alynx Zhou from comment #2) > Hi Gerhard, is your `targetSdkVersion` is 29 or higher? I found some reason > here: > > https://developer.android.com/reference/android/hardware/usb/ > UsbDevice#getSerialNumber() > > Because I submitted my apk to Play Store and it asked me to update > `targetSdkVersion` to 29, so I changed from 26 to 29. And according to the > doc, this method, is the only one that throws Exception when app have no > permission to USB device, and this only happens when `targetSdkVersion` is > 29 or higher. > > Since original getSerialNumber returns "" when no SerialNumber returns, I > think it's not important so I use the following patch to ignore this > Exception: > > ``` > diff --git a/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java > b/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java > index 33816e3..98c0f9d 100644 > --- a/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java > +++ b/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java > @@ -53,7 +53,14 @@ class HIDDeviceUSB implements HIDDevice { > public String getSerialNumber() { > String result = null; > if (Build.VERSION.SDK_INT >= 21) { > - result = mDevice.getSerialNumber(); > + // If `targetSdkVersion` is 29 or higher, `getProductName()` > will > + // throw `SecurityException` when no permission requested. Not > sure > + // why SDL2 needs this but it seems not important so just > ignore it. > + try { > + result = mDevice.getSerialNumber(); > + } catch (SecurityException e) { > + > + } > } > if (result == null) { > result = ""; > ``` > > Need some devs to tell us how to handle it properly, it sounds like that SDL > just want to see how many usb devices attached when it starts (but not > interact so no permission needed here), and SDL gets some info of them, then > Google suddenly say that you need to ask permission for one of the info... Yes, it is SDK version 29. Well, I require a permission for using the gamepad. I don't get any exception when the gamepad is not connected. So it somehow makes sense to me. Can you still use a USB C Gamepad with your diff or do you have to reconnect while your app is running? @Gerhard Sorry I cannot provide further info because this log is from my friend actually, I cannot reproduce it on my phone, but when I send my app to him, him got crash and send this log to me... Hello, recently someone reported a crash in one of our projects that uses SDL. The crash happends when they tries to plug in physical keyboard or joystick. Since the logcat is same as the OP posted, I'd be worth to add the solution here. Add this intent-filter to AndroidManifest.xml: <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> |
When I plug in a 8bitdo controller (and many others) the app crashes. The java exception thrown is as follows: java.lang.RuntimeException: at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3304) at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3443) at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2040) at android.os.Handler.dispatchMessage (Handler.java:107) at android.os.Looper.loop (Looper.java:221) at android.app.ActivityThread.main (ActivityThread.java:7520) at java.lang.reflect.Method.invoke (Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:950) Caused by: java.lang.SecurityException: at android.os.Parcel.createException (Parcel.java:2074) at android.os.Parcel.readException (Parcel.java:2042) at android.os.Parcel.readException (Parcel.java:1990) at android.hardware.usb.IUsbSerialReader$Stub$Proxy.getSerial (IUsbSerialReader.java:123) at android.hardware.usb.UsbDevice.getSerialNumber (UsbDevice.java:143) at org.libsdl.app.HIDDeviceUSB.getSerialNumber (Unknown Source:8) at org.libsdl.app.HIDDeviceManager.connectHIDDeviceUSB (Unknown Source:110) at org.libsdl.app.HIDDeviceManager.handleUsbDeviceAttached (Unknown Source) at org.libsdl.app.HIDDeviceManager.initializeUSB (Unknown Source:65) at org.libsdl.app.HIDDeviceManager.<init> (Unknown Source:81) at org.libsdl.app.HIDDeviceManager.acquire (Unknown Source:6) at org.libsdl.app.SDLActivity.onCreate (Unknown Source:214) at android.app.Activity.performCreate (Activity.java:7899) at android.app.Activity.performCreate (Activity.java:7886) at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1309) at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3279) Caused by: android.os.RemoteException: at com.android.server.usb.UsbUserSettingsManager.checkPermission (UsbUserSettingsManager.java:177) at com.android.server.usb.UsbSerialReader.getSerial (UsbSerialReader.java:96) at android.hardware.usb.IUsbSerialReader$Stub.onTransact (IUsbSerialReader.java:84) at android.os.Binder.execTransactInternal (Binder.java:1021) at android.os.Binder.execTransact (Binder.java:994) The problem is that under /home/gerstrong/workspace/cgenius-crossbuild/android/commandergenius/project/jni/sdl-2.0/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java at line 362 device.getSerialNumber() cannot work of no permission is given. The dialog is never called because openDevice was not called at this stage. NO idea why this happens. I worked around this by adding following code between lines 361 and 362: if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) { HIDDeviceOpenPending(id); try { mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0)); } catch (Exception e) { Log.v(TAG, "Couldn't request permission for USB device " + usbDevice); HIDDeviceOpenResult(id, false); return; } } This help my App showing the request persmission dialog and if the user gives it, everything works fine. I still think, this code should not exist. Maybe openDevice must be called from somewhere. Btw. this expection is thrown before the Application even starts.