From ca4bd4b63cc4e324f34d6885dfd9a41f0c5233f3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 23 Jul 2024 20:55:24 -0700 Subject: [PATCH] Android life cycle behavior more closely matches iOS This change also decouples the pause/resume handling from the video subsystem on Android, so applications that don't use SDL for video can get application life cycle events. The semantics for the life cycle events are that they need to be handled in an event watch callback, and once they've been delivered, the application will block until it's been resumed. SDL_HINT_ANDROID_BLOCK_ON_PAUSE can be used to control that behavior, and if that's set to "0", then the application will continue to run in the background at low CPU usage until being resumed or stopped. SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO has been removed, and the audio will be paused when the application is paused. Fixes https://github.com/libsdl-org/SDL/issues/3193 --- docs/README-android.md | 101 ++++++++++---- docs/README-migration.md | 1 + include/SDL3/SDL_events.h | 8 +- include/SDL3/SDL_hints.h | 15 --- src/SDL.c | 9 ++ src/core/android/SDL_android.c | 10 +- src/core/android/SDL_android.h | 10 +- src/events/SDL_events.c | 9 +- src/render/SDL_render.c | 6 +- src/video/android/SDL_androidevents.c | 182 +++++++++----------------- src/video/android/SDL_androidevents.h | 5 +- src/video/android/SDL_androidgl.c | 8 +- src/video/android/SDL_androidvideo.c | 11 -- src/video/android/SDL_androidvideo.h | 3 - src/video/android/SDL_androidwindow.c | 12 +- 15 files changed, 183 insertions(+), 207 deletions(-) diff --git a/docs/README-android.md b/docs/README-android.md index 700bbdb27..754d2edfa 100644 --- a/docs/README-android.md +++ b/docs/README-android.md @@ -189,42 +189,87 @@ disable this behaviour, see for example: http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/ -Pause / Resume behaviour +Activity lifecycle ================================================================================ +On Android the application goes through a fixed life cycle and you will get +notifications of state changes via application events. When these events +are delivered you must handle them in an event callback because the OS may +not give you any processing time after the events are delivered. + +e.g. + + int HandleAppEvents(void *userdata, SDL_Event *event) + { + switch (event->type) + { + case SDL_EVENT_TERMINATING: + /* Terminate the app. + Shut everything down before returning from this function. + */ + return 0; + case SDL_EVENT_LOW_MEMORY: + /* You will get this when your app is paused and iOS wants more memory. + Release as much memory as possible. + */ + return 0; + case SDL_EVENT_WILL_ENTER_BACKGROUND: + /* Prepare your app to go into the background. Stop loops, etc. + This gets called when the user hits the home button, or gets a call. + + You should not make any OpenGL graphics calls or use the rendering API, + in addition, you should set the render target to NULL, if you're using + it, e.g. call SDL_SetRenderTarget(renderer, NULL). + */ + return 0; + case SDL_EVENT_DID_ENTER_BACKGROUND: + /* Your app is NOT active at this point. */ + return 0; + case SDL_EVENT_WILL_ENTER_FOREGROUND: + /* This call happens when your app is coming back to the foreground. + Restore all your state here. + */ + return 0; + case SDL_EVENT_DID_ENTER_FOREGROUND: + /* Restart your loops here. + Your app is interactive and getting CPU again. + + You have access to the OpenGL context or rendering API at this point. + However, there's a chance (on older hardware, or on systems under heavy load), + where the graphics context can not be restored. You should listen for the + event SDL_EVENT_RENDER_DEVICE_RESET and recreate your OpenGL context and + restore your textures when you get it, or quit the app. + */ + return 0; + default: + /* No special processing, add it to the event queue */ + return 1; + } + } + + int main(int argc, char *argv[]) + { + SDL_SetEventFilter(HandleAppEvents, NULL); + + ... run your main loop + + return 0; + } + + +Note that if you are using main callbacks instead of a standard C main() function, +your SDL_AppEvent() callback will run as these events arrive and you do not need to +use SDL_SetEventFilter. + If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default), the event loop will block itself when the app is paused (ie, when the user returns to the main Android dashboard). Blocking is better in terms of battery use, and it allows your app to spring back to life instantaneously after resume (versus polling for a resume message). -Upon resume, SDL will attempt to restore the GL context automatically. -In modern devices (Android 3.0 and up) this will most likely succeed and your -app can continue to operate as it was. - -However, there's a chance (on older hardware, or on systems under heavy load), -where the GL context can not be restored. In that case you have to listen for -a specific message (SDL_EVENT_RENDER_DEVICE_RESET) and restore your textures -manually or quit the app. - -You should not use the SDL renderer API while the app going in background: -- SDL_EVENT_WILL_ENTER_BACKGROUND: - after you read this message, GL context gets backed-up and you should not - use the SDL renderer API. - - When this event is received, you have to set the render target to NULL, if you're using it. - (eg call SDL_SetRenderTarget(renderer, NULL)) - -- SDL_EVENT_DID_ENTER_FOREGROUND: - GL context is restored, and the SDL renderer API is available (unless you - receive SDL_EVENT_RENDER_DEVICE_RESET). - -Activity lifecycle -================================================================================ - -You can control activity re-creation (eg. onCreate()) behaviour. This allows to keep -or re-initialize java and native static datas, see SDL_hints.h: -- SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY +You can control activity re-creation (eg. onCreate()) behaviour. This allows you +to choose whether to keep or re-initialize java and native static datas, see +SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY in SDL_hints.h. Mouse / Touch events ================================================================================ diff --git a/docs/README-migration.md b/docs/README-migration.md index 77132c6bf..caf5cab33 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -767,6 +767,7 @@ Calling SDL_GetHint() with the name of the hint being changed from within a hint The following hints have been removed: * SDL_HINT_ACCELEROMETER_AS_JOYSTICK +* SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO - the audio will be paused when the application is paused, and SDL_HINT_ANDROID_BLOCK_ON_PAUSE can be used to control that * SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional * SDL_HINT_GRAB_KEYBOARD - use SDL_SetWindowKeyboardGrab() instead * SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver() instead diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 58467d3ae..0eaecb5af 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -79,14 +79,14 @@ typedef enum SDL_EventType /* Application events */ SDL_EVENT_QUIT = 0x100, /**< User-requested quit */ - /* These application events have special meaning on iOS, see README-ios.md for details */ - SDL_EVENT_TERMINATING, /**< The application is being terminated by the OS + /* These application events have special meaning on iOS and Android, see README-ios.md and README-android.md for details */ + SDL_EVENT_TERMINATING, /**< The application is being terminated by the OS Called on iOS in applicationWillTerminate() Called on Android in onDestroy() */ - SDL_EVENT_LOW_MEMORY, /**< The application is low on memory, free memory if possible. + SDL_EVENT_LOW_MEMORY, /**< The application is low on memory, free memory if possible. Called on iOS in applicationDidReceiveMemoryWarning() - Called on Android in onLowMemory() + Called on Android in onTrimMemory() */ SDL_EVENT_WILL_ENTER_BACKGROUND, /**< The application is about to enter the background Called on iOS in applicationWillResignActive() diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 373a039a2..a42aff063 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -102,21 +102,6 @@ extern "C" { */ #define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" -/** - * A variable to control whether SDL will pause audio in background. - * - * The variable can be set to the following values: - * - * - "0": Not paused, requires that SDL_HINT_ANDROID_BLOCK_ON_PAUSE be set to - * "0" - * - "1": Paused. (default) - * - * This hint should be set before SDL is initialized. - * - * \since This hint is available since SDL 3.0.0. - */ -#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO" - /** * A variable to control whether we trap the Android back button to handle it * manually. diff --git a/src/SDL.c b/src/SDL.c index 3cbd3b768..c5a171e9e 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -52,6 +52,7 @@ #include "thread/SDL_thread_c.h" #include "video/SDL_pixels_c.h" #include "video/SDL_video_c.h" +#include "video/android/SDL_androidevents.h" #include "filesystem/SDL_filesystem_c.h" #define SDL_INIT_EVERYTHING ~0U @@ -225,6 +226,10 @@ int SDL_InitSubSystem(Uint32 flags) SDL_InitMainThread(); +#ifdef SDL_PLATFORM_ANDROID + Android_InitEvents(); +#endif + #ifdef SDL_USE_LIBDBUS SDL_DBus_Init(); #endif @@ -571,6 +576,10 @@ void SDL_Quit(void) SDL_DBus_Quit(); #endif +#ifdef SDL_PLATFORM_ANDROID + Android_QuitEvents(); +#endif + SDL_SetObjectsInvalid(); SDL_ClearHints(); SDL_AssertionsQuit(); diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 3e1b8b4f0..40f43cc2d 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -403,6 +403,10 @@ static jobject javaAssetManagerRef = 0; /* Re-create activity hint */ static SDL_AtomicInt bAllowRecreateActivity; +static SDL_Mutex *Android_ActivityMutex = NULL; +SDL_Semaphore *Android_PauseSem = NULL; +SDL_Semaphore *Android_ResumeSem = NULL; + /******************************************************************************* Functions called by JNI *******************************************************************************/ @@ -903,18 +907,18 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)( } /* Lock / Unlock Mutex */ -void Android_ActivityMutex_Lock(void) +void Android_LockActivityMutex(void) { SDL_LockMutex(Android_ActivityMutex); } -void Android_ActivityMutex_Unlock(void) +void Android_UnlockActivityMutex(void) { SDL_UnlockMutex(Android_ActivityMutex); } /* Lock the Mutex when the Activity is in its 'Running' state */ -void Android_ActivityMutex_Lock_Running(void) +void Android_LockActivityMutexOnceRunning(void) { int pauseSignaled = 0; int resumeSignaled = 0; diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index c292f2499..fea6c426a 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -139,15 +139,19 @@ SDL_bool SDL_IsAndroidTV(void); SDL_bool SDL_IsChromebook(void); SDL_bool SDL_IsDeXMode(void); -void Android_ActivityMutex_Lock(void); -void Android_ActivityMutex_Unlock(void); -void Android_ActivityMutex_Lock_Running(void); +void Android_LockActivityMutex(void); +void Android_UnlockActivityMutex(void); +void Android_LockActivityMutexOnceRunning(void); /* File Dialogs */ SDL_bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void* userdata, const SDL_DialogFileFilter *filters, int nfilters, SDL_bool forwrite, SDL_bool multiple); +/* Semaphores for event state processing */ +extern SDL_Semaphore *Android_PauseSem; +extern SDL_Semaphore *Android_ResumeSem; + /* Ends C function definitions when using C++ */ #ifdef __cplusplus /* *INDENT-OFF* */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 1068788ad..a8fd5450f 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -34,6 +34,7 @@ #include "../sensor/SDL_sensor_c.h" #endif #include "../video/SDL_sysvideo.h" +#include "../video/android/SDL_androidevents.h" /* An arbitrary limit so we don't have unbounded growth */ #define SDL_MAX_QUEUED_EVENTS 65535 @@ -1173,18 +1174,22 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) /* Run the system dependent event loops */ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - /* Free old event memory */ SDL_FreeTemporaryMemory(); /* Release any keys held down from last frame */ SDL_ReleaseAutoReleaseKeys(); +#ifdef SDL_PLATFORM_ANDROID + /* Android event processing is independent of the video subsystem */ + Android_PumpEvents(); +#else /* Get events from the video subsystem */ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this) { _this->PumpEvents(_this); } +#endif #ifndef SDL_AUDIO_DISABLED SDL_UpdateAudio(); diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index a187a761c..7ebee08c9 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -968,7 +968,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) SDL_SetObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER, SDL_TRUE); #ifdef SDL_PLATFORM_ANDROID - Android_ActivityMutex_Lock_Running(); + Android_LockActivityMutexOnceRunning(); #endif if ((!window && !surface) || (window && surface)) { @@ -1127,7 +1127,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) SDL_renderers = renderer; #ifdef SDL_PLATFORM_ANDROID - Android_ActivityMutex_Unlock(); + Android_UnlockActivityMutex(); #endif SDL_ClearError(); @@ -1139,7 +1139,7 @@ error: SDL_SetObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER, SDL_FALSE); #ifdef SDL_PLATFORM_ANDROID - Android_ActivityMutex_Unlock(); + Android_UnlockActivityMutex(); #endif SDL_free(renderer->texture_formats); SDL_free(renderer); diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index 75313297c..df965240c 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -28,16 +28,10 @@ #include "../SDL_sysvideo.h" #include "../../events/SDL_events_c.h" - #include "../../audio/android/SDL_androidaudio.h" #include "../../audio/aaudio/SDL_aaudio.h" #include "../../audio/openslES/SDL_openslES.h" -/* Number of 'type' events in the event queue */ -static int SDL_NumberOfEvents(Uint32 type) -{ - return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type); -} #ifdef SDL_VIDEO_OPENGL_EGL static void android_egl_context_restore(SDL_Window *window) @@ -54,7 +48,7 @@ static void android_egl_context_restore(SDL_Window *window) event.common.timestamp = 0; SDL_PushEvent(&event); } - data->backup_done = 0; + data->backup_done = SDL_FALSE; if (data->has_swap_interval) { SDL_GL_SetSwapInterval(data->swap_interval); @@ -79,121 +73,44 @@ static void android_egl_context_backup(SDL_Window *window) /* We need to do this so the EGLSurface can be freed */ SDL_GL_MakeCurrent(window, NULL); - data->backup_done = 1; + data->backup_done = SDL_TRUE; } } #endif /* * Android_ResumeSem and Android_PauseSem are signaled from Java_org_libsdl_app_SDLActivity_nativePause and Java_org_libsdl_app_SDLActivity_nativeResume - * When the pause semaphore is signaled, if Android_PumpEvents_Blocking is used, the event loop will block until the resume signal is emitted. - * - * No polling necessary */ +static SDL_bool Android_EventsInitialized; +static SDL_bool Android_Paused; +static SDL_bool Android_PausedAudio; +static Sint32 Android_PausedWaitTime = -1; -void Android_PumpEvents_Blocking(SDL_VideoDevice *_this) +void Android_InitEvents(void) { - SDL_VideoData *videodata = _this->internal; - - if (videodata->isPaused) { -#ifdef SDL_VIDEO_OPENGL_EGL - /* Make sure this is the last thing we do before pausing */ - if (Android_Window && !Android_Window->external_graphics_context) { - SDL_LockMutex(Android_ActivityMutex); - android_egl_context_backup(Android_Window); - SDL_UnlockMutex(Android_ActivityMutex); - } -#endif - - ANDROIDAUDIO_PauseDevices(); - OPENSLES_PauseDevices(); - AAUDIO_PauseDevices(); - - if (SDL_WaitSemaphore(Android_ResumeSem) == 0) { - - videodata->isPaused = 0; - - /* Android_ResumeSem was signaled */ - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); - - ANDROIDAUDIO_ResumeDevices(); - OPENSLES_ResumeDevices(); - AAUDIO_ResumeDevices(); - - /* Restore the GL Context from here, as this operation is thread dependent */ -#ifdef SDL_VIDEO_OPENGL_EGL - if (Android_Window && !Android_Window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) { - SDL_LockMutex(Android_ActivityMutex); - android_egl_context_restore(Android_Window); - SDL_UnlockMutex(Android_ActivityMutex); - } -#endif - - /* Make sure SW Keyboard is restored when an app becomes foreground */ - if (Android_Window) { - Android_RestoreScreenKeyboardOnResume(_this, Android_Window); - } - - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND); - SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - } - } else { - if (videodata->isPausing || SDL_TryWaitSemaphore(Android_PauseSem) == 0) { - - /* Android_PauseSem was signaled */ - if (videodata->isPausing == 0) { - SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND); - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); - } - - /* We've been signaled to pause (potentially several times), but before we block ourselves, - * we need to make sure that the very last event (of the first pause sequence, if several) - * has reached the app */ - if (SDL_NumberOfEvents(SDL_EVENT_DID_ENTER_BACKGROUND) > SDL_GetSemaphoreValue(Android_PauseSem)) { - videodata->isPausing = 1; - } else { - videodata->isPausing = 0; - videodata->isPaused = 1; - } + if (!Android_EventsInitialized) { + if (SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, SDL_TRUE)) { + Android_PausedWaitTime = -1; + } else { + Android_PausedWaitTime = 100; } + Android_Paused = SDL_FALSE; + Android_EventsInitialized = SDL_TRUE; } } -void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this) +void Android_PumpEvents(void) { - SDL_VideoData *videodata = _this->internal; - static int backup_context = 0; +restart: + if (Android_Paused) { + if (SDL_WaitSemaphoreTimeout(Android_ResumeSem, Android_PausedWaitTime) == 0) { - if (videodata->isPaused) { - - if (backup_context) { - -#ifdef SDL_VIDEO_OPENGL_EGL - if (Android_Window && !Android_Window->external_graphics_context) { - SDL_LockMutex(Android_ActivityMutex); - android_egl_context_backup(Android_Window); - SDL_UnlockMutex(Android_ActivityMutex); - } -#endif - - if (videodata->pauseAudio) { - ANDROIDAUDIO_PauseDevices(); - OPENSLES_PauseDevices(); - AAUDIO_PauseDevices(); - } - - backup_context = 0; - } - - if (SDL_TryWaitSemaphore(Android_ResumeSem) == 0) { - - videodata->isPaused = 0; + Android_Paused = SDL_FALSE; /* Android_ResumeSem was signaled */ - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); + SDL_OnApplicationWillEnterForeground(); - if (videodata->pauseAudio) { + if (Android_PausedAudio) { ANDROIDAUDIO_ResumeDevices(); OPENSLES_ResumeDevices(); AAUDIO_ResumeDevices(); @@ -202,42 +119,61 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this) #ifdef SDL_VIDEO_OPENGL_EGL /* Restore the GL Context from here, as this operation is thread dependent */ if (Android_Window && !Android_Window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) { - SDL_LockMutex(Android_ActivityMutex); + Android_LockActivityMutex(); android_egl_context_restore(Android_Window); - SDL_UnlockMutex(Android_ActivityMutex); + Android_UnlockActivityMutex(); } #endif /* Make sure SW Keyboard is restored when an app becomes foreground */ if (Android_Window) { - Android_RestoreScreenKeyboardOnResume(_this, Android_Window); + Android_RestoreScreenKeyboardOnResume(SDL_GetVideoDevice(), Android_Window); } - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND); - SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_RESTORED, 0, 0); + SDL_OnApplicationDidEnterForeground(); } } else { - if (videodata->isPausing || SDL_TryWaitSemaphore(Android_PauseSem) == 0) { + if (SDL_TryWaitSemaphore(Android_PauseSem) == 0) { /* Android_PauseSem was signaled */ - if (videodata->isPausing == 0) { - SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND); - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); + SDL_OnApplicationWillEnterBackground(); + SDL_OnApplicationDidEnterBackground(); + + /* Make sure we handle potentially multiple pause/resume sequences */ + while (SDL_GetSemaphoreValue(Android_PauseSem) > 0) { + SDL_WaitSemaphore(Android_ResumeSem); + SDL_WaitSemaphore(Android_PauseSem); } - /* We've been signaled to pause (potentially several times), but before we block ourselves, - * we need to make sure that the very last event (of the first pause sequence, if several) - * has reached the app */ - if (SDL_NumberOfEvents(SDL_EVENT_DID_ENTER_BACKGROUND) > SDL_GetSemaphoreValue(Android_PauseSem)) { - videodata->isPausing = 1; - } else { - videodata->isPausing = 0; - videodata->isPaused = 1; - backup_context = 1; + /* The semantics are that as soon as the enter background event + * has been queued, the app will block. The application should + * do any life cycle handling in an event filter while the event + * was being queued. + */ +#ifdef SDL_VIDEO_OPENGL_EGL + if (Android_Window && !Android_Window->external_graphics_context) { + Android_LockActivityMutex(); + android_egl_context_backup(Android_Window); + Android_UnlockActivityMutex(); } +#endif + if (Android_PausedWaitTime < 0) { + /* We're blocking, also pause audio */ + ANDROIDAUDIO_PauseDevices(); + OPENSLES_PauseDevices(); + AAUDIO_PauseDevices(); + Android_PausedAudio = SDL_TRUE; + } + + Android_Paused = SDL_TRUE; + goto restart; } } } +void Android_QuitEvents(void) +{ + Android_EventsInitialized = SDL_FALSE; +} + #endif /* SDL_VIDEO_DRIVER_ANDROID */ diff --git a/src/video/android/SDL_androidevents.h b/src/video/android/SDL_androidevents.h index 35bd5b712..884d6f59f 100644 --- a/src/video/android/SDL_androidevents.h +++ b/src/video/android/SDL_androidevents.h @@ -22,5 +22,6 @@ #include "SDL_androidvideo.h" -extern void Android_PumpEvents_Blocking(SDL_VideoDevice *_this); -extern void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this); +extern void Android_InitEvents(void); +extern void Android_PumpEvents(void); +extern void Android_QuitEvents(void); diff --git a/src/video/android/SDL_androidgl.c b/src/video/android/SDL_androidgl.c index 68c5a5b96..d310fbb8a 100644 --- a/src/video/android/SDL_androidgl.c +++ b/src/video/android/SDL_androidgl.c @@ -48,11 +48,11 @@ SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *win { SDL_GLContext ret; - Android_ActivityMutex_Lock_Running(); + Android_LockActivityMutexOnceRunning(); ret = SDL_EGL_CreateContext(_this, window->internal->egl_surface); - SDL_UnlockMutex(Android_ActivityMutex); + Android_UnlockActivityMutex(); return ret; } @@ -61,7 +61,7 @@ int Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) { int retval; - SDL_LockMutex(Android_ActivityMutex); + Android_LockActivityMutex(); /* The following two calls existed in the original Java code * If you happen to have a device that's affected by their removal, @@ -72,7 +72,7 @@ int Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) _this->egl_data->eglWaitGL();*/ retval = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface); - SDL_UnlockMutex(Android_ActivityMutex); + Android_UnlockActivityMutex(); return retval; } diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index 02302c34d..b11b72500 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -63,9 +63,6 @@ static int Android_DeviceHeight = 0; static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; /* Default SurfaceView format, in case this is queried before being filled */ float Android_ScreenDensity = 1.0f; static float Android_ScreenRate = 0.0f; -SDL_Semaphore *Android_PauseSem = NULL; -SDL_Semaphore *Android_ResumeSem = NULL; -SDL_Mutex *Android_ActivityMutex = NULL; static SDL_SystemTheme Android_SystemTheme; static int Android_SuspendScreenSaver(SDL_VideoDevice *_this) @@ -83,7 +80,6 @@ static SDL_VideoDevice *Android_CreateDevice(void) { SDL_VideoDevice *device; SDL_VideoData *data; - SDL_bool block_on_pause; /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); @@ -103,12 +99,6 @@ static SDL_VideoDevice *Android_CreateDevice(void) /* Set the function pointers */ device->VideoInit = Android_VideoInit; device->VideoQuit = Android_VideoQuit; - block_on_pause = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, SDL_TRUE); - if (block_on_pause) { - device->PumpEvents = Android_PumpEvents_Blocking; - } else { - device->PumpEvents = Android_PumpEvents_NonBlocking; - } device->CreateSDLWindow = Android_CreateWindow; device->SetWindowTitle = Android_SetWindowTitle; @@ -174,7 +164,6 @@ int Android_VideoInit(SDL_VideoDevice *_this) videodata->isPaused = SDL_FALSE; videodata->isPausing = SDL_FALSE; - videodata->pauseAudio = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO, SDL_TRUE); SDL_zero(mode); mode.format = Android_ScreenFormat; diff --git a/src/video/android/SDL_androidvideo.h b/src/video/android/SDL_androidvideo.h index b7043ffa8..fa6bbc2fe 100644 --- a/src/video/android/SDL_androidvideo.h +++ b/src/video/android/SDL_androidvideo.h @@ -37,13 +37,10 @@ struct SDL_VideoData { int isPaused; int isPausing; - int pauseAudio; }; extern int Android_SurfaceWidth; extern int Android_SurfaceHeight; extern float Android_ScreenDensity; -extern SDL_Semaphore *Android_PauseSem, *Android_ResumeSem; -extern SDL_Mutex *Android_ActivityMutex; #endif /* SDL_androidvideo_h_ */ diff --git a/src/video/android/SDL_androidwindow.c b/src/video/android/SDL_androidwindow.c index cf43d3130..e27bf8c25 100644 --- a/src/video/android/SDL_androidwindow.c +++ b/src/video/android/SDL_androidwindow.c @@ -40,7 +40,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert SDL_WindowData *data; int retval = 0; - Android_ActivityMutex_Lock_Running(); + Android_LockActivityMutexOnceRunning(); if (Android_Window) { retval = SDL_SetError("Android only supports one window"); @@ -95,7 +95,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert endfunction: - SDL_UnlockMutex(Android_ActivityMutex); + Android_UnlockActivityMutex(); return retval; } @@ -107,7 +107,7 @@ void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen) { - SDL_LockMutex(Android_ActivityMutex); + Android_LockActivityMutex(); if (window == Android_Window) { SDL_WindowData *data; @@ -153,7 +153,7 @@ int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_ endfunction: - SDL_UnlockMutex(Android_ActivityMutex); + Android_UnlockActivityMutex(); return 0; } @@ -170,7 +170,7 @@ void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_ void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_LockMutex(Android_ActivityMutex); + Android_LockActivityMutex(); if (window == Android_Window) { Android_Window = NULL; @@ -192,7 +192,7 @@ void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) } } - SDL_UnlockMutex(Android_ActivityMutex); + Android_UnlockActivityMutex(); } #endif /* SDL_VIDEO_DRIVER_ANDROID */