diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 05c0a15cd9..43b6fe38de 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -12,7 +12,6 @@ TARGET_PLATFORM := android-5 LOCAL_HEADER_FILES := \ com/mapswithme/core/jni_helper.hpp \ - com/mapswithme/core/jni_string.hpp \ com/mapswithme/core/logging.hpp \ com/mapswithme/core/render_context.hpp \ com/mapswithme/maps/Framework.hpp \ @@ -26,7 +25,6 @@ LOCAL_HEADER_FILES := \ LOCAL_SRC_FILES := \ com/mapswithme/core/jni_helper.cpp \ - com/mapswithme/core/jni_string.cpp \ com/mapswithme/core/logging.cpp \ com/mapswithme/core/render_context.cpp \ com/mapswithme/maps/DownloadUI.cpp \ @@ -38,8 +36,7 @@ LOCAL_SRC_FILES := \ com/mapswithme/platform/Platform.cpp \ com/mapswithme/platform/HttpThread.cpp \ com/mapswithme/platform/Language.cpp \ - com/mapswithme/jni/jni_thread.cpp \ - com/mapswithme/jni/jni_method.cpp \ + com/mapswithme/platform/PThreadImpl.cpp \ nv_thread/nv_thread.cpp \ nv_event/nv_event_queue.cpp \ nv_event/nv_event.cpp \ diff --git a/android/jni/com/mapswithme/core/jni_helper.cpp b/android/jni/com/mapswithme/core/jni_helper.cpp index 4911abe482..c0641c3bc2 100644 --- a/android/jni/com/mapswithme/core/jni_helper.cpp +++ b/android/jni/com/mapswithme/core/jni_helper.cpp @@ -1,21 +1,76 @@ #include "jni_helper.hpp" +#include "logging.hpp" #include "../../../../../base/assert.hpp" +static JavaVM * g_jvm = 0; -namespace jni { +// @TODO remove after refactoring. Needed for NVidia code +void InitNVEvent(JavaVM * jvm); - // Some examples of sig: - // "()V" - void function returning void; - // "(Ljava/lang/String;)V" - String function returning void; - jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, - char const * fn, char const * sig) +extern "C" +{ + + JNIEXPORT jint JNICALL + JNI_OnLoad(JavaVM * jvm, void *) { - ASSERT ( env != 0 && obj != 0, () ); + g_jvm = jvm; + jni::InitSystemLog(); + jni::InitAssertLog(); + // @TODO remove line below after refactoring + InitNVEvent(jvm); + return JNI_VERSION_1_6; + } + + JNIEXPORT void JNICALL + JNI_OnUnload(JavaVM *, void *) + { + g_jvm = 0; + } + +} // extern "C" + + +namespace jni +{ + jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig) + { + ASSERT(env, ("JNIEnv can't be 0")); + ASSERT(obj, ("jobject can't be 0")); jclass cls = env->GetObjectClass(obj); + ASSERT(cls, ("Can't get java class")); jmethodID mid = env->GetMethodID(cls, fn, sig); - ASSERT ( mid != 0, () ); + ASSERT(mid, ("Can't find java method", fn, sig)); return mid; } -} + string ToString(JNIEnv * env, jstring str) + { + string result; + char const * utfBuffer = env->GetStringUTFChars(str, 0); + if (utfBuffer) + { + result = utfBuffer; + env->ReleaseStringUTFChars(str, utfBuffer); + } + return result; + } + + JNIEnv * GetEnv() + { + JNIEnv * env; + if (JNI_OK != g_jvm->GetEnv((void **)&env, JNI_VERSION_1_6)) + { + ASSERT(false, ("Can't get JNIEnv. Was thread attached to JVM?")); + return 0; + } + return env; + } + + JavaVM * GetJVM() + { + ASSERT(g_jvm, ("JVM is not initialized")); + return g_jvm; + } + +} // namespace jni diff --git a/android/jni/com/mapswithme/core/jni_helper.hpp b/android/jni/com/mapswithme/core/jni_helper.hpp index bde60a7b8c..bbc7fbd40d 100644 --- a/android/jni/com/mapswithme/core/jni_helper.hpp +++ b/android/jni/com/mapswithme/core/jni_helper.hpp @@ -2,28 +2,15 @@ #include +#include "../../../../../std/string.hpp" + namespace jni { // Some examples of sig: // "()V" - void function returning void; // "(Ljava/lang/String;)V" - String function returning void; - - jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, - char const * fn, char const * sig); - /* Example of usage: - JNIEXPORT void JNICALL - Java_com_mapswithme_maps_MWMActivity_callbackFromJNI(JNIEnv * env, jobject thiz) - { - LOG("Enter callbackFromJNI"); - - env->CallVoidMethod(thiz, - jni::GetJavaMethodID(env, thiz, "callbackVoid", "()V")); - env->CallVoidMethod( - thiz, - jni::GetJavaMethodID(env, thiz, "callbackString", - "(Ljava/lang/String;)V"), env->NewStringUTF("Pass string from JNI.")); - - LOG("Leave callbackFromJNI"); - } - */ + jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig); + string ToString(JNIEnv * env, jstring str); + JNIEnv * GetEnv(); + JavaVM * GetJVM(); } diff --git a/android/jni/com/mapswithme/core/jni_string.cpp b/android/jni/com/mapswithme/core/jni_string.cpp deleted file mode 100644 index 63ff450001..0000000000 --- a/android/jni/com/mapswithme/core/jni_string.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "jni_string.hpp" - -#include "../../../../../base/string_utils.hpp" - - -namespace jni -{ - String::String(JNIEnv * env, jstring s) - : m_env(env), m_s(s) - { - m_ret = m_env->GetStringChars(m_s, NULL); - } - - String::~String() - { - m_env->ReleaseStringChars(m_s, m_ret); - } - - string String::ToString() const - { - size_t const sz = m_env->GetStringLength(m_s); - - string res; - utf8::unchecked::utf16to8(m_ret, m_ret + sz, back_inserter(res)); - - return res; - } - - string ToString(JNIEnv * env, jstring s) - { - return String(env, s).ToString(); - } -} diff --git a/android/jni/com/mapswithme/core/jni_string.hpp b/android/jni/com/mapswithme/core/jni_string.hpp deleted file mode 100644 index 2691a7fe21..0000000000 --- a/android/jni/com/mapswithme/core/jni_string.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -#include "../../../../../std/string.hpp" - -namespace jni -{ - class String - { - JNIEnv * m_env; - jstring m_s; - jchar const * m_ret; - public: - String(JNIEnv * env, jstring s); - ~String(); - - string ToString() const; - }; - - string ToString(JNIEnv * env, jstring s); -} diff --git a/android/jni/com/mapswithme/core/logging.cpp b/android/jni/com/mapswithme/core/logging.cpp index 087f467c04..f73dcf6dad 100644 --- a/android/jni/com/mapswithme/core/logging.cpp +++ b/android/jni/com/mapswithme/core/logging.cpp @@ -3,8 +3,10 @@ #include #include "../../../../../base/assert.hpp" +#include "../../../../../base/logging.hpp" -namespace jni { +namespace jni +{ using namespace my; diff --git a/android/jni/com/mapswithme/core/logging.hpp b/android/jni/com/mapswithme/core/logging.hpp index 1dd6df53b4..2d72b3509a 100644 --- a/android/jni/com/mapswithme/core/logging.hpp +++ b/android/jni/com/mapswithme/core/logging.hpp @@ -1,7 +1,5 @@ #pragma once -#include "../../../../../base/logging.hpp" - namespace jni { void InitSystemLog(); diff --git a/android/jni/com/mapswithme/jni/jni_method.cpp b/android/jni/com/mapswithme/jni/jni_method.cpp deleted file mode 100644 index ab294fdf02..0000000000 --- a/android/jni/com/mapswithme/jni/jni_method.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * method_ref.cpp - * - * Created on: Nov 27, 2011 - * Author: siarheirachytski - */ - -#include "jni_thread.hpp" -#include "jni_method.hpp" -#include "../../../../../base/assert.hpp" - -namespace jni -{ - Method::Method(jclass klass, - char const * name, - char const * signature) - : m_name(name), - m_signature(signature) - { - JNIEnv * env = GetCurrentThreadJNIEnv(); - m_index = env->GetMethodID(klass, m_name, m_signature); - CHECK(m_index, ("Error: No valid function pointer in ", m_name)); - } - - Method::Method(jobject obj, - char const * name, - char const * signature) - : m_name(name), - m_signature(signature) - { - jclass k = GetCurrentThreadJNIEnv()->GetObjectClass(obj); - GetCurrentThreadJNIEnv()->GetMethodID(k, m_name, m_signature); - CHECK(m_index, ("Error: No valid function pointer in ", m_name)); - } - - bool Method::CallBoolean(jobject self) - { - JNIEnv* jniEnv = GetCurrentThreadJNIEnv(); - - CHECK(jniEnv, ("Error: No valid JNI env in ", m_name)); - - return jniEnv->CallBooleanMethod(self, m_index); - } - - bool Method::CallInt(jobject self) - { - JNIEnv* jniEnv = GetCurrentThreadJNIEnv(); - - CHECK(jniEnv, ("Error: No valid JNI env in ", m_name)); - - return (int)jniEnv->CallIntMethod(self, m_index); - } - - jmethodID Method::GetMethodID() const - { - return m_index; - } -} diff --git a/android/jni/com/mapswithme/jni/jni_method.hpp b/android/jni/com/mapswithme/jni/jni_method.hpp deleted file mode 100644 index dfe2701c90..0000000000 --- a/android/jni/com/mapswithme/jni/jni_method.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * method_ref.hpp - * - * Created on: Nov 27, 2011 - * Author: siarheirachytski - */ - -#pragma once - -#include -#include "jni_thread.hpp" - -namespace jni -{ - class Method - { - private: - - const char* m_name; - const char* m_signature; - jmethodID m_index; - - public: - - Method(jclass klass, - char const * name, - char const * signature); - - Method(jobject obj, - char const * name, - char const * signature); - - void CallVoid(jobject self) - { - GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index); - }; - - template - void CallVoid(jobject self, A1 a1) - { - GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1); - } - - template - void CallVoid(jobject self, A1 a1, A2 a2) - { - GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2); - } - - template - void CallVoid(jobject self, A1 a1, A2 a2, A3 a3) - { - GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2, a3); - } - - template - void CallVoid(jobject self, A1 a1, A2 a2, A3 a3, A4 a4) - { - GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2, a3, a4); - } - - template - void CallVoid(jobject self, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) - { - GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2, a3, a4, a5); - } - - jmethodID GetMethodID() const; - - bool CallBoolean(jobject self); - bool CallInt(jobject self); - }; -} diff --git a/android/jni/com/mapswithme/jni/jni_thread.cpp b/android/jni/com/mapswithme/jni/jni_thread.cpp deleted file mode 100644 index 6e03df502f..0000000000 --- a/android/jni/com/mapswithme/jni/jni_thread.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * jni_thread.cpp - * - * Created on: Nov 27, 2011 - * Author: siarheirachytski - */ - -#include "jni_thread.hpp" -#include -#include "../../../../../base/logging.hpp" - -namespace jni -{ - JavaVM * s_jvm; - - void SetCurrentJVM(JavaVM * jvm) - { - s_jvm = jvm; - } - - JavaVM * GetCurrentJVM() - { - if (s_jvm == 0) - LOG(LINFO, ("no current JVM")); - return s_jvm; - } - - static pthread_key_t s_jniEnvKey = 0; - - JNIEnv* GetCurrentThreadJNIEnv() - { - JNIEnv* env = NULL; - if (s_jniEnvKey) - env = (JNIEnv*)pthread_getspecific(s_jniEnvKey); - else - pthread_key_create(&s_jniEnvKey, NULL); - - if (!env) - { - if (!GetCurrentJVM()) - { - LOG(LINFO, ("Error - could not find JVM!")); - return 0; - } - - // Hmm - no env for this thread cached yet - int error = GetCurrentJVM()->AttachCurrentThread(&env, 0); - - LOG(LINFO, ("AttachCurrentThread: ", error, ", ", env)); - if (error || !env) - { - LOG(LINFO, ("Error - could not attach thread to JVM!")); - return 0; - } - - pthread_setspecific(s_jniEnvKey, env); - } - - return env; - } - -} - - - diff --git a/android/jni/com/mapswithme/jni/jni_thread.hpp b/android/jni/com/mapswithme/jni/jni_thread.hpp deleted file mode 100644 index 853bf4883e..0000000000 --- a/android/jni/com/mapswithme/jni/jni_thread.hpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * jni_thread.hpp - * - * Created on: Nov 27, 2011 - * Author: siarheirachytski - */ - -#pragma once - -#include - -namespace jni -{ - void SetCurrentJVM(JavaVM * jvm); - JavaVM * GetCurrentJVM(); - - JNIEnv * GetCurrentThreadJNIEnv(); -} diff --git a/android/jni/com/mapswithme/maps/DownloadUI.cpp b/android/jni/com/mapswithme/maps/DownloadUI.cpp index 2f388f9419..bee70f2e11 100644 --- a/android/jni/com/mapswithme/maps/DownloadUI.cpp +++ b/android/jni/com/mapswithme/maps/DownloadUI.cpp @@ -1,7 +1,8 @@ -#include +#include "../core/jni_helper.hpp" + #include "Framework.hpp" #include "DownloadUI.hpp" -#include "../jni/jni_thread.hpp" + #include "../../../../../std/bind.hpp" android::DownloadUI * g_downloadUI = 0; @@ -10,12 +11,15 @@ namespace android { DownloadUI::DownloadUI(jobject self) { - m_self = jni::GetCurrentThreadJNIEnv()->NewGlobalRef(self); + JNIEnv * env = jni::GetEnv(); + m_self = env->NewGlobalRef(self); - jclass k = jni::GetCurrentThreadJNIEnv()->GetObjectClass(m_self); - - m_onChangeCountry.reset(new jni::Method(k, "onChangeCountry", "(III)V")); - m_onProgress.reset(new jni::Method(k, "onProgress", "(IIIJJ)V")); + jclass k = env->GetObjectClass(m_self); + ASSERT(k, ("Can't get java class")); + m_onChangeCountry = env->GetMethodID(k, "onChangeCountry", "(III)V"); + ASSERT(m_onChangeCountry, ("Can't get onChangeCountry methodID")); + m_onProgress = env->GetMethodID(k, "onProgress", "(IIIJJ)V"); + ASSERT(m_onProgress, ("Can't get onProgress methodID")); ASSERT(!g_downloadUI, ("DownloadUI is initialized twice")); g_downloadUI = this; @@ -23,18 +27,18 @@ namespace android DownloadUI::~DownloadUI() { - jni::GetCurrentThreadJNIEnv()->DeleteGlobalRef(m_self); g_downloadUI = 0; + jni::GetEnv()->DeleteGlobalRef(m_self); } void DownloadUI::OnChangeCountry(storage::TIndex const & idx) { - m_onChangeCountry->CallVoid(m_self, idx.m_group, idx.m_country, idx.m_region); + jni::GetEnv()->CallVoidMethod(m_self, m_onChangeCountry, idx.m_group, idx.m_country, idx.m_region); } void DownloadUI::OnProgress(storage::TIndex const & idx, pair const & p) { - m_onProgress->CallVoid(m_self, idx.m_group, idx.m_country, idx.m_region, p.first, p.second); + jni::GetEnv()->CallVoidMethod(m_self, m_onProgress, idx.m_group, idx.m_country, idx.m_region, p.first, p.second); } } diff --git a/android/jni/com/mapswithme/maps/DownloadUI.hpp b/android/jni/com/mapswithme/maps/DownloadUI.hpp index 2ba68ea730..e94ed43533 100644 --- a/android/jni/com/mapswithme/maps/DownloadUI.hpp +++ b/android/jni/com/mapswithme/maps/DownloadUI.hpp @@ -1,8 +1,8 @@ #pragma once -#include "../jni/jni_method.hpp" +#include + #include "../../../../../storage/storage.hpp" -#include "../../../../../std/scoped_ptr.hpp" namespace android { @@ -11,8 +11,8 @@ namespace android private: jobject m_self; - scoped_ptr m_onChangeCountry; - scoped_ptr m_onProgress; + jmethodID m_onChangeCountry; + jmethodID m_onProgress; public: diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 4a7f4bbd7a..7d7fa98bdd 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -2,9 +2,7 @@ #include "VideoTimer.hpp" #include "../core/jni_helper.hpp" -#include "../core/jni_string.hpp" #include "../core/render_context.hpp" -#include "../jni/jni_thread.hpp" #include "../../../../../indexer/drawing_rules.hpp" @@ -23,8 +21,6 @@ #include "../../../../../base/logging.hpp" #include "../../../../../base/math.hpp" -android::Framework * g_framework = 0; - namespace android { void Framework::CallRepaint() @@ -32,7 +28,7 @@ namespace android //LOG(LINFO, ("Calling Repaint")); } - Framework::Framework(JavaVM * jvm) + Framework::Framework() : m_work(), m_eventType(NVMultiTouchEventType(0)), m_hasFirst(false), @@ -44,15 +40,14 @@ namespace android ASSERT(g_framework == 0, ()); g_framework = this; - m_videoTimer = new VideoTimer(jvm, bind(&Framework::CallRepaint, this)); + m_videoTimer = new VideoTimer(bind(&Framework::CallRepaint, this)); // @TODO refactor storage m_work.Storage().ReInitCountries(false); } - void Framework::SetEmptyModelMessage(jstring s) + void Framework::SetEmptyModelMessage(string const & emptyModelMsg) { - std::string emptyModelMsg = jni::ToString(jni::GetCurrentThreadJNIEnv(), s); m_work.GetInformationDisplay().setEmptyModelMessage(emptyModelMsg.c_str()); } diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index 6bec88efb1..b86532f1a9 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -45,10 +45,10 @@ namespace android public: - Framework(JavaVM * jvm); + Framework(); ~Framework(); - void SetEmptyModelMessage(jstring emptyModelMsg); + void SetEmptyModelMessage(string const & emptyModelMsg); storage::Storage & Storage(); diff --git a/android/jni/com/mapswithme/maps/MWMActivity.cpp b/android/jni/com/mapswithme/maps/MWMActivity.cpp index 7a38b89e7c..7907449d96 100644 --- a/android/jni/com/mapswithme/maps/MWMActivity.cpp +++ b/android/jni/com/mapswithme/maps/MWMActivity.cpp @@ -1,41 +1,17 @@ -#include - -#include "../core/logging.hpp" - #include "Framework.hpp" -#include "../platform/Platform.hpp" -#include "../../../../../platform/settings.hpp" -#include "../../../nv_event/nv_event.hpp" -#include "../jni/jni_thread.hpp" -#include "../../../../../base/logging.hpp" -JavaVM * g_jvm; +#include "../core/jni_helper.hpp" + +#include "../platform/Platform.hpp" + +#include "../../../nv_event/nv_event.hpp" + +#include "../../../../../platform/settings.hpp" + +android::Framework * g_framework = 0; extern "C" { - JNIEXPORT jint JNICALL - JNI_OnLoad(JavaVM * jvm, void * reserved) - { - jni::InitSystemLog(); - jni::InitAssertLog(); - - LOG(LINFO, ("logging services initialized")); - - jni::SetCurrentJVM(jvm); - InitNVEvent(jvm); - g_jvm = jvm; - LOG(LDEBUG, ("JNI_OnLoad")); - return JNI_VERSION_1_6; - } - - JNIEXPORT void JNICALL - JNI_OnUnload(JavaVM * vm, void * reserved) - { - delete g_framework; - jni::SetCurrentJVM(0); - } - - JNIEXPORT void JNICALL Java_com_mapswithme_maps_MWMActivity_nativeInit(JNIEnv * env, jobject thiz, @@ -60,10 +36,11 @@ extern "C" settingsPath); if (!g_framework) - g_framework = new android::Framework(g_jvm); + g_framework = new android::Framework(); - g_framework->SetEmptyModelMessage(emptyModelMessage); + g_framework->SetEmptyModelMessage(jni::ToString(env, emptyModelMessage)); } + //////////////////////////////////////////////////////////////////////////////////////////// JNIEXPORT void JNICALL diff --git a/android/jni/com/mapswithme/maps/VideoTimer.cpp b/android/jni/com/mapswithme/maps/VideoTimer.cpp index ac94ffe119..761b03b155 100644 --- a/android/jni/com/mapswithme/maps/VideoTimer.cpp +++ b/android/jni/com/mapswithme/maps/VideoTimer.cpp @@ -1,10 +1,3 @@ -/* - * VideoTimer.cpp - * - * Created on: Nov 5, 2011 - * Author: siarheirachytski - */ - #include "../core/jni_helper.hpp" #include "VideoTimer.hpp" #include "../../../../../base/assert.hpp" @@ -14,8 +7,8 @@ android::VideoTimer * g_timer = 0; namespace android { - VideoTimer::VideoTimer(JavaVM * javaVM, TFrameFn frameFn) - : m_javaVM(javaVM), ::VideoTimer(frameFn) + VideoTimer::VideoTimer(TFrameFn frameFn) + : ::VideoTimer(frameFn) { ASSERT(g_timer == 0, ()); g_timer = this; diff --git a/android/jni/com/mapswithme/maps/VideoTimer.hpp b/android/jni/com/mapswithme/maps/VideoTimer.hpp index 56669eeb10..08fef273a5 100644 --- a/android/jni/com/mapswithme/maps/VideoTimer.hpp +++ b/android/jni/com/mapswithme/maps/VideoTimer.hpp @@ -15,13 +15,11 @@ namespace android class VideoTimer : public ::VideoTimer { private: - JavaVM * m_javaVM; - jobject m_videoTimer; public: - VideoTimer(JavaVM * jvm, TFrameFn frameFn); + VideoTimer(TFrameFn frameFn); ~VideoTimer(); void SetParentObject(jobject videoTimer); diff --git a/android/jni/com/mapswithme/platform/HttpThread.cpp b/android/jni/com/mapswithme/platform/HttpThread.cpp index f3a4387b27..136d33822f 100644 --- a/android/jni/com/mapswithme/platform/HttpThread.cpp +++ b/android/jni/com/mapswithme/platform/HttpThread.cpp @@ -1,5 +1,7 @@ #include "../../../../../platform/http_thread_callback.hpp" +#include "../core/jni_helper.hpp" + #include "../maps/DownloadUI.hpp" class HttpThread @@ -16,7 +18,7 @@ public: string const & pb) { /// should create java object here. - JNIEnv * env = jni::GetCurrentThreadJNIEnv(); + JNIEnv * env = jni::GetEnv(); jclass klass = env->FindClass("com/mapswithme/maps/downloader/DownloadChunkTask"); ASSERT(klass, ("Can't find java class com/mapswithme/maps/downloader/DownloadChunkTask")); @@ -35,11 +37,8 @@ public: ~HttpThread() { - JNIEnv * env = jni::GetCurrentThreadJNIEnv(); - jclass klass = env->FindClass("com/mapswithme/maps/downloader/DownloadChunkTask"); - ASSERT(klass, ("Can't find java class com/mapswithme/maps/downloader/DownloadChunkTask")); - - jmethodID methodId = env->GetMethodID(klass, "cancel", "(Z)Z"); + JNIEnv * env = jni::GetEnv(); + jmethodID methodId = jni::GetJavaMethodID(env, m_self, "cancel", "(Z)Z"); ASSERT(methodId, ("Can't find java method 'cancel' in com/mapswithme/maps/downloader/DownloadChunkTask")); env->CallBooleanMethod(m_self, methodId, false); @@ -73,10 +72,9 @@ extern "C" jlong httpCallbackID, jlong beg, jbyteArray data, jlong size) { downloader::IHttpThreadCallback * cb = reinterpret_cast(httpCallbackID); - JNIEnv * env0 = jni::GetCurrentThreadJNIEnv(); - jbyte * buf = env0->GetByteArrayElements(data, 0); + jbyte * buf = env->GetByteArrayElements(data, 0); cb->OnWrite(beg, buf, size); - env0->ReleaseByteArrayElements(data, buf, 0); + env->ReleaseByteArrayElements(data, buf, 0); } JNIEXPORT void JNICALL diff --git a/android/jni/com/mapswithme/platform/Language.cpp b/android/jni/com/mapswithme/platform/Language.cpp index 348f23d6a7..897e033b92 100644 --- a/android/jni/com/mapswithme/platform/Language.cpp +++ b/android/jni/com/mapswithme/platform/Language.cpp @@ -1,22 +1,19 @@ -#include +#include "../core/jni_helper.hpp" #include "../../../../../base/assert.hpp" #include "../../../../../base/logging.hpp" #include "../../../../../std/string.hpp" -/// Defined and initialized in MWMActivity.cpp -extern JavaVM * g_jvm; - #define DEFAULT_LANG "en" /// This function is called from native c++ code string GetAndroidSystemLanguage() { - JNIEnv * env = 0; - if (!g_jvm || g_jvm->AttachCurrentThread(&env, 0) || !env) + JNIEnv * env = jni::GetEnv(); + if (!env) { - LOG(LWARNING, ("Can't attach thread")); + LOG(LWARNING, ("Can't get JNIEnv")); return DEFAULT_LANG; } @@ -42,6 +39,6 @@ string GetAndroidSystemLanguage() result = langUtf8; env->ReleaseStringUTFChars(langString, langUtf8); } - g_jvm->DetachCurrentThread(); + return result; } diff --git a/android/jni/com/mapswithme/platform/PThreadImpl.cpp b/android/jni/com/mapswithme/platform/PThreadImpl.cpp new file mode 100644 index 0000000000..e068f9b2aa --- /dev/null +++ b/android/jni/com/mapswithme/platform/PThreadImpl.cpp @@ -0,0 +1,14 @@ +#include "../core/jni_helper.hpp" + +/// Implements bodies of base/thread.hpp functions for Android + +void AndroidThreadAttachToJVM() +{ + JNIEnv * env; + jni::GetJVM()->AttachCurrentThread(&env, 0); +} + +void AndroidThreadDetachFromJVM() +{ + jni::GetJVM()->DetachCurrentThread(); +} diff --git a/android/jni/com/mapswithme/platform/Platform.cpp b/android/jni/com/mapswithme/platform/Platform.cpp index 8c978c6f64..abec4e52d4 100644 --- a/android/jni/com/mapswithme/platform/Platform.cpp +++ b/android/jni/com/mapswithme/platform/Platform.cpp @@ -1,6 +1,6 @@ #include "Platform.hpp" -#include "../core/jni_string.hpp" +#include "../core/jni_helper.hpp" #include "../../../../../base/logging.hpp" diff --git a/android/jni/nv_thread/nv_thread.cpp b/android/jni/nv_thread/nv_thread.cpp index fbdb24c62e..6255fdf029 100644 --- a/android/jni/nv_thread/nv_thread.cpp +++ b/android/jni/nv_thread/nv_thread.cpp @@ -4,7 +4,7 @@ // Email: tegradev@nvidia.com // Web: http://developer.nvidia.com/category/zone/mobile-development // -// Copyright 2009-2011 NVIDIA® Corporation +// Copyright 2009-2011 NVIDIA� Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ static pthread_key_t s_jniEnvKey = 0; #define MODULE "NVThread" #include "../nv_debug/nv_debug.hpp" +#include "../com/mapswithme/core/jni_helper.hpp" void NVThreadInit(JavaVM* vm) { @@ -40,38 +41,40 @@ void NVThreadInit(JavaVM* vm) JNIEnv* NVThreadGetCurrentJNIEnv() { - JNIEnv* env = NULL; - if (s_jniEnvKey) - { - env = (JNIEnv*)pthread_getspecific(s_jniEnvKey); - } - else - { - pthread_key_create(&s_jniEnvKey, NULL); - } + return jni::GetEnv(); - if (!env) - { - // do we have a VM cached? - if (!s_vm) - { - __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error - could not find JVM!"); - return NULL; - } - - // Hmm - no env for this thread cached yet - int error = s_vm->AttachCurrentThread(&env, NULL); - __android_log_print(ANDROID_LOG_DEBUG, MODULE, "AttachCurrentThread: %d, 0x%p", error, env); - if (error || !env) - { - __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error - could not attach thread to JVM!"); - return NULL; - } - - pthread_setspecific(s_jniEnvKey, env); - } - - return env; +// JNIEnv* env = NULL; +// if (s_jniEnvKey) +// { +// env = (JNIEnv*)pthread_getspecific(s_jniEnvKey); +// } +// else +// { +// pthread_key_create(&s_jniEnvKey, NULL); +// } +// +// if (!env) +// { +// // do we have a VM cached? +// if (!s_vm) +// { +// __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error - could not find JVM!"); +// return NULL; +// } +// +// // Hmm - no env for this thread cached yet +// int error = s_vm->AttachCurrentThread(&env, NULL); +// __android_log_print(ANDROID_LOG_DEBUG, MODULE, "AttachCurrentThread: %d, 0x%p", error, env); +// if (error || !env) +// { +// __android_log_print(ANDROID_LOG_DEBUG, MODULE, "Error - could not attach thread to JVM!"); +// return NULL; +// } +// +// pthread_setspecific(s_jniEnvKey, env); +// } +// +// return env; } typedef struct NVThreadInitStruct @@ -80,6 +83,12 @@ typedef struct NVThreadInitStruct void *(*m_startRoutine)(void *); } NVThreadInitStruct; +// Implementations are in PThreadImpl.cpp +// They're used automatically if thread is created with base/thread.hpp +// @TODO: refactor and remove +void AndroidThreadAttachToJVM(); +void AndroidThreadDetachFromJVM(); + static void* NVThreadSpawnProc(void* arg) { NVThreadInitStruct* init = (NVThreadInitStruct*)arg; @@ -89,12 +98,11 @@ static void* NVThreadSpawnProc(void* arg) free(arg); - NVThreadGetCurrentJNIEnv(); + AndroidThreadAttachToJVM(); ret = start_routine(data); - if (s_vm) - s_vm->DetachCurrentThread(); + AndroidThreadDetachFromJVM(); return ret; } diff --git a/base/thread.cpp b/base/thread.cpp index 33f0bce5e1..afc8f8b022 100644 --- a/base/thread.cpp +++ b/base/thread.cpp @@ -7,6 +7,11 @@ #include "../std/windows.hpp" #else #include + #if defined (OMIM_OS_ANDROID) + /// External implementations are in android/jni code + void AndroidThreadAttachToJVM(); + void AndroidThreadDetachFromJVM(); + #endif #endif @@ -99,9 +104,19 @@ namespace threads static void * PthreadsWrapperThreadProc(void * p) { +#ifdef OMIM_OS_ANDROID + // Attach thread to JVM, implemented in android/jni code + AndroidThreadAttachToJVM(); +#endif + IRoutine * pRoutine = reinterpret_cast(p); pRoutine->Do(); +#ifdef OMIM_OS_ANDROID + // Detach thread from JVM, implemented in android/jni code + AndroidThreadDetachFromJVM(); +#endif + ::pthread_exit(NULL); return NULL; } @@ -156,7 +171,7 @@ namespace threads { if (m_routine) { - int error = m_impl->Join(); + int const error = m_impl->Join(); if (0 != error) { ASSERT ( !"Thread join failed. See error value.", (error) );