2
0
Эх сурвалжийг харах

Merge pull request #73257 from RedworkDE/net-android-support

C#: Support exporting for Android
Ignacio Roldán Etcheverry 2 жил өмнө
parent
commit
54ba3cf768

+ 0 - 2
modules/mono/SCsub

@@ -23,8 +23,6 @@ env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp")
 if env["platform"] in ["macos", "ios"]:
 if env["platform"] in ["macos", "ios"]:
     env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm")
     env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm")
     env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m")
     env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m")
-elif env["platform"] == "android":
-    env_mono.add_source_files(env.modules_sources, "mono_gd/android_mono_config.gen.cpp")
 
 
 if env.editor_build:
 if env.editor_build:
     env_mono.add_source_files(env.modules_sources, "editor/*.cpp")
     env_mono.add_source_files(env.modules_sources, "editor/*.cpp")

+ 1 - 1
modules/mono/config.py

@@ -1,6 +1,6 @@
 # Prior to .NET Core, we supported these: ["windows", "macos", "linuxbsd", "android", "haiku", "web", "ios"]
 # Prior to .NET Core, we supported these: ["windows", "macos", "linuxbsd", "android", "haiku", "web", "ios"]
 # Eventually support for each them should be added back (except Haiku if not supported by .NET Core)
 # Eventually support for each them should be added back (except Haiku if not supported by .NET Core)
-supported_platforms = ["windows", "macos", "linuxbsd"]
+supported_platforms = ["windows", "macos", "linuxbsd", "android"]
 
 
 
 
 def can_build(env, platform):
 def can_build(env, platform):

+ 55 - 9
modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs

@@ -3,6 +3,8 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
 using GodotTools.Build;
 using GodotTools.Build;
 using GodotTools.Core;
 using GodotTools.Core;
 using GodotTools.Internals;
 using GodotTools.Internals;
@@ -45,6 +47,17 @@ namespace GodotTools.Export
                         }
                         }
                     },
                     },
                     { "default_value", true }
                     { "default_value", true }
+                },
+                new Godot.Collections.Dictionary()
+                {
+                    {
+                        "option", new Godot.Collections.Dictionary()
+                        {
+                            { "name", "dotnet/embed_build_outputs" },
+                            { "type", (int)Variant.Type.Bool }
+                        }
+                    },
+                    { "default_value", false }
                 }
                 }
             };
             };
         }
         }
@@ -114,7 +127,7 @@ namespace GodotTools.Export
             if (!DeterminePlatformFromFeatures(features, out string platform))
             if (!DeterminePlatformFromFeatures(features, out string platform))
                 throw new NotSupportedException("Target platform not supported.");
                 throw new NotSupportedException("Target platform not supported.");
 
 
-            if (!new[] { OS.Platforms.Windows, OS.Platforms.LinuxBSD, OS.Platforms.MacOS }
+            if (!new[] { OS.Platforms.Windows, OS.Platforms.LinuxBSD, OS.Platforms.MacOS, OS.Platforms.Android }
                     .Contains(platform))
                     .Contains(platform))
             {
             {
                 throw new NotImplementedException("Target platform not yet implemented.");
                 throw new NotImplementedException("Target platform not yet implemented.");
@@ -129,15 +142,19 @@ namespace GodotTools.Export
             {
             {
                 archs.Add("x86_64");
                 archs.Add("x86_64");
             }
             }
-            else if (features.Contains("x86_32"))
+            if (features.Contains("x86_32"))
             {
             {
                 archs.Add("x86_32");
                 archs.Add("x86_32");
             }
             }
-            else if (features.Contains("arm64"))
+            if (features.Contains("arm64"))
             {
             {
                 archs.Add("arm64");
                 archs.Add("arm64");
             }
             }
-            else if (features.Contains("universal"))
+            if (features.Contains("arm32"))
+            {
+                archs.Add("arm32");
+            }
+            if (features.Contains("universal"))
             {
             {
                 if (platform == OS.Platforms.MacOS)
                 if (platform == OS.Platforms.MacOS)
                 {
                 {
@@ -146,6 +163,8 @@ namespace GodotTools.Export
                 }
                 }
             }
             }
 
 
+            bool embedBuildResults = (bool)GetOption("dotnet/embed_build_outputs") || features.Contains("android");
+
             foreach (var arch in archs)
             foreach (var arch in archs)
             {
             {
                 string ridOS = DetermineRuntimeIdentifierOS(platform);
                 string ridOS = DetermineRuntimeIdentifierOS(platform);
@@ -190,17 +209,44 @@ namespace GodotTools.Export
                         "Publish succeeded but project assembly not found in the output directory");
                         "Publish succeeded but project assembly not found in the output directory");
                 }
                 }
 
 
