Browse Source

Merge pull request #92143 from m4gr3d/cleanup_android_plugin_on_exit

Add logic to unregister the Godot plugins on engine termination
Rémi Verschelde 1 year ago
parent
commit
eef7e29527

+ 1 - 0
platform/android/api/jni_singleton.h

@@ -244,6 +244,7 @@ public:
 
 	~JNISingleton() {
 #ifdef ANDROID_ENABLED
+		method_map.clear();
 		if (instance) {
 			JNIEnv *env = get_jni_env();
 			ERR_FAIL_NULL(env);

+ 10 - 12
platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java

@@ -112,19 +112,18 @@ public abstract class GodotPlugin {
 	/**
 	 * Register the plugin with Godot native code.
 	 * <p>
-	 * This method is invoked by the Godot Engine on the render thread.
+	 * This method is invoked on the render thread to register the plugin on engine startup.
 	 */
 	public final void onRegisterPluginWithGodotNative() {
-		registeredSignals.putAll(
-				registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals()));
-	}
+		final String pluginName = getPluginName();
+		if (!nativeRegisterSingleton(pluginName, this)) {
+			return;
+		}
 
-	private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
-			String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals) {
-		nativeRegisterSingleton(pluginName, pluginObject);
+		List<String> pluginMethods = getPluginMethods();
 
 		Set<Method> filteredMethods = new HashSet<>();
-		Class<?> clazz = pluginObject.getClass();
+		Class<?> clazz = getClass();
 
 		Method[] methods = clazz.getDeclaredMethods();
 		for (Method method : methods) {
@@ -156,15 +155,14 @@ public abstract class GodotPlugin {
 			nativeRegisterMethod(pluginName, method.getName(), method.getReturnType().getName(), pt);
 		}
 
+		Set<SignalInfo> pluginSignals = getPluginSignals();
+
 		// Register the signals for this plugin.
-		Map<String, SignalInfo> registeredSignals = new HashMap<>();
 		for (SignalInfo signalInfo : pluginSignals) {
 			String signalName = signalInfo.getName();
 			nativeRegisterSignal(pluginName, signalName, signalInfo.getParamTypesNames());
 			registeredSignals.put(signalName, signalInfo);
 		}
-
-		return registeredSignals;
 	}
 
 	/**
@@ -408,7 +406,7 @@ public abstract class GodotPlugin {
 	 * Used to setup a {@link GodotPlugin} instance.
 	 * @param p_name Name of the instance.
 	 */
-	private static native void nativeRegisterSingleton(String p_name, Object object);
+	private static native boolean nativeRegisterSingleton(String p_name, Object object);
 
 	/**
 	 * Used to complete registration of the {@link GodotPlugin} instance's methods.

+ 3 - 1
platform/android/java/nativeSrcsConfigs/CMakeLists.txt

@@ -7,6 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 
 set(GODOT_ROOT_DIR ../../../..)
+set(ANDROID_ROOT_DIR "${GODOT_ROOT_DIR}/platform/android" CACHE STRING "")
 
 # Get sources
 file(GLOB_RECURSE SOURCES ${GODOT_ROOT_DIR}/*.c**)
@@ -15,6 +16,7 @@ file(GLOB_RECURSE HEADERS ${GODOT_ROOT_DIR}/*.h**)
 add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
 target_include_directories(${PROJECT_NAME}
         SYSTEM PUBLIC
-        ${GODOT_ROOT_DIR})
+        ${GODOT_ROOT_DIR}
+        ${ANDROID_ROOT_DIR})
 
 add_definitions(-DUNIX_ENABLED -DVULKAN_ENABLED -DANDROID_ENABLED -DGLES3_ENABLED -DTOOLS_ENABLED)

+ 4 - 0
platform/android/java_godot_lib_jni.cpp

@@ -42,6 +42,7 @@
 #include "jni_utils.h"
 #include "net_socket_android.h"
 #include "os_android.h"
+#include "plugin/godot_plugin_jni.h"
 #include "string_android.h"
 #include "thread_jandroid.h"
 #include "tts_android.h"
@@ -78,6 +79,9 @@ static void _terminate(JNIEnv *env, bool p_restart = false) {
 	step.set(-1); // Ensure no further steps are attempted and no further events are sent
 
 	// lets cleanup
+	// Unregister android plugins
+	unregister_plugins_singletons();
+
 	if (java_class_wrapper) {
 		memdelete(java_class_wrapper);
 	}

+ 17 - 1
platform/android/plugin/godot_plugin_jni.cpp

@@ -40,16 +40,32 @@
 
 static HashMap<String, JNISingleton *> jni_singletons;
 
+void unregister_plugins_singletons() {
+	for (const KeyValue<String, JNISingleton *> &E : jni_singletons) {
+		Engine::get_singleton()->remove_singleton(E.key);
+		ProjectSettings::get_singleton()->set(E.key, Variant());
+
+		if (E.value) {
+			memdelete(E.value);
+		}
+	}
+	jni_singletons.clear();
+}
+
 extern "C" {
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj) {
+JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj) {
 	String singname = jstring_to_string(name, env);
+
+	ERR_FAIL_COND_V(jni_singletons.has(singname), false);
+
 	JNISingleton *s = (JNISingleton *)ClassDB::instantiate("JNISingleton");
 	s->set_instance(env->NewGlobalRef(obj));
 	jni_singletons[singname] = s;
 
 	Engine::get_singleton()->add_singleton(Engine::Singleton(singname, s));
 	ProjectSettings::get_singleton()->set(singname, s);
+	return true;
 }
 
 JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args) {

+ 3 - 1
platform/android/plugin/godot_plugin_jni.h

@@ -34,8 +34,10 @@
 #include <android/log.h>
 #include <jni.h>
 
+void unregister_plugins_singletons();
+
 extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj);
+JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params);