Fixed bug 3012 - Android accelerometer joystick axis values overflow when values from Android are larger than gravity
authorSam Lantinga <slouken@libsdl.org>
Sun, 14 Jun 2015 19:25:12 -0700
changeset 97410ff5994253c2
parent 9740 55e88e3bc7cc
child 9742 4189503733ac
Fixed bug 3012 - Android accelerometer joystick axis values overflow when values from Android are larger than gravity

Magnus Bjerke Vik

This causes issues when for instance using the joystick API to make an Android phone rotate an object by rotating the phone. When the absolute value of an axis reported by android is larger than earth gravity, SDL will overflow the Sint16 value used for joystick axes, causing sporadic movements when close to the gravity. Just holding the phone so that e.g. Y points directly upwards will make it unstable, and even more if you just tap the phone gently from below (increasing the acceleration).

More detailed: SDLActivity gets the accelerometer values in onSensorChanged and divides each axis by earth gravity. SDL_SYS_JoystickUpdate takes each of the axis values, multiplies them by 32767.0 (largest Sint16), and the casts them to Sint16. From this you can see that any value from Android that exceeds earth gravity will overflow the joystick axis.

A fix is to clamp the values so that they won't overflow the Sint16.
src/joystick/android/SDL_sysjoystick.c
     1.1 --- a/src/joystick/android/SDL_sysjoystick.c	Sun Jun 14 19:21:13 2015 -0700
     1.2 +++ b/src/joystick/android/SDL_sysjoystick.c	Sun Jun 14 19:25:12 2015 -0700
     1.3 @@ -518,6 +518,15 @@
     1.4              if (item->joystick) {
     1.5                  if (Android_JNI_GetAccelerometerValues(values)) {
     1.6                      for ( i = 0; i < 3; i++ ) {
     1.7 +                        if (values[i] > 1.0f)
     1.8 +                        {
     1.9 +                            values[i] = 1.0f;
    1.10 +                        }
    1.11 +                        else if (values[i] < -1.0f)
    1.12 +                        {
    1.13 +                            values[i] = -1.0f;
    1.14 +                        }
    1.15 +
    1.16                          value = (Sint16)(values[i] * 32767.0f);
    1.17                          SDL_PrivateJoystickAxis(item->joystick, i, value);
    1.18                      }