-                // Add to the exported project shared object list.
+                var manifest = new StringBuilder();
 
 
+                // Add to the exported project shared object list or packed resources.
                 foreach (string file in Directory.GetFiles(publishOutputTempDir, "*", SearchOption.AllDirectories))
                 foreach (string file in Directory.GetFiles(publishOutputTempDir, "*", SearchOption.AllDirectories))
                 {
                 {
-                    AddSharedObject(file, tags: null,
-                        Path.Join(projectDataDirName,
-                            Path.GetRelativePath(publishOutputTempDir, Path.GetDirectoryName(file))));
+                    if (embedBuildResults)
+                    {
+                        var filePath = SanitizeSlashes(Path.GetRelativePath(publishOutputTempDir, file));
+                        var fileData = File.ReadAllBytes(file);
+                        var hash = Convert.ToBase64String(SHA512.HashData(fileData));
+
+                        manifest.Append($"{filePath}\t{hash}\n");
+
+                        AddFile($"res://.godot/mono/publish/{arch}/{filePath}", fileData, false);
+                    }
+                    else
+                    {
+                        AddSharedObject(file, tags: null,
+                            Path.Join(projectDataDirName,
+                                Path.GetRelativePath(publishOutputTempDir, Path.GetDirectoryName(file))));
+                    }
+                }
+
+                if (embedBuildResults)
+                {
+                    var fileData = Encoding.Default.GetBytes(manifest.ToString());
+                    AddFile($"res://.godot/mono/publish/{arch}/.dotnet-publish-manifest", fileData, false);
                 }
                 }
             }
             }
         }
         }
 
 
+        private string SanitizeSlashes(string path)
+        {
+            if (Path.DirectorySeparatorChar == '\\')
+                return path.Replace('\\', '/');
+            return path;
+        }
+
         private string DetermineRuntimeIdentifierOS(string platform)
         private string DetermineRuntimeIdentifierOS(string platform)
             => OS.DotNetOSPlatformMap[platform];
             => OS.DotNetOSPlatformMap[platform];
 
 
@@ -214,7 +260,7 @@ namespace GodotTools.Export
                 "x86_64" => "x64",
                 "x86_64" => "x64",
                 "armeabi-v7a" => "arm",
                 "armeabi-v7a" => "arm",
                 "arm64-v8a" => "arm64",
                 "arm64-v8a" => "arm64",
-                "armv7" => "arm",
+                "arm32" => "arm",
                 "arm64" => "arm64",
                 "arm64" => "arm64",
                 _ => throw new ArgumentOutOfRangeException(nameof(arch), arch, "Unexpected architecture")
                 _ => throw new ArgumentOutOfRangeException(nameof(arch), arch, "Unexpected architecture")
             };
             };

+ 44 - 11
modules/mono/godotsharp_dirs.cpp

@@ -141,19 +141,52 @@ private:
 #else // TOOLS_ENABLED
 #else // TOOLS_ENABLED
 		String arch = Engine::get_singleton()->get_architecture_name();
 		String arch = Engine::get_singleton()->get_architecture_name();
 		String appname_safe = path::get_csharp_project_name();
 		String appname_safe = path::get_csharp_project_name();
-		String data_dir_root = exe_dir.path_join("data_" + appname_safe + "_" + arch);
-		if (!DirAccess::exists(data_dir_root)) {
-			data_dir_root = exe_dir.path_join("data_Godot_" + arch);
-		}
+		String packed_path = "res://.godot/mono/publish/" + arch;
+		if (DirAccess::exists(packed_path)) {
+			// The dotnet publish data is packed in the pck/zip.
+			String data_dir_root = OS::get_singleton()->get_cache_path().path_join("data_" + appname_safe + "_" + arch);
+			bool has_data = false;
+			if (!has_data) {
+				// 1. Try to access the data directly.
+				String global_packed = ProjectSettings::get_singleton()->globalize_path(packed_path);
+				if (global_packed.is_absolute_path() && FileAccess::exists(global_packed.path_join(".dotnet-publish-manifest"))) {
+					data_dir_root = global_packed;
+					has_data = true;
+				}
+			}
+			if (!has_data) {
+				// 2. Check if the data was extracted before and is up-to-date.
+				String packed_manifest = packed_path.path_join(".dotnet-publish-manifest");
+				String extracted_manifest = data_dir_root.path_join(".dotnet-publish-manifest");
+				if (FileAccess::exists(packed_manifest) && FileAccess::exists(extracted_manifest)) {
+					if (FileAccess::get_file_as_bytes(packed_manifest) == FileAccess::get_file_as_bytes(extracted_manifest)) {
+						has_data = true;
+					}
+				}
+			}
+			if (!has_data) {
+				// 3. Extract the data to a temporary location to load from there.
+				Ref<DirAccess> da = DirAccess::create_for_path(packed_path);
+				ERR_FAIL_NULL(da);
+				ERR_FAIL_COND(da->copy_dir(packed_path, data_dir_root) != OK);
+			}
+			api_assemblies_dir = data_dir_root;
+		} else {
+			// The dotnet publish data is in a directory next to the executable.
+			String data_dir_root = exe_dir.path_join("data_" + appname_safe + "_" + arch);
+			if (!DirAccess::exists(data_dir_root)) {
+				data_dir_root = exe_dir.path_join("data_Godot_" + arch);
+			}
 #ifdef MACOS_ENABLED
 #ifdef MACOS_ENABLED
-		if (!DirAccess::exists(data_dir_root)) {
-			data_dir_root = res_dir.path_join("data_" + appname_safe + "_" + arch);
-		}
-		if (!DirAccess::exists(data_dir_root)) {
-			data_dir_root = res_dir.path_join("data_Godot_" + arch);
-		}
+			if (!DirAccess::exists(data_dir_root)) {
+				data_dir_root = res_dir.path_join("data_" + appname_safe + "_" + arch);
+			}
+			if (!DirAccess::exists(data_dir_root)) {
+				data_dir_root = res_dir.path_join("data_Godot_" + arch);
+			}
 #endif
 #endif
-		api_assemblies_dir = data_dir_root;
+			api_assemblies_dir = data_dir_root;
+		}
 #endif
 #endif
 	}
 	}
 
 

