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 4141 - Haptic doesn't work properly when native main runs for the second time (ie app closed and brought in foreground from the task manager)
Summary: Haptic doesn't work properly when native main runs for the second time (ie ap...
Status: NEW
Alias: None
Product: SDL
Classification: Unclassified
Component: haptic (show other bugs)
Version: 2.0.8
Hardware: x86_64 Android (All)
: P2 normal
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-04-18 12:41 UTC by Michele Caini
Modified: 2018-04-18 12:41 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michele Caini 2018-04-18 12:41:41 UTC
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;
    }