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.
This commit is contained in:
Sylvain Becker 2019-01-14 23:33:48 +01:00
parent 1b24b2eca5
commit dc263450ff
3 changed files with 39 additions and 20 deletions

View file

@ -505,10 +505,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
mSDLThread = new Thread(new SDLMain(), "SDLThread"); mSDLThread = new Thread(new SDLMain(), "SDLThread");
mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true); mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
mSDLThread.start(); mSDLThread.start();
}
// No nativeResume(), don't signal Android_ResumeSem
mSurface.handleResume();
} else {
nativeResume(); nativeResume();
mSurface.handleResume(); mSurface.handleResume();
}
mCurrentNativeState = mNextNativeState; mCurrentNativeState = mNextNativeState;
} }
} }

View file

@ -439,6 +439,17 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ActivityMutex mutex"); __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ActivityMutex mutex");
} }
Android_PauseSem = SDL_CreateSemaphore(0);
if (Android_PauseSem == NULL) {
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_PauseSem semaphore");
}
Android_ResumeSem = SDL_CreateSemaphore(0);
if (Android_ResumeSem == NULL) {
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ResumeSem semaphore");
}
mActivityClass = (jclass)((*env)->NewGlobalRef(env, cls)); mActivityClass = (jclass)((*env)->NewGlobalRef(env, cls));
midGetNativeSurface = (*env)->GetStaticMethodID(env, mActivityClass, midGetNativeSurface = (*env)->GetStaticMethodID(env, mActivityClass,
@ -961,6 +972,16 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeQuit)(
Android_ActivityMutex = NULL; Android_ActivityMutex = NULL;
} }
if (Android_PauseSem) {
SDL_DestroySemaphore(Android_PauseSem);
Android_PauseSem = NULL;
}
if (Android_ResumeSem) {
SDL_DestroySemaphore(Android_ResumeSem);
Android_ResumeSem = NULL;
}
str = SDL_GetError(); str = SDL_GetError();
if (str && str[0]) { if (str && str[0]) {
__android_log_print(ANDROID_LOG_ERROR, "SDL", "SDLActivity thread ends (error=%s)", str); __android_log_print(ANDROID_LOG_ERROR, "SDL", "SDLActivity thread ends (error=%s)", str);
@ -982,13 +1003,13 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePause)(
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0); SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND); SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND); SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
}
/* *After* sending the relevant events, signal the pause semaphore /* *After* sending the relevant events, signal the pause semaphore
* so the event loop knows to pause and (optionally) block itself. * so the event loop knows to pause and (optionally) block itself.
* Sometimes 2 pauses can be queued (eg pause/resume/pause), so it's * Sometimes 2 pauses can be queued (eg pause/resume/pause), so it's
* always increased. */ * always increased. */
SDL_SemPost(Android_PauseSem); SDL_SemPost(Android_PauseSem);
}
SDL_UnlockMutex(Android_ActivityMutex); SDL_UnlockMutex(Android_ActivityMutex);
} }
@ -1006,12 +1027,13 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeResume)(
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND); SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0); SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0); SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
/* Signal the resume semaphore so the event loop knows to resume and restore the GL Context /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
* We can't restore the GL Context here because it needs to be done on the SDL main thread * We can't restore the GL Context here because it needs to be done on the SDL main thread
* and this function will be called from the Java thread instead. * and this function will be called from the Java thread instead.
*/ */
SDL_SemPost(Android_ResumeSem); SDL_SemPost(Android_ResumeSem);
}
SDL_UnlockMutex(Android_ActivityMutex); SDL_UnlockMutex(Android_ActivityMutex);
} }

View file

@ -49,9 +49,6 @@ Android_CreateWindow(_THIS, SDL_Window * window)
goto endfunction; goto endfunction;
} }
Android_PauseSem = SDL_CreateSemaphore(0);
Android_ResumeSem = SDL_CreateSemaphore(0);
/* Set orientation */ /* Set orientation */
Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS)); Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
@ -171,10 +168,6 @@ Android_DestroyWindow(_THIS, SDL_Window *window)
if (window == Android_Window) { if (window == Android_Window) {
Android_Window = NULL; Android_Window = NULL;
if (Android_PauseSem) SDL_DestroySemaphore(Android_PauseSem);
if (Android_ResumeSem) SDL_DestroySemaphore(Android_ResumeSem);
Android_PauseSem = NULL;
Android_ResumeSem = NULL;
if (window->driverdata) { if (window->driverdata) {
SDL_WindowData *data = (SDL_WindowData *) window->driverdata; SDL_WindowData *data = (SDL_WindowData *) window->driverdata;