+ 0 - 43
modules/mono/mono_gd/android_mono_config.h

@@ -1,43 +0,0 @@
-/**************************************************************************/
-/*  android_mono_config.h                                                 */
-/**************************************************************************/
-/*                         This file is part of:                          */
-/*                             GODOT ENGINE                               */
-/*                        https://godotengine.org                         */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
-/*                                                                        */
-/* Permission is hereby granted, free of charge, to any person obtaining  */
-/* a copy of this software and associated documentation files (the        */
-/* "Software"), to deal in the Software without restriction, including    */
-/* without limitation the rights to use, copy, modify, merge, publish,    */
-/* distribute, sublicense, and/or sell copies of the Software, and to     */
-/* permit persons to whom the Software is furnished to do so, subject to  */
-/* the following conditions:                                              */
-/*                                                                        */
-/* The above copyright notice and this permission notice shall be         */
-/* included in all copies or substantial portions of the Software.        */
-/*                                                                        */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
-/**************************************************************************/
-
-#ifndef ANDROID_MONO_CONFIG_H
-#define ANDROID_MONO_CONFIG_H
-
-#ifdef ANDROID_ENABLED
-
-#include "core/string/ustring.h"
-
-// This function is defined in an auto-generated source file
-String get_godot_android_mono_config();
-
-#endif // ANDROID_ENABLED
-
-#endif // ANDROID_MONO_CONFIG_H

+ 1 - 7
modules/mono/mono_gd/gd_mono.cpp

@@ -55,9 +55,7 @@
 
 
 // TODO mobile
 // TODO mobile
 #if 0
 #if 0
-#ifdef ANDROID_ENABLED
-#include "support/android_support.h"
-#elif defined(IOS_ENABLED)
+#ifdef IOS_ENABLED
 #include "support/ios_support.h"
 #include "support/ios_support.h"
 #endif
 #endif
 #endif
 #endif
@@ -554,10 +552,6 @@ GDMono::~GDMono() {
 	finalizing_scripts_domain = false;
 	finalizing_scripts_domain = false;
 	runtime_initialized = false;
 	runtime_initialized = false;
 
 
-#if defined(ANDROID_ENABLED)
-	gdmono::android::support::cleanup();
-#endif
-
 	singleton = nullptr;
 	singleton = nullptr;
 }
 }
 
 

+ 0 - 720
modules/mono/mono_gd/support/android_support.cpp

