docs/README-android.md
author Sam Lantinga <slouken@libsdl.org>
Sun, 10 Dec 2017 09:17:33 -0800
changeset 11758 c70cf178aacb
parent 11659 b2fd0f264cd3
permissions -rw-r--r--
Workaround for bug 3931 - spurious SDL_MOUSEMOTION events with SDL_HINT_MOUSE_RELATIVE_MODE_WARP 1 since Windows 10 Fall Creators update

Elisée Maurer

The attached minimal program sets the SDL_HINT_MOUSE_RELATIVE_MODE_WARP to 1, enables relative mouse mode then logs all SDL_MOUSEMOTION xrel values as they happen.

When moving the mouse exclusively to the right:

* On a Windows 10 installation before Fall Creators update (for instance, Version 10.0.15063 Build 15063), only positive values are reported, as expected
* On a Windows 10 installation after Fall Creators update (for instance, Version 10.0.16299 Update 16299), a mix of positive and negative values are reported.

3 different people have reproduced this bug and have confirmed it started to happen after the Fall Creators update was installed. It happens with SDL 2.0.7 as well as latest default branch as of today.

It seems like some obscure (maybe unintended) Windows behavior change? Haven't been able to pin it down more yet.

(To force-upgrade a Windows installation to the Fall Creators update, you can use the update assistant at https://www.microsoft.com/en-us/software-download/windows10)

Eric Wasylishen

Broken GetCursorPos / SetCursorPos based games on Win 10 fall creators are not limited to SDL.. I just tested winquake.exe (original 1997 exe) and it now has "jumps" in the mouse input if you try to look around in a circle. It uses GetCursorPos/SetCursorPos by default. Switching WinQuake to use directinput (-dinput flag) seems to get rid of the jumps.

Daniel Gibson

A friend tested on Win10 1607 (which is before the Fall Creators Update) and the the bug doesn't occur there, so the regression that SetCursorPos() doesn't reliably generate mouse events was indeed introduced with that update.
I even reproduced it in a minimal WinAPI-only application (https://gist.github.com/DanielGibson/b5b033c67b9137f0280af9fc53352c68), the weird thing is that if you don't do anything each "frame" (i.e. the mainloop only polls the events and does nothing else), there are a lot of mouse events with the coordinates you passed to SetCursorPos(), but when sleeping for 10ms in each iteration of the mainloop, those events basically don't happen anymore. Which is bad, because in games the each iteration of the mainloop usually takes 16ms..

I have a patch now that I find acceptable.
It checks for the windows version with RtlGetVersion() (https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx) and only if it's >= Win10 build 16299, enables the workaround.
All code is in video/windows/SDL_windowsevents.c
and the workaround is, that for each WM_MOUSEMOVE event, "if(isWin10FCUorNewer && mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp)", an addition mouse move event is generated with the coordinates of the center of the screen
(SDL_SendMouseMotion(data->window, mouseID, 0, center_x, center_y);) - which is exactly what would happen if windows generated those reliably itself.
This will cause SDL_PrivateSendMouseMotion() to set mouse->last_x = center_x; and mouse->last_y = center_y; so the next mouse relative mouse event will be calculated correctly.

If Microsoft ever fixes this bug, the IsWin10FCUorNewer() function would have to
be adjusted to also check for a maximum version, so the workaround is then disabled again.
     1 Android
     2 ================================================================================
     3 
     4 Matt Styles wrote a tutorial on building SDL for Android with Visual Studio:
     5 http://trederia.blogspot.de/2017/03/building-sdl2-for-android-with-visual.html
     6 
     7 The rest of this README covers the Android gradle style build process.
     8 
     9 If you are using the older ant build process, it is no longer officially
    10 supported, but you can use the "android-project-ant" directory as a template.
    11 
    12 
    13 ================================================================================
    14  Requirements
    15 ================================================================================
    16 
    17 Android SDK (version 16 or later)
    18 https://developer.android.com/sdk/index.html
    19 
    20 Android NDK r10e or later
    21 https://developer.android.com/tools/sdk/ndk/index.html
    22 
    23 Minimum API level supported by SDL: 14 (Android 4.0.1)
    24 
    25 
    26 ================================================================================
    27  How the port works
    28 ================================================================================
    29 
    30 - Android applications are Java-based, optionally with parts written in C
    31 - As SDL apps are C-based, we use a small Java shim that uses JNI to talk to 
    32   the SDL library
    33 - This means that your application C code must be placed inside an Android 
    34   Java project, along with some C support code that communicates with Java
    35 - This eventually produces a standard Android .apk package
    36 
    37 The Android Java code implements an "Activity" and can be found in:
    38 android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
    39 
    40 The Java code loads your game code, the SDL shared library, and
    41 dispatches to native functions implemented in the SDL library:
    42 src/core/android/SDL_android.c
    43 
    44 
    45 ================================================================================
    46  Building an app
    47 ================================================================================
    48 
    49 For simple projects you can use the script located at build-scripts/androidbuild.sh
    50 
    51 There's two ways of using it:
    52 
    53     androidbuild.sh com.yourcompany.yourapp < sources.list
    54     androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c
    55 
    56 sources.list should be a text file with a source file name in each line
    57 Filenames should be specified relative to the current directory, for example if
    58 you are in the build-scripts directory and want to create the testgles.c test, you'll
    59 run:
    60 
    61     ./androidbuild.sh org.libsdl.testgles ../test/testgles.c
    62 
    63 One limitation of this script is that all sources provided will be aggregated into
    64 a single directory, thus all your source files should have a unique name.
    65 
    66 Once the project is complete the script will tell you where the debug APK is located.
    67 If you want to create a signed release APK, you can use the project created by this
    68 utility to generate it.
    69 
    70 Finally, a word of caution: re running androidbuild.sh wipes any changes you may have
    71 done in the build directory for the app!
    72 
    73 
    74 For more complex projects, follow these instructions:
    75     
    76 1. Copy the android-project directory wherever you want to keep your projects
    77    and rename it to the name of your project.
    78 2. Move or symlink this SDL directory into the "<project>/app/jni" directory
    79 3. Edit "<project>/app/jni/src/Android.mk" to include your source files
    80 4. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
    81 
    82 If you want to use Android Studio (recommended), skip to the Android Studio section below.
    83 
    84 5. Run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device
    85 
    86 Here's an explanation of the files in the Android project, so you can customize them:
    87 
    88     android-project/app
    89         build.gradle            - build info including the application version and SDK
    90         src/main/AndroidManifest.xml	- package manifest. Among others, it contains the class name
    91         			  of the main Activity and the package name of the application.
    92         jni/			- directory holding native code
    93         jni/Application.mk	- Application JNI settings, including target platform and STL library
    94         jni/Android.mk		- Android makefile that can call recursively the Android.mk files in all subdirectories
    95         jni/SDL/		- (symlink to) directory holding the SDL library files
    96         jni/SDL/Android.mk	- Android makefile for creating the SDL shared library
    97         jni/src/		- directory holding your C/C++ source
    98         jni/src/Android.mk	- Android makefile that you should customize to include your source code and any library references
    99         src/main/assets/	- directory holding asset files for your application
   100         src/main/res/		- directory holding resources for your application
   101         src/main/res/mipmap-*	- directories holding icons for different phone hardware
   102         src/main/res/values/strings.xml	- strings used in your application, including the application name
   103         src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application.
   104 
   105 
   106 ================================================================================
   107  Customizing your application name
   108 ================================================================================
   109 
   110 To customize your application name, edit AndroidManifest.xml and replace
   111 "org.libsdl.app" with an identifier for your product package.
   112 
   113 Then create a Java class extending SDLActivity and place it in a directory
   114 under src matching your package, e.g.
   115 
   116     src/com/gamemaker/game/MyGame.java
   117 
   118 Here's an example of a minimal class file:
   119 
   120     --- MyGame.java --------------------------
   121     package com.gamemaker.game;
   122     
   123     import org.libsdl.app.SDLActivity; 
   124     
   125     /**
   126      * A sample wrapper class that just calls SDLActivity 
   127      */ 
   128     
   129     public class MyGame extends SDLActivity { }
   130     
   131     ------------------------------------------
   132 
   133 Then replace "SDLActivity" in AndroidManifest.xml with the name of your
   134 class, .e.g. "MyGame"
   135 
   136 
   137 ================================================================================
   138  Customizing your application icon
   139 ================================================================================
   140 
   141 Conceptually changing your icon is just replacing the "ic_launcher.png" files in
   142 the drawable directories under the res directory. There are several directories
   143 for different screen sizes.
   144 
   145 
   146 ================================================================================
   147  Loading assets
   148 ================================================================================
   149 
   150 Any files you put in the "app/src/main/assets" directory of your project
   151 directory will get bundled into the application package and you can load
   152 them using the standard functions in SDL_rwops.h.
   153 
   154 There are also a few Android specific functions that allow you to get other
   155 useful paths for saving and loading data:
   156 * SDL_AndroidGetInternalStoragePath()
   157 * SDL_AndroidGetExternalStorageState()
   158 * SDL_AndroidGetExternalStoragePath()
   159 
   160 See SDL_system.h for more details on these functions.
   161 
   162 The asset packaging system will, by default, compress certain file extensions.
   163 SDL includes two asset file access mechanisms, the preferred one is the so
   164 called "File Descriptor" method, which is faster and doesn't involve the Dalvik
   165 GC, but given this method does not work on compressed assets, there is also the
   166 "Input Stream" method, which is automatically used as a fall back by SDL. You
   167 may want to keep this fact in mind when building your APK, specially when large
   168 files are involved.
   169 For more information on which extensions get compressed by default and how to
   170 disable this behaviour, see for example:
   171     
   172 http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/
   173 
   174 
   175 ================================================================================
   176  Pause / Resume behaviour
   177 ================================================================================
   178 
   179 If SDL is compiled with SDL_ANDROID_BLOCK_ON_PAUSE defined (the default),
   180 the event loop will block itself when the app is paused (ie, when the user
   181 returns to the main Android dashboard). Blocking is better in terms of battery
   182 use, and it allows your app to spring back to life instantaneously after resume
   183 (versus polling for a resume message).
   184 
   185 Upon resume, SDL will attempt to restore the GL context automatically.
   186 In modern devices (Android 3.0 and up) this will most likely succeed and your
   187 app can continue to operate as it was.
   188 
   189 However, there's a chance (on older hardware, or on systems under heavy load),
   190 where the GL context can not be restored. In that case you have to listen for
   191 a specific message, (which is not yet implemented!) and restore your textures
   192 manually or quit the app (which is actually the kind of behaviour you'll see
   193 under iOS, if the OS can not restore your GL context it will just kill your app)
   194 
   195 
   196 ================================================================================
   197  Threads and the Java VM
   198 ================================================================================
   199 
   200 For a quick tour on how Linux native threads interoperate with the Java VM, take
   201 a look here: https://developer.android.com/guide/practices/jni.html
   202 
   203 If you want to use threads in your SDL app, it's strongly recommended that you
   204 do so by creating them using SDL functions. This way, the required attach/detach
   205 handling is managed by SDL automagically. If you have threads created by other
   206 means and they make calls to SDL functions, make sure that you call
   207 Android_JNI_SetupThread() before doing anything else otherwise SDL will attach
   208 your thread automatically anyway (when you make an SDL call), but it'll never
   209 detach it.
   210 
   211 
   212 ================================================================================
   213  Using STL
   214 ================================================================================
   215 
   216 You can use STL in your project by creating an Application.mk file in the jni
   217 folder and adding the following line:
   218 
   219     APP_STL := stlport_static
   220 
   221 For more information check out CPLUSPLUS-SUPPORT.html in the NDK documentation.
   222 
   223 
   224 ================================================================================
   225  Additional documentation
   226 ================================================================================
   227 
   228 The documentation in the NDK docs directory is very helpful in understanding the
   229 build process and how to work with native code on the Android platform.
   230 
   231 The best place to start is with docs/OVERVIEW.TXT
   232 
   233 
   234 ================================================================================
   235  Using Android Studio
   236 ================================================================================
   237 
   238 You can open your project directory with Android Studio and run it normally.
   239 
   240 
   241 ================================================================================
   242  Using the emulator
   243 ================================================================================
   244 
   245 There are some good tips and tricks for getting the most out of the
   246 emulator here: https://developer.android.com/tools/devices/emulator.html
   247 
   248 Especially useful is the info on setting up OpenGL ES 2.0 emulation.
   249 
   250 Notice that this software emulator is incredibly slow and needs a lot of disk space.
   251 Using a real device works better.
   252 
   253 
   254 ================================================================================
   255  Troubleshooting
   256 ================================================================================
   257 
   258 You can see if adb can see any devices with the following command:
   259 
   260     adb devices
   261 
   262 You can see the output of log messages on the default device with:
   263 
   264     adb logcat
   265 
   266 You can push files to the device with:
   267 
   268     adb push local_file remote_path_and_file
   269 
   270 You can push files to the SD Card at /sdcard, for example:
   271 
   272     adb push moose.dat /sdcard/moose.dat
   273 
   274 You can see the files on the SD card with a shell command:
   275 
   276     adb shell ls /sdcard/
   277 
   278 You can start a command shell on the default device with:
   279 
   280     adb shell
   281 
   282 You can remove the library files of your project (and not the SDL lib files) with:
   283 
   284     ndk-build clean
   285 
   286 You can do a build with the following command:
   287 
   288     ndk-build
   289 
   290 You can see the complete command line that ndk-build is using by passing V=1 on the command line:
   291 
   292     ndk-build V=1
   293 
   294 If your application crashes in native code, you can use addr2line to convert the
   295 addresses in the stack trace to lines in your code.
   296 
   297 For example, if your crash looks like this:
   298 
   299     I/DEBUG   (   31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
   300     I/DEBUG   (   31):  r0 00000000  r1 00001000  r2 00000003  r3 400085d4
   301     I/DEBUG   (   31):  r4 400085d0  r5 40008000  r6 afd41504  r7 436c6a7c
   302     I/DEBUG   (   31):  r8 436c6b30  r9 435c6fb0  10 435c6f9c  fp 4168d82c
   303     I/DEBUG   (   31):  ip 8346aff0  sp 436c6a60  lr afd1c8ff  pc afd1c902  cpsr 60000030
   304     I/DEBUG   (   31):          #00  pc 0001c902  /system/lib/libc.so
   305     I/DEBUG   (   31):          #01  pc 0001ccf6  /system/lib/libc.so
   306     I/DEBUG   (   31):          #02  pc 000014bc  /data/data/org.libsdl.app/lib/libmain.so
   307     I/DEBUG   (   31):          #03  pc 00001506  /data/data/org.libsdl.app/lib/libmain.so
   308 
   309 You can see that there's a crash in the C library being called from the main code.
   310 I run addr2line with the debug version of my code:
   311 
   312     arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
   313 
   314 and then paste in the number after "pc" in the call stack, from the line that I care about:
   315 000014bc
   316 
   317 I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23.
   318 
   319 You can add logging to your code to help show what's happening:
   320 
   321     #include <android/log.h>
   322     
   323     __android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
   324 
   325 If you need to build without optimization turned on, you can create a file called
   326 "Application.mk" in the jni directory, with the following line in it:
   327 
   328     APP_OPTIM := debug
   329 
   330 
   331 ================================================================================
   332  Memory debugging
   333 ================================================================================
   334 
   335 The best (and slowest) way to debug memory issues on Android is valgrind.
   336 Valgrind has support for Android out of the box, just grab code using:
   337 
   338     svn co svn://svn.valgrind.org/valgrind/trunk valgrind
   339 
   340 ... and follow the instructions in the file README.android to build it.
   341 
   342 One thing I needed to do on Mac OS X was change the path to the toolchain,
   343 and add ranlib to the environment variables:
   344 export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
   345 
   346 Once valgrind is built, you can create a wrapper script to launch your
   347 application with it, changing org.libsdl.app to your package identifier:
   348 
   349     --- start_valgrind_app -------------------
   350     #!/system/bin/sh
   351     export TMPDIR=/data/data/org.libsdl.app
   352     exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
   353     ------------------------------------------
   354 
   355 Then push it to the device:
   356 
   357     adb push start_valgrind_app /data/local
   358 
   359 and make it executable:
   360 
   361     adb shell chmod 755 /data/local/start_valgrind_app
   362 
   363 and tell Android to use the script to launch your application:
   364 
   365     adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
   366 
   367 If the setprop command says "could not set property", it's likely that
   368 your package name is too long and you should make it shorter by changing
   369 AndroidManifest.xml and the path to your class file in android-project/src
   370 
   371 You can then launch your application normally and waaaaaaaiiittt for it.
   372 You can monitor the startup process with the logcat command above, and
   373 when it's done (or even while it's running) you can grab the valgrind
   374 output file:
   375 
   376     adb pull /sdcard/valgrind.log
   377 
   378 When you're done instrumenting with valgrind, you can disable the wrapper:
   379 
   380     adb shell setprop wrap.org.libsdl.app ""
   381 
   382 
   383 ================================================================================
   384  Graphics debugging
   385 ================================================================================
   386 
   387 If you are developing on a compatible Tegra-based tablet, NVidia provides
   388 Tegra Graphics Debugger at their website. Because SDL2 dynamically loads EGL
   389 and GLES libraries, you must follow their instructions for installing the
   390 interposer library on a rooted device. The non-rooted instructions are not
   391 compatible with applications that use SDL2 for video.
   392 
   393 The Tegra Graphics Debugger is available from NVidia here:
   394 https://developer.nvidia.com/tegra-graphics-debugger
   395 
   396 
   397 ================================================================================
   398  Why is API level 14 the minimum required?
   399 ================================================================================
   400 
   401 The latest NDK toolchain doesn't support targeting earlier than API level 14.
   402 As of this writing, according to https://developer.android.com/about/dashboards/index.html
   403 about 99% of the Android devices accessing Google Play support API level 14 or
   404 higher (October 2017).
   405 
   406 
   407 ================================================================================
   408  A note regarding the use of the "dirty rectangles" rendering technique
   409 ================================================================================
   410 
   411 If your app uses a variation of the "dirty rectangles" rendering technique,
   412 where you only update a portion of the screen on each frame, you may notice a
   413 variety of visual glitches on Android, that are not present on other platforms.
   414 This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
   415 contexts, in particular the use of the eglSwapBuffers function. As stated in the
   416 documentation for the function "The contents of ancillary buffers are always 
   417 undefined after calling eglSwapBuffers".
   418 Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
   419 is not possible for SDL as it requires EGL 1.4, available only on the API level
   420 17+, so the only workaround available on this platform is to redraw the entire
   421 screen each frame.
   422 
   423 Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
   424 
   425 
   426 ================================================================================
   427  Known issues
   428 ================================================================================
   429 
   430 - The number of buttons reported for each joystick is hardcoded to be 36, which
   431 is the current maximum number of buttons Android can report.
   432