SDL: gendynapi.py: add android native symbols to SDL_dynapi.sym

From 9421828e7ef45a6e87e9d30f0977e788f4569af3 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Wed, 21 Dec 2022 09:59:20 +0100
Subject: [PATCH] gendynapi.py: add android native symbols to SDL_dynapi.sym

---
 src/dynapi/SDL_dynapi.sym | 55 ++++++++++++++++++++++++
 src/dynapi/gendynapi.py   | 88 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index cffe4f2259f1..5ded7ee6ecfc 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -860,5 +860,60 @@ SDL3_0.0.0 {
     SDL_GetRenderDriver;
     SDL_RunApp;
     # extra symbols go here (don't modify this line)
+    # Android symbols start here (don't modify this line)
+    JNI_OnLoad;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceConnected;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceDisconnected;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceFeatureReport;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceInputReport;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceOpenPending;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceOpenResult;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceRegisterCallback;
+    Java_org_libsdl_app_HIDDeviceManager_HIDDeviceReleaseCallback;
+    Java_org_libsdl_app_SDLActivity_nativeAddTouch;
+    Java_org_libsdl_app_SDLActivity_nativeFocusChanged;
+    Java_org_libsdl_app_SDLActivity_nativeGetHint;
+    Java_org_libsdl_app_SDLActivity_nativeGetHintBoolean;
+    Java_org_libsdl_app_SDLActivity_nativeGetVersion;
+    Java_org_libsdl_app_SDLActivity_nativeLowMemory;
+    Java_org_libsdl_app_SDLActivity_nativePause;
+    Java_org_libsdl_app_SDLActivity_nativePermissionResult;
+    Java_org_libsdl_app_SDLActivity_nativeQuit;
+    Java_org_libsdl_app_SDLActivity_nativeResume;
+    Java_org_libsdl_app_SDLActivity_nativeRunMain;
+    Java_org_libsdl_app_SDLActivity_nativeSendQuit;
+    Java_org_libsdl_app_SDLActivity_nativeSetScreenResolution;
+    Java_org_libsdl_app_SDLActivity_nativeSetenv;
+    Java_org_libsdl_app_SDLActivity_nativeSetupJNI;
+    Java_org_libsdl_app_SDLActivity_onNativeAccel;
+    Java_org_libsdl_app_SDLActivity_onNativeClipboardChanged;
+    Java_org_libsdl_app_SDLActivity_onNativeDropFile;
+    Java_org_libsdl_app_SDLActivity_onNativeKeyDown;
+    Java_org_libsdl_app_SDLActivity_onNativeKeyUp;
+    Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost;
+    Java_org_libsdl_app_SDLActivity_onNativeLocaleChanged;
+    Java_org_libsdl_app_SDLActivity_onNativeMouse;
+    Java_org_libsdl_app_SDLActivity_onNativeOrientationChanged;
+    Java_org_libsdl_app_SDLActivity_onNativeResize;
+    Java_org_libsdl_app_SDLActivity_onNativeSoftReturnKey;
+    Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged;
+    Java_org_libsdl_app_SDLActivity_onNativeSurfaceCreated;
+    Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed;
+    Java_org_libsdl_app_SDLActivity_onNativeTouch;
+    Java_org_libsdl_app_SDLAudioManager_addAudioDevice;
+    Java_org_libsdl_app_SDLAudioManager_nativeSetupJNI;
+    Java_org_libsdl_app_SDLAudioManager_removeAudioDevice;
+    Java_org_libsdl_app_SDLControllerManager_nativeAddHaptic;
+    Java_org_libsdl_app_SDLControllerManager_nativeAddJoystick;
+    Java_org_libsdl_app_SDLControllerManager_nativeRemoveHaptic;
+    Java_org_libsdl_app_SDLControllerManager_nativeRemoveJoystick;
+    Java_org_libsdl_app_SDLControllerManager_nativeSetupJNI;
+    Java_org_libsdl_app_SDLControllerManager_onNativeHat;
+    Java_org_libsdl_app_SDLControllerManager_onNativeJoy;
+    Java_org_libsdl_app_SDLControllerManager_onNativePadDown;
+    Java_org_libsdl_app_SDLControllerManager_onNativePadUp;
+    Java_org_libsdl_app_SDLInputConnection_nativeCommitText;
+    Java_org_libsdl_app_SDLInputConnection_nativeGenerateScancodeForUnichar;
+    # Android symbols end here (don't modify this line)
   local: *;
 };
diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py
index 087b89c438d6..b99010897413 100755
--- a/src/dynapi/gendynapi.py
+++ b/src/dynapi/gendynapi.py
@@ -43,6 +43,8 @@
 SDL_DYNAPI_PROCS_H = SDL_ROOT / "src/dynapi/SDL_dynapi_procs.h"
 SDL_DYNAPI_OVERRIDES_H = SDL_ROOT / "src/dynapi/SDL_dynapi_overrides.h"
 SDL_DYNAPI_SYM = SDL_ROOT / "src/dynapi/SDL_dynapi.sym"