@@ -1,720 +0,0 @@
-/**************************************************************************/
-/*  android_support.cpp                                                   */
-/**************************************************************************/
-/*                         This file is part of:                          */
-/*                             GODOT ENGINE                               */
-/*                        https://godotengine.org                         */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
-/*                                                                        */
-/* Permission is hereby granted, free of charge, to any person obtaining  */
-/* a copy of this software and associated documentation files (the        */
-/* "Software"), to deal in the Software without restriction, including    */
-/* without limitation the rights to use, copy, modify, merge, publish,    */
-/* distribute, sublicense, and/or sell copies of the Software, and to     */
-/* permit persons to whom the Software is furnished to do so, subject to  */
-/* the following conditions:                                              */
-/*                                                                        */
-/* The above copyright notice and this permission notice shall be         */
-/* included in all copies or substantial portions of the Software.        */
-/*                                                                        */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
-/**************************************************************************/
-
-#include "android_support.h"
-
-#if defined(ANDROID_ENABLED)
-
-#include "../../utils/path_utils.h"
-#include "../../utils/string_utils.h"
-#include "../gd_mono_cache.h"
-#include "../gd_mono_marshal.h"
-
-#include "core/os/os.h"
-#include "core/string/ustring.h"
-
-#include "java_godot_wrapper.h"
-#include "os_android.h"
-#include "thread_jandroid.h"
-
-#include <mono/utils/mono-dl-fallback.h>
-
-#include <dlfcn.h> // dlopen, dlsym
-#include <sys/system_properties.h>
-#include <cstddef>
-
-#if __ANDROID_API__ < 24
-#include "thirdparty/misc/ifaddrs-android.h"
-#else
-#include <ifaddrs.h>
-#endif
-
-// Warning: JNI boilerplate ahead... continue at your own risk
-
-namespace gdmono {
-namespace android {
-namespace support {
-
-template <typename T>
-struct ScopedLocalRef {
-	JNIEnv *env;
-	T local_ref;
-
-	_FORCE_INLINE_ T get() const { return local_ref; }
-	_FORCE_INLINE_ operator T() const { return local_ref; }
-	_FORCE_INLINE_ operator jvalue() const { return (jvalue)local_ref; }
-
-	_FORCE_INLINE_ operator bool() const { return local_ref != nullptr; }
-
-	_FORCE_INLINE_ bool operator==(std::nullptr_t) const {
-		return local_ref == nullptr;
-	}
-
-	_FORCE_INLINE_ bool operator!=(std::nullptr_t) const {
-		return local_ref != nullptr;
-	}
-
-	ScopedLocalRef(const ScopedLocalRef &) = delete;
-	ScopedLocalRef &operator=(const ScopedLocalRef &) = delete;
-
-	ScopedLocalRef(JNIEnv *p_env, T p_local_ref) :
-			env(p_env),
-			local_ref(p_local_ref) {
-	}
-
-	~ScopedLocalRef() {
-		if (local_ref) {
-			env->DeleteLocalRef(local_ref);
-		}
-	}
-};
-
-bool jni_exception_check(JNIEnv *p_env) {
-	if (p_env->ExceptionCheck()) {
-		// Print the exception to logcat
-		p_env->ExceptionDescribe();
-
-		p_env->ExceptionClear();
-		return true;
-	}
-
-	return false;
-}
-
-String app_native_lib_dir_cache;
-
-String determine_app_native_lib_dir() {
-	JNIEnv *env = get_jni_env();
-
-	ScopedLocalRef<jclass> activityThreadClass(env, env->FindClass("android/app/ActivityThread"));
-	jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;");
-	ScopedLocalRef<jobject> activityThread(env, env->CallStaticObjectMethod(activityThreadClass, currentActivityThread));
-	jmethodID getApplication = env->GetMethodID(activityThreadClass, "getApplication", "()Landroid/app/Application;");
-	ScopedLocalRef<jobject> ctx(env, env->CallObjectMethod(activityThread, getApplication));
-
-	jmethodID getApplicationInfo = env->GetMethodID(env->GetObjectClass(ctx), "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
-	ScopedLocalRef<jobject> applicationInfo(env, env->CallObjectMethod(ctx, getApplicationInfo));
-	jfieldID nativeLibraryDirField = env->GetFieldID(env->GetObjectClass(applicationInfo), "nativeLibraryDir", "Ljava/lang/String;");
-	ScopedLocalRef<jstring> nativeLibraryDir(env, (jstring)env->GetObjectField(applicationInfo, nativeLibraryDirField));
-
-	String result;
-
-	const char *const nativeLibraryDirUtf8 = env->GetStringUTFChars(nativeLibraryDir, nullptr);
-	if (nativeLibraryDirUtf8) {
-		result.parse_utf8(nativeLibraryDirUtf8);
-		env->ReleaseStringUTFChars(nativeLibraryDir, nativeLibraryDirUtf8);
-	}
-
-	return result;
-}
-
-String get_app_native_lib_dir() {
-	if (app_native_lib_dir_cache.is_empty()) {
-		app_native_lib_dir_cache = determine_app_native_lib_dir();
-	}
-	return app_native_lib_dir_cache;
-}
-
-int gd_mono_convert_dl_flags(int flags) {
-	// from mono's runtime-bootstrap.c
-
-	int lflags = flags & MONO_DL_LOCAL ? 0 : RTLD_GLOBAL;
-
-	if (flags & MONO_DL_LAZY) {
-		lflags |= RTLD_LAZY;
-	} else {
-		lflags |= RTLD_NOW;
-	}
-
-	return lflags;
-}
-
-#ifndef GD_MONO_SO_NAME
-#define GD_MONO_SO_NAME "libmonosgen-2.0.so"
-#endif
-
-const char *mono_so_name = GD_MONO_SO_NAME;
-const char *godot_so_name = "libgodot_android.so";
-
-void *mono_dl_handle = nullptr;
-void *godot_dl_handle = nullptr;
-
-void *try_dlopen(const String &p_so_path, int p_flags) {
-	if (!FileAccess::exists(p_so_path)) {
-		if (OS::get_singleton()->is_stdout_verbose()) {
-			OS::get_singleton()->print("Cannot find shared library: '%s'\n", p_so_path.utf8().get_data());
-		}
-		return nullptr;
-	}
-
-	int lflags = gd_mono_convert_dl_flags(p_flags);
-
-	void *handle = dlopen(p_so_path.utf8().get_data(), lflags);
-
-	if (!handle) {
-		if (OS::get_singleton()->is_stdout_verbose()) {
-			OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", p_so_path.utf8().get_data(), dlerror());
-		}
-		return nullptr;
-	}
-
-	if (OS::get_singleton()->is_stdout_verbose()) {
-		OS::get_singleton()->print("Successfully loaded shared library: '%s'\n", p_so_path.utf8().get_data());
-	}
-
-	return handle;
-}
-
-void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void *p_user_data) {
-	if (p_name == nullptr) {
-		// __Internal
-
-		if (!mono_dl_handle) {
-			String app_native_lib_dir = get_app_native_lib_dir();
-			String so_path = path::join(app_native_lib_dir, mono_so_name);
-
-			mono_dl_handle = try_dlopen(so_path, p_flags);
-		}
-
-		return mono_dl_handle;
-	}
-
-	String name = String::utf8(p_name);
-
-	if (name.ends_with(".dll.so") || name.ends_with(".exe.so")) {
-		String app_native_lib_dir = get_app_native_lib_dir();
-
-		String orig_so_name = name.get_file();
-		String so_name = "lib-aot-" + orig_so_name;
-		String so_path = path::join(app_native_lib_dir, so_name);
-
-		return try_dlopen(so_path, p_flags);
-	}
-
-	return nullptr;
-}
-
-void *gd_mono_android_dlsym(void *p_handle, const char *p_name, char **r_err, void *p_user_data) {
-	void *sym_addr = dlsym(p_handle, p_name);
-
-	if (sym_addr) {
-		return sym_addr;
-	}
-
-	if (p_handle == mono_dl_handle && godot_dl_handle) {
-		// Looking up for '__Internal' P/Invoke. We want to search in both the Mono and Godot shared libraries.
-		// This is needed to resolve the monodroid P/Invoke functions that are defined at the bottom of the file.
-		sym_addr = dlsym(godot_dl_handle, p_name);
-
-		if (sym_addr) {
-			return sym_addr;
-		}
-	}
-
-	if (r_err) {
-		*r_err = str_format_new("%s\n", dlerror());
-	}
-
-	return nullptr;
-}
-
-void *gd_mono_android_dlclose(void *p_handle, void *p_user_data) {
-	dlclose(p_handle);
-
-	// Not sure if this ever happens. Does Mono close the handle for the main module?
-	if (p_handle == mono_dl_handle) {
-		mono_dl_handle = nullptr;
-	}
-
-	return nullptr;
-}
-
-int32_t build_version_sdk_int = 0;
-
-int32_t get_build_version_sdk_int() {
-	// The JNI code is the equivalent of:
-	//
-	// android.os.Build.VERSION.SDK_INT
-
-	if (build_version_sdk_int == 0) {
-		JNIEnv *env = get_jni_env();
-
-		jclass versionClass = env->FindClass("android/os/Build$VERSION");
-		ERR_FAIL_NULL_V(versionClass, 0);
-
-		jfieldID sdkIntField = env->GetStaticFieldID(versionClass, "SDK_INT", "I");
-		ERR_FAIL_NULL_V(sdkIntField, 0);
-
-		build_version_sdk_int = (int32_t)env->GetStaticIntField(versionClass, sdkIntField);
-	}
-
-	return build_version_sdk_int;
-}
-
-jobject certStore = nullptr; // KeyStore
-
-MonoBoolean _gd_mono_init_cert_store() {
-	// The JNI code is the equivalent of:
-	//
-	// try {
-	// 	certStoreLocal = KeyStore.getInstance("AndroidCAStore");
-	// 	certStoreLocal.load(null);
-	//	certStore = certStoreLocal;
-	//	return true;
-	// } catch (Exception e) {
-	//	return false;
-	// }
-
-	JNIEnv *env = get_jni_env();
-
-	ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore"));
-
-	jmethodID getInstance = env->GetStaticMethodID(keyStoreClass, "getInstance", "(Ljava/lang/String;)Ljava/security/KeyStore;");
-	jmethodID load = env->GetMethodID(keyStoreClass, "load", "(Ljava/security/KeyStore$LoadStoreParameter;)V");
-
-	ScopedLocalRef<jstring> androidCAStoreString(env, env->NewStringUTF("AndroidCAStore"));
-
-	ScopedLocalRef<jobject> certStoreLocal(env, env->CallStaticObjectMethod(keyStoreClass, getInstance, androidCAStoreString.get()));
-
-	if (jni_exception_check(env)) {
-		return 0;
-	}
-
-	env->CallVoidMethod(certStoreLocal, load, nullptr);
-
-	if (jni_exception_check(env)) {
-		return 0;
-	}
-
-	certStore = env->NewGlobalRef(certStoreLocal);
-
-	return 1;
-}
-
-MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) {
-	// The JNI code is the equivalent of:
-	//
-	// Certificate certificate = certStore.getCertificate(alias);
-	// if (certificate == null) {
-	//	return null;
-	// }
-	// return certificate.getEncoded();
-
-	MonoError mono_error;
-	char *alias_utf8 = mono_string_to_utf8_checked(p_alias, &mono_error);
-
-	if (!mono_error_ok(&mono_error)) {
-		ERR_PRINT(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&mono_error) + "'.");
-		mono_error_cleanup(&mono_error);
-		return nullptr;
-	}
-
-	JNIEnv *env = get_jni_env();
-
-	ScopedLocalRef<jstring> js_alias(env, env->NewStringUTF(alias_utf8));
-	mono_free(alias_utf8);
-
-	ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore"));
-	ERR_FAIL_NULL_V(keyStoreClass, nullptr);
-	ScopedLocalRef<jclass> certificateClass(env, env->FindClass("java/security/cert/Certificate"));
-	ERR_FAIL_NULL_V(certificateClass, nullptr);
-
-	jmethodID getCertificate = env->GetMethodID(keyStoreClass, "getCertificate", "(Ljava/lang/String;)Ljava/security/cert/Certificate;");
-	ERR_FAIL_NULL_V(getCertificate, nullptr);
-
-	jmethodID getEncoded = env->GetMethodID(certificateClass, "getEncoded", "()[B");
-	ERR_FAIL_NULL_V(getEncoded, nullptr);
-
-	ScopedLocalRef<jobject> certificate(env, env->CallObjectMethod(certStore, getCertificate, js_alias.get()));
-
-	if (!certificate) {
-		return nullptr;
-	}
-
-	ScopedLocalRef<jbyteArray> encoded(env, (jbyteArray)env->CallObjectMethod(certificate, getEncoded));
-	jsize encodedLength = env->GetArrayLength(encoded);
-
-	MonoArray *encoded_ret = mono_array_new(mono_domain_get(), mono_get_byte_class(), encodedLength);
-	uint8_t *dest = (uint8_t *)mono_array_addr(encoded_ret, uint8_t, 0);
-
-	env->GetByteArrayRegion(encoded, 0, encodedLength, reinterpret_cast<jbyte *>(dest));
-
-	return encoded_ret;
-}
-
-void register_internal_calls() {
-	GDMonoUtils::add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_init_cert_store", _gd_mono_init_cert_store);
-	GDMonoUtils::add_internal_call("Android.Runtime.AndroidEnvironment::_gd_mono_android_cert_store_lookup", _gd_mono_android_cert_store_lookup);
-}
-
-void initialize() {
-	// We need to set this environment variable to make the monodroid BCL use btls instead of legacy as the default provider
-	OS::get_singleton()->set_environment("XA_TLS_PROVIDER", "btls");
-
-	mono_dl_fallback_register(gd_mono_android_dlopen, gd_mono_android_dlsym, gd_mono_android_dlclose, nullptr);
-
-	String app_native_lib_dir = get_app_native_lib_dir();
-	String so_path = path::join(app_native_lib_dir, godot_so_name);
-
-	godot_dl_handle = try_dlopen(so_path, gd_mono_convert_dl_flags(MONO_DL_LAZY));
-}
-
-void cleanup() {
-	// This is called after shutting down the Mono runtime
-
-	if (mono_dl_handle) {
-		gd_mono_android_dlclose(mono_dl_handle, nullptr);
-	}
-
-	if (godot_dl_handle) {
-		gd_mono_android_dlclose(godot_dl_handle, nullptr);
-	}
-
-	JNIEnv *env = get_jni_env();
-
-	if (certStore) {
-		env->DeleteGlobalRef(certStore);
-		certStore = nullptr;
-	}
-}
-} // namespace support
-} // namespace android
-} // namespace gdmono
-
-using namespace gdmono::android::support;
-
-// The following are P/Invoke functions required by the monodroid profile of the BCL.
-// These are P/Invoke functions and not internal calls, hence why they use
-// 'mono_bool' and 'const char*' instead of 'MonoBoolean' and 'MonoString*'.
-
-#define GD_PINVOKE_EXPORT extern "C" __attribute__((visibility("default")))
-
-GD_PINVOKE_EXPORT int32_t _monodroid_get_android_api_level() {
-	return get_build_version_sdk_int();
-}
-
-GD_PINVOKE_EXPORT void monodroid_free(void *ptr) {
-	free(ptr);
-}
-
-GD_PINVOKE_EXPORT int32_t monodroid_get_system_property(const char *p_name, char **r_value) {
-	char prop_value_str[PROP_VALUE_MAX + 1] = { 0 };
-
-	int len = __system_property_get(p_name, prop_value_str);
-
-	if (r_value) {
-		if (len >= 0) {
-			*r_value = (char *)malloc(len + 1);
-			ERR_FAIL_NULL_V_MSG(*r_value, -1, "Out of memory.");
-			memcpy(*r_value, prop_value_str, len);
-			(*r_value)[len] = '\0';
-		} else {
-			*r_value = nullptr;
-		}
-	}
-
-	return len;
-}
-
-GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_up_state(const char *p_ifname, mono_bool *r_is_up) {
-	// The JNI code is the equivalent of:
-	//
-	// NetworkInterface.getByName(p_ifname).isUp()
-
-	if (!r_is_up || !p_ifname || strlen(p_ifname) == 0) {
-		return 0;
-	}
-
-	*r_is_up = 0;
-
-	JNIEnv *env = get_jni_env();
-
-	jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
-	ERR_FAIL_NULL_V(networkInterfaceClass, 0);
-
-	jmethodID getByName = env->GetStaticMethodID(networkInterfaceClass, "getByName", "(Ljava/lang/String;)Ljava/net/NetworkInterface;");
-	ERR_FAIL_NULL_V(getByName, 0);
-
-	jmethodID isUp = env->GetMethodID(networkInterfaceClass, "isUp", "()Z");
-	ERR_FAIL_NULL_V(isUp, 0);
-
-	ScopedLocalRef<jstring> js_ifname(env, env->NewStringUTF(p_ifname));
-	ScopedLocalRef<jobject> networkInterface(env, env->CallStaticObjectMethod(networkInterfaceClass, getByName, js_ifname.get()));
-
-	if (!networkInterface) {
-		return 0;
-	}
-
-	*r_is_up = (mono_bool)env->CallBooleanMethod(networkInterface, isUp);
-
-	return 1;
-}
-
-GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_supports_multicast(const char *p_ifname, mono_bool *r_supports_multicast) {
-	// The JNI code is the equivalent of:
-	//
-	// NetworkInterface.getByName(p_ifname).supportsMulticast()
-
-	if (!r_supports_multicast || !p_ifname || strlen(p_ifname) == 0) {
-		return 0;
-	}
-
-	*r_supports_multicast = 0;
-
-	JNIEnv *env = get_jni_env();
-
-	jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
-	ERR_FAIL_NULL_V(networkInterfaceClass, 0);
-
-	jmethodID getByName = env->GetStaticMethodID(networkInterfaceClass, "getByName", "(Ljava/lang/String;)Ljava/net/NetworkInterface;");
-	ERR_FAIL_NULL_V(getByName, 0);
-
-	jmethodID supportsMulticast = env->GetMethodID(networkInterfaceClass, "supportsMulticast", "()Z");
-	ERR_FAIL_NULL_V(supportsMulticast, 0);
-
-	ScopedLocalRef<jstring> js_ifname(env, env->NewStringUTF(p_ifname));
-	ScopedLocalRef<jobject> networkInterface(env, env->CallStaticObjectMethod(networkInterfaceClass, getByName, js_ifname.get()));
-
-	if (!networkInterface) {
-		return 0;
-	}
-
-	*r_supports_multicast = (mono_bool)env->CallBooleanMethod(networkInterface, supportsMulticast);
-
-	return 1;
-}
-
-static const int dns_servers_len = 8;
-
-static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dns_servers_count) {
-	// The JNI code is the equivalent of:
-	//
-	// ConnectivityManager connectivityManager = (ConnectivityManager)getApplicationContext()
-	// 		.getSystemService(Context.CONNECTIVITY_SERVICE);
-	// Network activeNerwork = connectivityManager.getActiveNetwork();
-	// LinkProperties linkProperties = connectivityManager.getLinkProperties(activeNerwork);
-	// List<String> dnsServers = linkProperties.getDnsServers().stream()
-	// 		.map(inetAddress -> inetAddress.getHostAddress()).collect(Collectors.toList());
-
-#ifdef DEBUG_ENABLED
-	CRASH_COND(get_build_version_sdk_int() < 23);
-#endif
-
-	JNIEnv *env = get_jni_env();
-
-	GodotJavaWrapper *godot_java = ((OS_Android *)OS::get_singleton())->get_godot_java();
-	jobject activity = godot_java->get_activity();
-
-	ScopedLocalRef<jclass> activityClass(env, env->GetObjectClass(activity));
-	ERR_FAIL_NULL(activityClass);
-
-	jmethodID getApplicationContext = env->GetMethodID(activityClass, "getApplicationContext", "()Landroid/content/Context;");
-
-	ScopedLocalRef<jobject> applicationContext(env, env->CallObjectMethod(activity, getApplicationContext));
-
-	ScopedLocalRef<jclass> contextClass(env, env->FindClass("android/content/Context"));
-	ERR_FAIL_NULL(contextClass);
-
-	jfieldID connectivityServiceField = env->GetStaticFieldID(contextClass, "CONNECTIVITY_SERVICE", "Ljava/lang/String;");
-	ScopedLocalRef<jstring> connectivityServiceString(env, (jstring)env->GetStaticObjectField(contextClass, connectivityServiceField));
-
-	jmethodID getSystemService = env->GetMethodID(contextClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
-
-	ScopedLocalRef<jobject> connectivityManager(env, env->CallObjectMethod(applicationContext, getSystemService, connectivityServiceString.get()));
-
-	if (!connectivityManager) {
-		return;
-	}
-
-	ScopedLocalRef<jclass> connectivityManagerClass(env, env->FindClass("android/net/ConnectivityManager"));
-	ERR_FAIL_NULL(connectivityManagerClass);
-
-	jmethodID getActiveNetwork = env->GetMethodID(connectivityManagerClass, "getActiveNetwork", "()Landroid/net/Network;");
-	ERR_FAIL_NULL(getActiveNetwork);
-
-	ScopedLocalRef<jobject> activeNetwork(env, env->CallObjectMethod(connectivityManager, getActiveNetwork));
-
-	if (!activeNetwork) {
-		return;
-	}
-
-	jmethodID getLinkProperties = env->GetMethodID(connectivityManagerClass,
-			"getLinkProperties", "(Landroid/net/Network;)Landroid/net/LinkProperties;");
-	ERR_FAIL_NULL(getLinkProperties);
-
-	ScopedLocalRef<jobject> linkProperties(env, env->CallObjectMethod(connectivityManager, getLinkProperties, activeNetwork.get()));
-
-	if (!linkProperties) {
-		return;
-	}
-
-	ScopedLocalRef<jclass> linkPropertiesClass(env, env->FindClass("android/net/LinkProperties"));
-	ERR_FAIL_NULL(linkPropertiesClass);
-
-	jmethodID getDnsServers = env->GetMethodID(linkPropertiesClass, "getDnsServers", "()Ljava/util/List;");
-	ERR_FAIL_NULL(getDnsServers);
-
-	ScopedLocalRef<jobject> dnsServers(env, env->CallObjectMethod(linkProperties, getDnsServers));
-
-	if (!dnsServers) {
-		return;
-	}
-
-	ScopedLocalRef<jclass> listClass(env, env->FindClass("java/util/List"));
-	ERR_FAIL_NULL(listClass);
-
-	jmethodID listSize = env->GetMethodID(listClass, "size", "()I");
-	ERR_FAIL_NULL(listSize);
-
-	int dnsServersCount = env->CallIntMethod(dnsServers, listSize);
-
-	if (dnsServersCount > dns_servers_len) {
-		dnsServersCount = dns_servers_len;
-	}
-
-	if (dnsServersCount <= 0) {
-		return;
-	}
-
-	jmethodID listGet = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
-	ERR_FAIL_NULL(listGet);
-
-	ScopedLocalRef<jclass> inetAddressClass(env, env->FindClass("java/net/InetAddress"));
-	ERR_FAIL_NULL(inetAddressClass);
-
-	jmethodID getHostAddress = env->GetMethodID(inetAddressClass, "getHostAddress", "()Ljava/lang/String;");
-	ERR_FAIL_NULL(getHostAddress);
-
-	for (int i = 0; i < dnsServersCount; i++) {
-		ScopedLocalRef<jobject> dnsServer(env, env->CallObjectMethod(dnsServers, listGet, (jint)i));
-		if (!dnsServer) {
-			continue;
-		}
-
-		ScopedLocalRef<jstring> hostAddress(env, (jstring)env->CallObjectMethod(dnsServer, getHostAddress));
-		const char *host_address = env->GetStringUTFChars(hostAddress, 0);
-
-		r_dns_servers[i] = strdup(host_address); // freed by the BCL
-		(*dns_servers_count)++;
-
-		env->ReleaseStringUTFChars(hostAddress, host_address);
-	}
-
-	// jesus...
-}
-
-GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array) {
-	if (!r_dns_servers_array) {
-		return -1;
-	}
-
-	*r_dns_servers_array = nullptr;
-
-	char *dns_servers[dns_servers_len];
-	int dns_servers_count = 0;
-
-	if (_monodroid_get_android_api_level() < 26) {
-		// The 'net.dns*' system properties are no longer available in Android 8.0 (API level 26) and greater:
-		// https://developer.android.com/about/versions/oreo/android-8.0-changes.html#o-pri
-
-		char prop_name[] = "net.dns*";
-
-		for (int i = 0; i < dns_servers_len; i++) {
-			prop_name[7] = (char)(i + 0x31);
-			char *prop_value;
-			int32_t len = monodroid_get_system_property(prop_name, &prop_value);
-
-			if (len > 0) {
-				dns_servers[dns_servers_count] = strndup(prop_value, (size_t)len); // freed by the BCL
-				dns_servers_count++;
-				free(prop_value);
-			}
-		}
-	} else {
-		// Alternative for Oreo and greater
-		interop_get_active_network_dns_servers(dns_servers, &dns_servers_count);
-	}
-
-	if (dns_servers_count > 0) {
-		size_t ret_size = sizeof(char *) * (size_t)dns_servers_count;
-		*r_dns_servers_array = malloc(ret_size); // freed by the BCL
-		ERR_FAIL_NULL_V_MSG(*r_dns_servers_array, -1, "Out of memory.");
-		memcpy(*r_dns_servers_array, dns_servers, ret_size);
-	}
-
-	return dns_servers_count;
-}
-
-GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() {
-	// The JNI code is the equivalent of:
-	//
-	// TimeZone.getDefault().getID()
-
-	JNIEnv *env = get_jni_env();
-
-	ScopedLocalRef<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone"));
-	ERR_FAIL_NULL_V(timeZoneClass, nullptr);
-
-	jmethodID getDefault = env->GetStaticMethodID(timeZoneClass, "getDefault", "()Ljava/util/TimeZone;");
-	ERR_FAIL_NULL_V(getDefault, nullptr);
-
-	jmethodID getID = env->GetMethodID(timeZoneClass, "getID", "()Ljava/lang/String;");
-	ERR_FAIL_NULL_V(getID, nullptr);
-
-	ScopedLocalRef<jobject> defaultTimeZone(env, env->CallStaticObjectMethod(timeZoneClass, getDefault));
-
-	if (!defaultTimeZone) {
-		return nullptr;
-	}
-
-	ScopedLocalRef<jstring> defaultTimeZoneID(env, (jstring)env->CallObjectMethod(defaultTimeZone, getID));
-
-	if (!defaultTimeZoneID) {
-		return nullptr;
-	}
-
-	const char *default_time_zone_id = env->GetStringUTFChars(defaultTimeZoneID, 0);
-
-	char *result = strdup(default_time_zone_id); // freed by the BCL
-
-	env->ReleaseStringUTFChars(defaultTimeZoneID, default_time_zone_id);
-
-	return result;
-}
-
-GD_PINVOKE_EXPORT int32_t _monodroid_getifaddrs(struct ifaddrs **p_ifap) {
-	return getifaddrs(p_ifap);
-}
-
-GD_PINVOKE_EXPORT void _monodroid_freeifaddrs(struct ifaddrs *p_ifap) {
-	freeifaddrs(p_ifap);
-}
-
-#endif

