Android: create Pause/ResumeSem semaphore at higher level than CreateWindow()
authorSylvain Becker <sylvain.becker@gmail.com>
Mon, 14 Jan 2019 23:33:48 +0100
changeset 12546aab006efb893
parent 12545 599ebb123f0a
child 12547 f100ca4dd31e
Android: create Pause/ResumeSem semaphore at higher level than CreateWindow()

- If you call onPause() before CreateWindow(), SDLThread will run in infinite loop in background.

- If you call onPause() between a DestroyWindow() and a new CreateWindow(), semaphores are invalids.

SDLActivity.java: the first resume() starts the SDLThread, don't call
nativeResume() as it would post ResumeSem. And the first pause would
automatically be resumed.
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
src/core/android/SDL_android.c
src/video/android/SDL_androidwindow.c
     1.1 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Mon Jan 14 22:56:57 2019 +0100
     1.2 +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java	Mon Jan 14 23:33:48 2019 +0100
     1.3 @@ -505,10 +505,14 @@
     1.4                      mSDLThread = new Thread(new SDLMain(), "SDLThread");
     1.5                      mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
     1.6                      mSDLThread.start();
     1.7 +                    
     1.8 +                    // No nativeResume(), don't signal Android_ResumeSem
     1.9 +                    mSurface.handleResume();
    1.10 +                } else {
    1.11 +                    nativeResume();
    1.12 +                    mSurface.handleResume();
    1.13                  }
    1.14  
    1.15 -                nativeResume();
    1.16 -                mSurface.handleResume();
    1.17                  mCurrentNativeState = mNextNativeState;
    1.18              }
    1.19          }
     2.1 --- a/src/core/android/SDL_android.c	Mon Jan 14 22:56:57 2019 +0100
     2.2 +++ b/src/core/android/SDL_android.c	Mon Jan 14 23:33:48 2019 +0100
     2.3 @@ -439,6 +439,17 @@
     2.4          __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ActivityMutex mutex");
     2.5      }
     2.6  
     2.7 +
     2.8 +    Android_PauseSem = SDL_CreateSemaphore(0);
     2.9 +    if (Android_PauseSem == NULL) {
    2.10 +        __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_PauseSem semaphore");
    2.11 +    }
    2.12 +
    2.13 +    Android_ResumeSem = SDL_CreateSemaphore(0);
    2.14 +    if (Android_ResumeSem == NULL) {
    2.15 +        __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ResumeSem semaphore");
    2.16 +    }
    2.17 +
    2.18      mActivityClass = (jclass)((*env)->NewGlobalRef(env, cls));
    2.19  
    2.20      midGetNativeSurface = (*env)->GetStaticMethodID(env, mActivityClass,
    2.21 @@ -961,6 +972,16 @@
    2.22          Android_ActivityMutex = NULL;
    2.23      }
    2.24  
    2.25 +    if (Android_PauseSem) {
    2.26 +        SDL_DestroySemaphore(Android_PauseSem);
    2.27 +        Android_PauseSem = NULL;
    2.28 +    }
    2.29 +
    2.30 +    if (Android_ResumeSem) {
    2.31 +        SDL_DestroySemaphore(Android_ResumeSem);
    2.32 +        Android_ResumeSem = NULL;
    2.33 +    }
    2.34 +
    2.35      str = SDL_GetError();
    2.36      if (str && str[0]) {
    2.37          __android_log_print(ANDROID_LOG_ERROR, "SDL", "SDLActivity thread ends (error=%s)", str);
    2.38 @@ -982,14 +1003,14 @@
    2.39          SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
    2.40          SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
    2.41          SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
    2.42 -
    2.43 -        /* *After* sending the relevant events, signal the pause semaphore
    2.44 -         * so the event loop knows to pause and (optionally) block itself.
    2.45 -         * Sometimes 2 pauses can be queued (eg pause/resume/pause), so it's
    2.46 -         * always increased. */
    2.47 -        SDL_SemPost(Android_PauseSem);
    2.48      }
    2.49  
    2.50 +    /* *After* sending the relevant events, signal the pause semaphore
    2.51 +     * so the event loop knows to pause and (optionally) block itself.
    2.52 +     * Sometimes 2 pauses can be queued (eg pause/resume/pause), so it's
    2.53 +     * always increased. */
    2.54 +    SDL_SemPost(Android_PauseSem);
    2.55 +
    2.56      SDL_UnlockMutex(Android_ActivityMutex);
    2.57  }
    2.58  
    2.59 @@ -1006,13 +1027,14 @@
    2.60          SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
    2.61          SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
    2.62          SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
    2.63 -        /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
    2.64 -         * We can't restore the GL Context here because it needs to be done on the SDL main thread
    2.65 -         * and this function will be called from the Java thread instead.
    2.66 -         */
    2.67 -        SDL_SemPost(Android_ResumeSem);
    2.68      }
    2.69  
    2.70 +    /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
    2.71 +     * We can't restore the GL Context here because it needs to be done on the SDL main thread
    2.72 +     * and this function will be called from the Java thread instead.
    2.73 +     */
    2.74 +    SDL_SemPost(Android_ResumeSem);
    2.75 +
    2.76      SDL_UnlockMutex(Android_ActivityMutex);
    2.77  }
    2.78  
     3.1 --- a/src/video/android/SDL_androidwindow.c	Mon Jan 14 22:56:57 2019 +0100
     3.2 +++ b/src/video/android/SDL_androidwindow.c	Mon Jan 14 23:33:48 2019 +0100
     3.3 @@ -49,9 +49,6 @@
     3.4          goto endfunction;
     3.5      }
     3.6  
     3.7 -    Android_PauseSem = SDL_CreateSemaphore(0);
     3.8 -    Android_ResumeSem = SDL_CreateSemaphore(0);
     3.9 -
    3.10      /* Set orientation */
    3.11      Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
    3.12  
    3.13 @@ -171,10 +168,6 @@
    3.14  
    3.15      if (window == Android_Window) {
    3.16          Android_Window = NULL;
    3.17 -        if (Android_PauseSem) SDL_DestroySemaphore(Android_PauseSem);
    3.18 -        if (Android_ResumeSem) SDL_DestroySemaphore(Android_ResumeSem);
    3.19 -        Android_PauseSem = NULL;
    3.20 -        Android_ResumeSem = NULL;
    3.21  
    3.22          if (window->driverdata) {
    3.23              SDL_WindowData *data = (SDL_WindowData *) window->driverdata;