+SDL_ANDROID_C = SDL_ROOT / "src/core/android/SDL_android.c"
+SDL_ANDROID_HID_CPP = SDL_ROOT / "src/hidapi/android/hid.cpp"
 
 full_API = []
 
@@ -318,7 +320,10 @@ def main():
     # For-End parsing all files of sdl_list_includes
 
     # Dump API into a json file
-    full_API_json();
+    full_API_json()
+
+    # Add all native Android functions to SDL_dynapi.sym
+    write_android_symbols_to_sym()
 
 # Dump API into a json file
 def full_API_json():
@@ -454,6 +459,87 @@ def add_dyn_api(proc):
         f.write(line)
     f.close()
 
+
+def extract_symbols_sdl_android_c():
+    sdl_android_c_source = SDL_ANDROID_C.read_text()
+
+    prefix_match = re.search(r"#define SDL_JAVA_PREFIX\s+(?P<prefix>\S+)", sdl_android_c_source)
+    prefix = prefix_match["prefix"]
+
+    wrapper_names = []
+    wrappers = set()
+    for m in re.finditer(r"JNIEXPORT[\s]+(?P<ret>[a-z_]+)[\s]+JNICALL[\s]+(?P<wrapper>SDL_JAVA[A-Z_]+)\((?P<name>[a-zA-Z0-9_]+)\)", sdl_android_c_source, flags=re.M):
+        wrappers.add(m["wrapper"])
+        wrapper_names.append({"wrapper": m["wrapper"], "name": m["name"]})
+
+    wrapper2prefix = {}
+    for wrapper in wrappers:
+        s = re.search(r"#define\s+"+wrapper+r"\([a-z]+\)\s+CONCAT1\(SDL_JAVA_PREFIX,\s*(?P<prefix>[a-zA-Z0-9_]+),\s*function\)", sdl_android_c_source)
+        wrapper2prefix[wrapper] = s["prefix"]
+
+    symbols = set()
+    for wrapper_name in wrapper_names:
+        symbols.add("Java_" + prefix + "_" + wrapper2prefix[wrapper_name["wrapper"]] + "_" + wrapper_name["name"])
+
+    symbols.add("JNI_OnLoad")
+    symbols = list(symbols)
+
+    return symbols
+
+
+def extract_symbols_andoid_sdl_hid_cpp():
+    hid_cpp_source = SDL_ANDROID_HID_CPP.read_text()
+
+    prefix_match = re.search(r"#define SDL_JAVA_PREFIX\s+(?P<prefix>\S+)", hid_cpp_source)
+    prefix = prefix_match["prefix"]
+
+    wrapper_names = []
+    wrappers = set()
+    for m in re.finditer(r"JNIEXPORT[\s]+(?P<ret>[a-z_]+)[\s]+JNICALL[\s]+(?P<wrapper>HID_[A-Z_]+)\((?P<name>[a-zA-Z0-9_]+)\)", hid_cpp_source, flags=re.M):
+        wrappers.add(m["wrapper"])
+        wrapper_names.append({"wrapper": m["wrapper"], "name": m["name"]})
+
+    wrapper2prefix = {}
+    for wrapper in wrappers:
+        s = re.search(r"#define\s+"+wrapper+r"\([a-z]+\)\s+CONCAT1\(SDL_JAVA_PREFIX,\s*(?P<prefix>[a-zA-Z0-9_]+),\s*function\)", hid_cpp_source)
+        wrapper2prefix[wrapper] = s["prefix"]
+
+    symbols = set()
+    for wrapper_name in wrapper_names:
+        symbols.add("Java_" + prefix + "_" + wrapper2prefix[wrapper_name["wrapper"]] + "_" + wrapper_name["name"])
+
+    symbols = list(symbols)
+    symbols.sort()
+
+    return symbols
+
+
+def extract_android_symbols():
+    symbols = extract_symbols_sdl_android_c() + extract_symbols_andoid_sdl_hid_cpp()
+    symbols.sort()
+
+    return symbols
+
+
+def write_android_symbols_to_sym():
+    android_symbols = extract_android_symbols()
+    new_input = []
+    ignore_current = False
+    for line in SDL_DYNAPI_SYM.open():
+        if "Android symbols end here" in line:
+            ignore_current = False
+            for android_symbol in android_symbols:
+                new_input.append("    " + android_symbol + ";\n")
+        if ignore_current:
+            continue
+        if "Android symbols start here" in line:
+            ignore_current = True
+        new_input.append(line)
+    with SDL_DYNAPI_SYM.open("w") as f:
+        for line in new_input:
+            f.write(line)
+
+
 if __name__ == '__main__':
 
     parser = argparse.ArgumentParser()