+ 0 - 54
modules/mono/mono_gd/support/android_support.h

@@ -1,54 +0,0 @@
-/**************************************************************************/
-/*  android_support.h                                                     */
-/**************************************************************************/
-/*                         This file is part of:                          */
-/*                             GODOT ENGINE                               */
-/*                        https://godotengine.org                         */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
-/*                                                                        */
-/* Permission is hereby granted, free of charge, to any person obtaining  */
-/* a copy of this software and associated documentation files (the        */
-/* "Software"), to deal in the Software without restriction, including    */
-/* without limitation the rights to use, copy, modify, merge, publish,    */
-/* distribute, sublicense, and/or sell copies of the Software, and to     */
-/* permit persons to whom the Software is furnished to do so, subject to  */
-/* the following conditions:                                              */
-/*                                                                        */
-/* The above copyright notice and this permission notice shall be         */
-/* included in all copies or substantial portions of the Software.        */
-/*                                                                        */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
-/**************************************************************************/
-
-#ifndef ANDROID_SUPPORT_H
-#define ANDROID_SUPPORT_H
-
-#if defined(ANDROID_ENABLED)
-
-#include "core/string/ustring.h"
-
-namespace gdmono {
-namespace android {
-namespace support {
-
-String get_app_native_lib_dir();
-
-void initialize();
-void cleanup();
-
-void register_internal_calls();
-} // namespace support
-} // namespace android
-} // namespace gdmono
-
-#endif // ANDROID_ENABLED
-
-#endif // ANDROID_SUPPORT_H