We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5307

Summary: Google Play console reporting crashes on Samsung Galaxy A51 Reporting crashes in in handleMotionEvent
Product: SDL Reporter: sdlbugs
Component: joystickAssignee: Sam Lantinga <slouken>
Status: NEW --- QA Contact: Sam Lantinga <slouken>
Severity: major    
Priority: P2 CC: sylvain.becker
Version: 2.0.12   
Hardware: ARM   
OS: Android (All)   
Attachments: Patch to prevent illegal array access

Description sdlbugs 2020-10-06 11:37:47 UTC
Created attachment 4475 [details]
Patch to prevent illegal array access

My #1 cause of crashes reported on Google Play console is:

Samsung Galaxy A51 5G Android 10 (SDK 29)
java.lang.IndexOutOfBoundsException: 
  at java.util.ArrayList.get (ArrayList.java:437)
  at org.libsdl.app.SDLJoystickHandler_API16.handleMotionEvent (SDLControllerManager.java:291)
  at org.libsdl.app.SDLControllerManager.handleJoystickMotionEvent (SDLControllerManager.java:57)

A quick look at the code suggests that handleMotionEvent() checks the array index before processing BUT assumes that all hats have two axes. 

   @Override
    public boolean handleMotionEvent(MotionEvent event) {
        if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) {
...
            switch(action) {
                case MotionEvent.ACTION_MOVE:
...
                        for (int i = 0; i < joystick.hats.size(); i+=2) {
                            int hatX = Math.round(event.getAxisValue( joystick.hats.get(i).getAxis(), actionPointerIndex ) );
                            int hatY = Math.round(event.getAxisValue( joystick.hats.get(i+1).getAxis(), actionPointerIndex ) );  // <--- exception here!
...
    }

So, it checks i is within range, but then uses i+1.
I'm guessing that on the A51 there is a hat that only has a single axis somehow.

There are I guess several possible root causes for this:
 - It not detecting the second hat axis
 - It misclassifying something as/as not a hat axis
 - Actually having only a single axis on a hat
 
I don't have access to an A51 to try it though, but I've added some defensive code that will zero the missing axis (just checks it exists before using it). Patch attached. 

While this should fix the exception, I'm not sure quite how this single axis hat will behave!
Comment 1 Sylvain 2020-10-06 14:08:53 UTC
Indeed, it seems an issue: 
not sure if we want to add or discard the last hat, when it's an odd length.

We only reference hat.size()/2 here:

https://hg.libsdl.org/SDL/file/9dfeb15ad47e/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#l207
Comment 2 Sylvain 2020-10-07 15:34:22 UTC
Fixed slightly differently in https://hg.libsdl.org/SDL/rev/c771059d843d

anyway, we register only size()/2 pair of axes, so we ignore the last one.

Please double-check.

I let the ticket opened, maybe Sam has a better idea of fixing this !
Comment 3 Sam Lantinga 2020-10-07 18:58:02 UTC
Any chance you can get logs to tell what controller people are using in this case?
Comment 4 sdlbugs 2020-10-08 07:59:00 UTC
Unfortunately no A51 logs for that period, which sadly isn't that surprising as the crash is in the initialisation code.

I did find one example of an A51 in the logs on the same version of the code earlier last month, which reported no controllers connected, so it's possible to get an A51 to work with my app.
This probably means it's some kind of external/bluetooth controller that's been paired to the phone.

Once my workaround has been released and it no longer crashes I should be able to get logs to confirm the controller in use.
Comment 5 sdlbugs 2020-10-08 08:11:03 UTC
It may be worth noting that this has affected 7 different users, but all with the same device on Android 10.
It hasn't affected any android user with a different device.
Comment 6 sdlbugs 2020-10-08 08:14:39 UTC
By far the most common controller used on Android according to my wider logs is some variant on the official Xbox One Wireless Controller (or a knock-off controller pretending to be an Xbox One Wireless Controller, which happens a lot).
Comment 7 Sylvain 2020-10-08 09:03:49 UTC
Just to say: my apps doesn't have this crash. I don't use the Bluetooth permission. And I have many users with Samsung Galaxy A51 (a51).

(I am not sure if it would be possible to connect a bluetooth controller anyway and use it.)


Does your app need/ask for the bluetooth permission ?  
Could the affected joystick be a HID one ?