| Summary: | Haptic doesn't work properly when native main runs for the second time (ie app closed and brought in foreground from the task manager) | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Michele Caini <michele.caini> |
| Component: | haptic | Assignee: | Ryan C. Gordon <icculus> |
| Status: | NEW --- | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | ||
| Version: | 2.0.8 | ||
| Hardware: | x86_64 | ||
| OS: | Android (All) | ||
Steps to reproduce: * Start an app that uses the haptic subsystem * Return from the main (somehow, as an example through a close button) * Select the app from the Android's task manager Two possible results: * If you wait for a while before to bring the app in foreground, everything works fine * If you get the app up and running immediately, the haptic subsystem isn't (re)initialized properly The problem is due to this function (android/SDL_syshaptic.c): int SDL_SYS_HapticInit(void) { /* Support for device connect/disconnect is API >= 16 only, * so we poll every three seconds * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html */ static Uint32 timeout = 0; if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { timeout = SDL_GetTicks() + 3000; Android_JNI_PollHapticDevices(); } return (numhaptics); } Because we returned from main, the library is reinitialized and SDL_GetTicks starts from 0. Therefore the condition (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) is likely to be false and thus Android_JNI_PollHapticDevices is never invoked. It means that haptic devices aren't detected when during the second run of our main function. This is also the reason for which everything works fine if we wait a while before to bring the app again in foreground from the task manager. Time passes and (timeout - SDL_GetTicks()) is true eventually. Quite subtle a bug, pretty hard to find. I hope I succeeded in describing it. Let me know if I can provide you with more details. --- The patch is straightforward indeed and involves both SDL_SYS_HapticInit and SDL_SYS_HapticQuit. Basically, put the timeout variable out of the SDL_SYS_HapticInit function and reset it on quit. Something along this line works as expected (tested on my Android device): static SDL_hapticlist_item *SDL_hapticlist = NULL; static SDL_hapticlist_item *SDL_hapticlist_tail = NULL; static int numhaptics = 0; static Uint32 pollTimeout = 0; // ... int SDL_SYS_HapticInit(void) { /* Support for device connect/disconnect is API >= 16 only, * so we poll every three seconds * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html */ if (SDL_TICKS_PASSED(SDL_GetTicks(), pollTimeout)) { pollTimeout = SDL_GetTicks() + 3000; Android_JNI_PollHapticDevices(); } return (numhaptics); } // ... void SDL_SYS_HapticQuit(void) { SDL_hapticlist_item *item = NULL; SDL_hapticlist_item *next = NULL; for (item = SDL_hapticlist; item; item = next) { next = item->next; SDL_free(item); } SDL_hapticlist = SDL_hapticlist_tail = NULL; pollTimeout = 0; numhaptics = 0; return; }