From 0aa256a26a072b7506be73b8f7cbe39fb4e154d5 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Tue, 11 Jan 2022 11:57:54 +0100 Subject: [PATCH] Move remaining stuff in Android.cpp --- src/openrct2/core/ZipAndroid.cpp | 3 +- src/openrct2/libopenrct2.vcxproj | 1 - src/openrct2/platform/Android.cpp | 77 ---------------------- src/openrct2/platform/Platform.Android.cpp | 61 +++++++++++++++++ src/openrct2/platform/Platform2.h | 16 +++++ src/openrct2/platform/Shared.cpp | 2 +- src/openrct2/platform/platform.h | 14 ---- 7 files changed, 80 insertions(+), 94 deletions(-) delete mode 100644 src/openrct2/platform/Android.cpp diff --git a/src/openrct2/core/ZipAndroid.cpp b/src/openrct2/core/ZipAndroid.cpp index c891b7023b..ae58016dad 100644 --- a/src/openrct2/core/ZipAndroid.cpp +++ b/src/openrct2/core/ZipAndroid.cpp @@ -9,6 +9,7 @@ #ifdef __ANDROID__ +# include "../platform/Platform2.h" # include "../platform/platform.h" # include "IStream.hpp" # include "MemoryStream.h" @@ -30,7 +31,7 @@ public: // retrieve the JNI environment. JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv(); - jclass jniClass = platform_android_find_class(env, "io/openrct2/ZipArchive"); + jclass jniClass = Platform::AndroidFindClass(env, "io/openrct2/ZipArchive"); jmethodID constructor = env->GetMethodID(jniClass, "", "(Ljava/lang/String;)V"); jstring jniPath = env->NewStringUTF(path.data()); diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 349015db7c..9888a01518 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -783,7 +783,6 @@ - diff --git a/src/openrct2/platform/Android.cpp b/src/openrct2/platform/Android.cpp deleted file mode 100644 index 8f537c7852..0000000000 --- a/src/openrct2/platform/Android.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#ifdef __ANDROID__ - -# include "../config/Config.h" -# include "../localisation/Language.h" -# include "../util/Util.h" -# include "platform.h" - -# include -# include -# include - -AndroidClassLoader::AndroidClassLoader() -{ - log_info("Obtaining JNI class loader"); - - // This is a workaround to be able to call JNI's ClassLoader from non-main - // thread, based on https://stackoverflow.com/a/16302771 - - // Apparently it's OK to use it from across different thread, but JNI - // only looks for ClassLoader in the _current_ thread and fails to find - // it when searched for from a native library's non-main thread. - - // The solution below works by obtaining a ClassLoader reference in main - // thread and caching it for future use from any thread, instead of using - // it via env->FindClass(). ClassLoader itself is abstract, so we cannot - // create it directly; instead we take an arbitrary class and call - // getClassLoader() on it to create a reference that way. - - // If we're here, SDL's JNI_OnLoad has already been called and set env - JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv(); - - // Take an arbitrary class. While the class does not really matter, it - // makes sense to use one that's most likely already loaded and is unlikely - // to be removed from code. - auto randomClass = env->FindClass("io/openrct2/MainActivity"); - jclass classClass = env->GetObjectClass(randomClass); - - // Get its class loader - auto classLoaderClass = env->FindClass("java/lang/ClassLoader"); - auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); - - // Store the class loader and its findClass method for future use - _classLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod)); - _findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); -} - -AndroidClassLoader::~AndroidClassLoader() -{ - JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv(); - env->DeleteGlobalRef(_classLoader); -} - -jobject AndroidClassLoader::_classLoader; -jmethodID AndroidClassLoader::_findClassMethod; - -static std::shared_ptr acl; - -void platform_android_init_class_loader() -{ - acl = std::make_shared(); -} - -jclass platform_android_find_class(JNIEnv* env, const char* name) -{ - return static_cast( - env->CallObjectMethod(AndroidClassLoader::_classLoader, AndroidClassLoader::_findClassMethod, env->NewStringUTF(name))); -} -#endif diff --git a/src/openrct2/platform/Platform.Android.cpp b/src/openrct2/platform/Platform.Android.cpp index 1ac745f6b6..9927056dcb 100644 --- a/src/openrct2/platform/Platform.Android.cpp +++ b/src/openrct2/platform/Platform.Android.cpp @@ -13,6 +13,20 @@ # include "../localisation/Language.h" # include "Platform2.h" +# include +# include + +AndroidClassLoader::~AndroidClassLoader() +{ + JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv(); + env->DeleteGlobalRef(_classLoader); +} + +jobject AndroidClassLoader::_classLoader; +jmethodID AndroidClassLoader::_findClassMethod; + +static std::shared_ptr acl; + namespace Platform { std::string GetFolderPath(SPECIAL_FOLDER folder) @@ -99,6 +113,53 @@ namespace Platform return displayScale; } + + void AndroidInitClassLoader() + { + acl = std::make_shared(); + } + + jclass AndroidFindClass(JNIEnv* env, std::string_view name) + { + return static_cast(env->CallObjectMethod( + AndroidClassLoader::_classLoader, AndroidClassLoader::_findClassMethod, + env->NewStringUTF(std::string(name).c_str()))); + } } // namespace Platform +AndroidClassLoader::AndroidClassLoader() +{ + log_info("Obtaining JNI class loader"); + + // This is a workaround to be able to call JNI's ClassLoader from non-main + // thread, based on https://stackoverflow.com/a/16302771 + + // Apparently it's OK to use it from across different thread, but JNI + // only looks for ClassLoader in the _current_ thread and fails to find + // it when searched for from a native library's non-main thread. + + // The solution below works by obtaining a ClassLoader reference in main + // thread and caching it for future use from any thread, instead of using + // it via env->FindClass(). ClassLoader itself is abstract, so we cannot + // create it directly; instead we take an arbitrary class and call + // getClassLoader() on it to create a reference that way. + + // If we're here, SDL's JNI_OnLoad has already been called and set env + JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv(); + + // Take an arbitrary class. While the class does not really matter, it + // makes sense to use one that's most likely already loaded and is unlikely + // to be removed from code. + auto randomClass = env->FindClass("io/openrct2/MainActivity"); + jclass classClass = env->GetObjectClass(randomClass); + + // Get its class loader + auto classLoaderClass = env->FindClass("java/lang/ClassLoader"); + auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); + + // Store the class loader and its findClass method for future use + _classLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod)); + _findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); +} + #endif diff --git a/src/openrct2/platform/Platform2.h b/src/openrct2/platform/Platform2.h index 6689c5cb48..7225215d36 100644 --- a/src/openrct2/platform/Platform2.h +++ b/src/openrct2/platform/Platform2.h @@ -80,6 +80,10 @@ namespace Platform const uint32_t iconIndex); void RemoveFileAssociations(); #endif +#ifdef __ANDROID__ + void AndroidInitClassLoader(); + jclass AndroidFindClass(JNIEnv* env, std::string_view name); +#endif bool IsRunningInWine(); bool IsColourTerminalSupported(); @@ -87,3 +91,15 @@ namespace Platform utf8* StrDecompToPrecomp(utf8* input); bool RequireNewWindow(bool openGL); } // namespace Platform + +#ifdef __ANDROID__ +class AndroidClassLoader +{ +public: + AndroidClassLoader(); + ~AndroidClassLoader(); + static jobject _classLoader; + static jmethodID _findClassMethod; +}; + +#endif // __ANDROID__ diff --git a/src/openrct2/platform/Shared.cpp b/src/openrct2/platform/Shared.cpp index 54c6258484..02c75c6313 100644 --- a/src/openrct2/platform/Shared.cpp +++ b/src/openrct2/platform/Shared.cpp @@ -223,7 +223,7 @@ void core_init() initialised = true; #ifdef __ANDROID__ - platform_android_init_class_loader(); + Platform::AndroidInitClassLoader(); #endif // __ANDROID__ platform_ticks_init(); diff --git a/src/openrct2/platform/platform.h b/src/openrct2/platform/platform.h index dcacbc052d..ace4b5e73e 100644 --- a/src/openrct2/platform/platform.h +++ b/src/openrct2/platform/platform.h @@ -124,17 +124,3 @@ bool platform_setup_uri_protocol(); // as it requires external linkage, which 'static' prevents __declspec(dllexport) int32_t StartOpenRCT2(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int32_t nCmdShow); #endif // _WIN32 - -#ifdef __ANDROID__ -class AndroidClassLoader -{ -public: - AndroidClassLoader(); - ~AndroidClassLoader(); - static jobject _classLoader; - static jmethodID _findClassMethod; -}; - -void platform_android_init_class_loader(); -jclass platform_android_find_class(JNIEnv* env, const char* name); -#endif // __ANDROID__