From 0dec8feadb1c6ecca2de3764ccd413a8d950c573 Mon Sep 17 00:00:00 2001 From: weihuoya Date: Wed, 29 May 2019 20:22:26 +0800 Subject: [PATCH] android: thread local env --- Source/Android/jni/AndroidCommon/IDCache.cpp | 22 +++++++++- Source/Android/jni/AndroidCommon/IDCache.h | 2 +- Source/Android/jni/MainAndroid.cpp | 41 ++----------------- Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp | 17 ++------ .../ControllerInterface/Android/Android.cpp | 4 +- Source/Core/InputCommon/GCAdapter_Android.cpp | 17 ++------ 6 files changed, 33 insertions(+), 70 deletions(-) diff --git a/Source/Android/jni/AndroidCommon/IDCache.cpp b/Source/Android/jni/AndroidCommon/IDCache.cpp index 71e2ae9d59..19b7147ba4 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.cpp +++ b/Source/Android/jni/AndroidCommon/IDCache.cpp @@ -29,9 +29,27 @@ static jmethodID s_do_rumble; namespace IDCache { -JavaVM* GetJavaVM() +JNIEnv* GetEnvForThread() { - return s_java_vm; + thread_local static struct OwnedEnv + { + OwnedEnv() + { + status = s_java_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); + if (status == JNI_EDETACHED) + s_java_vm->AttachCurrentThread(&env, nullptr); + } + + ~OwnedEnv() + { + if (status == JNI_EDETACHED) + s_java_vm->DetachCurrentThread(); + } + + int status; + JNIEnv* env = nullptr; + } owned; + return owned.env; } jclass GetNativeLibraryClass() diff --git a/Source/Android/jni/AndroidCommon/IDCache.h b/Source/Android/jni/AndroidCommon/IDCache.h index 0e71a6ca7a..e3ef7259c1 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.h +++ b/Source/Android/jni/AndroidCommon/IDCache.h @@ -10,7 +10,7 @@ namespace IDCache { static constexpr jint JNI_VERSION = JNI_VERSION_1_6; -JavaVM* GetJavaVM(); +JNIEnv* GetEnvForThread(); jclass GetNativeLibraryClass(); jmethodID GetDisplayAlertMsg(); diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index ebb062ee8e..66331fd59c 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -75,17 +75,8 @@ bool s_have_wm_user_stop = false; void UpdatePointer() { // Update touch pointer - JNIEnv* env; - int get_env_status = - IDCache::GetJavaVM()->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); - - if (get_env_status == JNI_EDETACHED) - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); - + JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetUpdateTouchPointer()); - - if (get_env_status == JNI_EDETACHED) - IDCache::GetJavaVM()->DetachCurrentThread(); } void Host_NotifyMapLoaded() @@ -157,28 +148,19 @@ void Host_UpdateProgressDialog(const char* caption, int position, int total) static bool MsgAlert(const char* caption, const char* text, bool yes_no, MsgType /*style*/) { - __android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "%s:%s", caption, text); - - // Associate the current Thread with the Java VM. - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); + JNIEnv* env = IDCache::GetEnvForThread(); // Execute the Java method. jboolean result = env->CallStaticBooleanMethod( IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), ToJString(env, caption), ToJString(env, text), yes_no ? JNI_TRUE : JNI_FALSE); - // Must be called before the current thread exits; might as well do it here. - IDCache::GetJavaVM()->DetachCurrentThread(); - return result != JNI_FALSE; } static void ReportSend(std::string endpoint, std::string report) { - // Associate the current Thread with the Java VM. - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); + JNIEnv* env = IDCache::GetEnvForThread(); jbyteArray output_array = env->NewByteArray(report.size()); jbyte* output = env->GetByteArrayElements(output_array, nullptr); @@ -186,32 +168,17 @@ static void ReportSend(std::string endpoint, std::string report) env->ReleaseByteArrayElements(output_array, output, 0); env->CallStaticVoidMethod(IDCache::GetAnalyticsClass(), IDCache::GetSendAnalyticsReport(), ToJString(env, endpoint), output_array); - - IDCache::GetJavaVM()->DetachCurrentThread(); } static std::string GetAnalyticValue(std::string key) { - // Associate the current Thread with the Java VM. - JNIEnv* env; - bool attached = false; - int getEnvStat = - IDCache::GetJavaVM()->GetEnv(reinterpret_cast(&env), IDCache::JNI_VERSION); - if (getEnvStat == JNI_EDETACHED) - { - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); - attached = true; - } + JNIEnv* env = IDCache::GetEnvForThread(); jstring value = reinterpret_cast(env->CallStaticObjectMethod( IDCache::GetAnalyticsClass(), IDCache::GetAnalyticsValue(), ToJString(env, key))); std::string stdvalue = GetJString(env, value); - // Only detach the thread if it wasn't already attached - if (attached) - IDCache::GetJavaVM()->DetachCurrentThread(); - return stdvalue; } diff --git a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp index b7f2e92076..657b072a28 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp @@ -29,12 +29,7 @@ void WiimoteScannerAndroid::FindWiimotes(std::vector& found_wiimotes, NOTICE_LOG(WIIMOTE, "Finding Wiimotes"); - JNIEnv* env; - int get_env_status = - IDCache::GetJavaVM()->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); - - if (get_env_status == JNI_EDETACHED) - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); + JNIEnv* env = IDCache::GetEnvForThread(); jmethodID openadapter_func = env->GetStaticMethodID(s_adapter_class, "OpenAdapter", "()Z"); jmethodID queryadapter_func = env->GetStaticMethodID(s_adapter_class, "QueryAdapter", "()Z"); @@ -45,9 +40,6 @@ void WiimoteScannerAndroid::FindWiimotes(std::vector& found_wiimotes, for (int i = 0; i < MAX_WIIMOTES; ++i) found_wiimotes.emplace_back(new WiimoteAndroid(i)); } - - if (get_env_status == JNI_EDETACHED) - IDCache::GetJavaVM()->DetachCurrentThread(); } WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index) @@ -62,7 +54,7 @@ WiimoteAndroid::~WiimoteAndroid() // Connect to a Wiimote with a known address. bool WiimoteAndroid::ConnectInternal() { - IDCache::GetJavaVM()->AttachCurrentThread(&m_env, nullptr); + m_env = IDCache::GetEnvForThread(); jfieldID payload_field = m_env->GetStaticFieldID(s_adapter_class, "wiimote_payload", "[[B"); jobjectArray payload_object = @@ -81,7 +73,6 @@ bool WiimoteAndroid::ConnectInternal() void WiimoteAndroid::DisconnectInternal() { - IDCache::GetJavaVM()->DetachCurrentThread(); } bool WiimoteAndroid::IsConnected() const @@ -119,9 +110,7 @@ int WiimoteAndroid::IOWrite(u8 const* buf, size_t len) void InitAdapterClass() { - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); - + JNIEnv* env = IDCache::GetEnvForThread(); jclass adapter_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter"); s_adapter_class = reinterpret_cast(env->NewGlobalRef(adapter_class)); } diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 0ff62ab48d..9ab4cbf0f8 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -237,10 +237,8 @@ void Touchscreen::Motor::SetState(ControlState state) void Touchscreen::Motor::Rumble(int padID, double state) { - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr); + JNIEnv* env = IDCache::GetEnvForThread(); env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetDoRumble(), padID, state); - IDCache::GetJavaVM()->DetachCurrentThread(); } } // namespace Android } // namespace ciface diff --git a/Source/Core/InputCommon/GCAdapter_Android.cpp b/Source/Core/InputCommon/GCAdapter_Android.cpp index 9c6092dc78..1538f6749d 100644 --- a/Source/Core/InputCommon/GCAdapter_Android.cpp +++ b/Source/Core/InputCommon/GCAdapter_Android.cpp @@ -65,8 +65,7 @@ static void ScanThreadFunc() Common::SetCurrentThreadName("GC Adapter Scanning Thread"); NOTICE_LOG(SERIALINTERFACE, "GC Adapter scanning thread started"); - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, NULL); + JNIEnv* env = IDCache::GetEnvForThread(); jmethodID queryadapter_func = env->GetStaticMethodID(s_adapter_class, "QueryAdapter", "()Z"); @@ -77,7 +76,6 @@ static void ScanThreadFunc() Setup(); Common::SleepCurrentThread(1000); } - IDCache::GetJavaVM()->DetachCurrentThread(); NOTICE_LOG(SERIALINTERFACE, "GC Adapter scanning thread stopped"); } @@ -87,8 +85,7 @@ static void Write() Common::SetCurrentThreadName("GC Adapter Write Thread"); NOTICE_LOG(SERIALINTERFACE, "GC Adapter write thread started"); - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, NULL); + JNIEnv* env = IDCache::GetEnvForThread(); jmethodID output_func = env->GetStaticMethodID(s_adapter_class, "Output", "([B)I"); while (s_write_adapter_thread_running.IsSet()) @@ -118,8 +115,6 @@ static void Write() Common::YieldCPU(); } - IDCache::GetJavaVM()->DetachCurrentThread(); - NOTICE_LOG(SERIALINTERFACE, "GC Adapter write thread stopped"); } @@ -129,8 +124,7 @@ static void Read() NOTICE_LOG(SERIALINTERFACE, "GC Adapter read thread started"); bool first_read = true; - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, NULL); + JNIEnv* env = IDCache::GetEnvForThread(); jfieldID payload_field = env->GetStaticFieldID(s_adapter_class, "controller_payload", "[B"); jobject payload_object = env->GetStaticObjectField(s_adapter_class, payload_field); @@ -184,8 +178,6 @@ static void Read() s_fd = 0; s_detected = false; - IDCache::GetJavaVM()->DetachCurrentThread(); - NOTICE_LOG(SERIALINTERFACE, "GC Adapter read thread stopped"); } @@ -202,8 +194,7 @@ void Init() s_last_init = CoreTiming::GetTicks(); } - JNIEnv* env; - IDCache::GetJavaVM()->AttachCurrentThread(&env, NULL); + JNIEnv* env = IDCache::GetEnvForThread(); jclass adapter_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Java_GCAdapter"); s_adapter_class = reinterpret_cast(env->NewGlobalRef(adapter_class));