SDL: Added special handling for SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY

From 6bb16296b0bf7b5b004830d76f2e6f01b446a73f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 3 Apr 2025 10:35:50 -0700
Subject: [PATCH] Added special handling for
 SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY

This hint needs to persist outside of the normal application flow, so use the environment to set the initial value, and then save the value set via SDL_SetHint() after that.

Fixes https://github.com/libsdl-org/SDL/issues/12677
---
 src/SDL_hints.c                | 33 +++++++++++++++++++++++++++++++++
 src/core/android/SDL_android.c | 18 +++++++++++++++++-
 src/core/android/SDL_android.h |  2 ++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/src/SDL_hints.c b/src/SDL_hints.c
index 9c4ccd4bd94dc..a10598f0ffe69 100644
--- a/src/SDL_hints.c
+++ b/src/SDL_hints.c
@@ -22,6 +22,10 @@
 
 #include "SDL_hints_c.h"
 
+#ifdef SDL_PLATFORM_ANDROID
+#include "core/android/SDL_android.h"
+#endif
+
 typedef struct SDL_HintWatch
 {
     SDL_HintCallback callback;
@@ -147,6 +151,13 @@ bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriori
         }
     }
 
+#ifdef SDL_PLATFORM_ANDROID
+    if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
+        // Special handling for this hint, which needs to persist outside the normal application flow
+        Android_SetAllowRecreateActivity(SDL_GetStringBoolean(value, false));
+    }
+#endif // SDL_PLATFORM_ANDROID
+
     SDL_UnlockProperties(hints);
 
     return result;
@@ -185,6 +196,17 @@ bool SDL_ResetHint(const char *name)
         result = true;
     }
 
+#ifdef SDL_PLATFORM_ANDROID
+    if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
+        // Special handling for this hint, which needs to persist outside the normal application flow
+        if (env) {
+            Android_SetAllowRecreateActivity(SDL_GetStringBoolean(env, false));
+        } else {
+            Android_SetAllowRecreateActivity(false);
+        }
+    }
+#endif // SDL_PLATFORM_ANDROID
+
     SDL_UnlockProperties(hints);
 
     return result;
@@ -210,6 +232,17 @@ static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, c
     SDL_free(hint->value);
     hint->value = NULL;
     hint->priority = SDL_HINT_DEFAULT;
+
+#ifdef SDL_PLATFORM_ANDROID
+    if (SDL_strcmp(name, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
+        // Special handling for this hint, which needs to persist outside the normal application flow
+        if (env) {
+            Android_SetAllowRecreateActivity(SDL_GetStringBoolean(env, false));
+        } else {
+            Android_SetAllowRecreateActivity(false);
+        }
+    }
+#endif // SDL_PLATFORM_ANDROID
 }
 
 void SDL_ResetHints(void)
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 1fb6fbf65b0a5..7b666c5f5a22d 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -751,6 +751,8 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
 typedef int (*SDL_main_func)(int argc, char *argv[]);
 
 static int run_count = 0;
+static bool allow_recreate_activity;
+static bool allow_recreate_activity_set;
 
 JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
     JNIEnv *env, jclass jcls)
@@ -760,10 +762,16 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)(
     return tmp;
 }
 
+void Android_SetAllowRecreateActivity(bool enabled)
+{
+    allow_recreate_activity = enabled;
+    allow_recreate_activity_set = true;
+}
+
 JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)(
     JNIEnv *env, jclass jcls)
 {
-    return SDL_GetHintBoolean(SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY, false);
+    return allow_recreate_activity;
 }
 
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeInitMainThread)(
@@ -1526,6 +1534,14 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
     // Note that we call setenv() directly to avoid affecting SDL environments
     setenv(utfname, utfvalue, 1); // This should NOT be SDL_setenv()
 
+    if (SDL_strcmp(utfname, SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY) == 0) {
+        // Special handling for this hint, which needs to persist outside the normal application flow
+        // Only set this the first time we run, in case it's been set by the application via SDL_SetHint()
+        if (!allow_recreate_activity_set) {
+            Android_SetAllowRecreateActivity(SDL_GetStringBoolean(utfvalue, false));
+        }
+    }
+
     (*env)->ReleaseStringUTFChars(env, name, utfname);
     (*env)->ReleaseStringUTFChars(env, value, utfvalue);
 }
diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h
index 3541c2a9ccc92..620639ca961e5 100644
--- a/src/core/android/SDL_android.h
+++ b/src/core/android/SDL_android.h
@@ -55,6 +55,8 @@ bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeout
 void Android_LockActivityMutex(void);
 void Android_UnlockActivityMutex(void);
 
+void Android_SetAllowRecreateActivity(bool enabled);
+
 // Interface from the SDL library into the Android Java activity
 extern void Android_JNI_SetActivityTitle(const char *title);
 extern void Android_JNI_SetWindowStyle(bool fullscreen);