diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 9d50aaad2e..9e39f59de6 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -12,14 +12,16 @@ 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 \ - com/mapswithme/maps/VideoTimer.hpp \ com/mapswithme/platform/Platform.hpp \ + com/mapswithme/platform/http_thread_android.hpp \ 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 \ @@ -31,7 +33,8 @@ LOCAL_SRC_FILES := \ com/mapswithme/platform/Platform.cpp \ com/mapswithme/platform/HttpThread.cpp \ com/mapswithme/platform/Language.cpp \ - com/mapswithme/platform/PThreadImpl.cpp \ + com/mapswithme/jni/jni_thread.cpp \ + com/mapswithme/jni/jni_method.cpp \ LOCAL_LDLIBS := -llog -lGLESv1_CM \ -lmap -lversion -lsearch -lstorage -lindexer -lyg -lplatform \ diff --git a/android/jni/com/mapswithme/core/jni_helper.cpp b/android/jni/com/mapswithme/core/jni_helper.cpp index d708be180e..4911abe482 100644 --- a/android/jni/com/mapswithme/core/jni_helper.cpp +++ b/android/jni/com/mapswithme/core/jni_helper.cpp @@ -1,69 +1,21 @@ #include "jni_helper.hpp" -#include "logging.hpp" #include "../../../../../base/assert.hpp" -static JavaVM * g_jvm = 0; -extern "C" -{ +namespace jni { -JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM * jvm, void *) -{ - g_jvm = jvm; - jni::InitSystemLog(); - jni::InitAssertLog(); - return JNI_VERSION_1_6; -} - -JNIEXPORT void JNICALL -JNI_OnUnload(JavaVM *, void *) -{ - g_jvm = 0; -} - -} - -namespace jni -{ - jmethodID GetJavaMethodID(JNIEnv * env, jobject obj, char const * fn, char const * sig) + // 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) { - ASSERT(env, ("JNIEnv can't be 0")); - ASSERT(obj, ("jobject can't be 0")); + ASSERT ( env != 0 && obj != 0, () ); jclass cls = env->GetObjectClass(obj); - ASSERT(cls, ("Can't get java class")); jmethodID mid = env->GetMethodID(cls, fn, sig); - ASSERT(mid, ("Can't find java method", fn, sig)); + ASSERT ( mid != 0, () ); return mid; } - string GetString(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; - } } diff --git a/android/jni/com/mapswithme/core/jni_helper.hpp b/android/jni/com/mapswithme/core/jni_helper.hpp index b89a1594ff..bde60a7b8c 100644 --- a/android/jni/com/mapswithme/core/jni_helper.hpp +++ b/android/jni/com/mapswithme/core/jni_helper.hpp @@ -2,16 +2,28 @@ #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); - string GetString(JNIEnv * env, jstring str); - JNIEnv * GetEnv(); - JavaVM * GetJVM(); + 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"); + } + */ } diff --git a/android/jni/com/mapswithme/core/jni_string.cpp b/android/jni/com/mapswithme/core/jni_string.cpp new file mode 100644 index 0000000000..63ff450001 --- /dev/null +++ b/android/jni/com/mapswithme/core/jni_string.cpp @@ -0,0 +1,33 @@ +#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 new file mode 100644 index 0000000000..2691a7fe21 --- /dev/null +++ b/android/jni/com/mapswithme/core/jni_string.hpp @@ -0,0 +1,23 @@ +#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 89f751bf89..087f467c04 100644 --- a/android/jni/com/mapswithme/core/logging.cpp +++ b/android/jni/com/mapswithme/core/logging.cpp @@ -2,7 +2,6 @@ #include -#include "../../../../../base/logging.hpp" #include "../../../../../base/assert.hpp" namespace jni { diff --git a/android/jni/com/mapswithme/core/logging.hpp b/android/jni/com/mapswithme/core/logging.hpp index 2d72b3509a..1dd6df53b4 100644 --- a/android/jni/com/mapswithme/core/logging.hpp +++ b/android/jni/com/mapswithme/core/logging.hpp @@ -1,5 +1,7 @@ #pragma once +#include "../../../../../base/logging.hpp" + namespace jni { void InitSystemLog(); diff --git a/android/jni/com/mapswithme/core/render_context.cpp b/android/jni/com/mapswithme/core/render_context.cpp index a60fe32f73..901a58aa88 100644 --- a/android/jni/com/mapswithme/core/render_context.cpp +++ b/android/jni/com/mapswithme/core/render_context.cpp @@ -1,3 +1,10 @@ +/* + * render_context.cpp + * + * Created on: Oct 14, 2011 + * Author: siarheirachytski + */ + #include "render_context.hpp" namespace android diff --git a/android/jni/com/mapswithme/core/render_context.hpp b/android/jni/com/mapswithme/core/render_context.hpp index 14559b3df0..cf328ad4eb 100644 --- a/android/jni/com/mapswithme/core/render_context.hpp +++ b/android/jni/com/mapswithme/core/render_context.hpp @@ -1,7 +1,16 @@ +/* + * render_context.hpp + * + * Created on: Oct 14, 2011 + * Author: siarheirachytski + */ + #pragma once #include "../../../../../yg/rendercontext.hpp" +#include "../../../../../std/shared_ptr.hpp" + namespace android { class RenderContext : public yg::gl::RenderContext @@ -10,7 +19,9 @@ namespace android RenderContext(); virtual void makeCurrent(); + virtual shared_ptr createShared(); + virtual void endThreadDrawing(); }; } diff --git a/android/jni/com/mapswithme/jni/jni_method.cpp b/android/jni/com/mapswithme/jni/jni_method.cpp new file mode 100644 index 0000000000..ab294fdf02 --- /dev/null +++ b/android/jni/com/mapswithme/jni/jni_method.cpp @@ -0,0 +1,58 @@ +/* + * 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 new file mode 100644 index 0000000000..dfe2701c90 --- /dev/null +++ b/android/jni/com/mapswithme/jni/jni_method.hpp @@ -0,0 +1,73 @@ +/* + * 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 new file mode 100644 index 0000000000..6e03df502f --- /dev/null +++ b/android/jni/com/mapswithme/jni/jni_thread.cpp @@ -0,0 +1,65 @@ +/* + * 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 new file mode 100644 index 0000000000..853bf4883e --- /dev/null +++ b/android/jni/com/mapswithme/jni/jni_thread.hpp @@ -0,0 +1,18 @@ +/* + * 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 29e1b0c41b..2f388f9419 100644 --- a/android/jni/com/mapswithme/maps/DownloadUI.cpp +++ b/android/jni/com/mapswithme/maps/DownloadUI.cpp @@ -1,8 +1,7 @@ +#include #include "Framework.hpp" #include "DownloadUI.hpp" - -#include "../core/jni_helper.hpp" - +#include "../jni/jni_thread.hpp" #include "../../../../../std/bind.hpp" android::DownloadUI * g_downloadUI = 0; @@ -11,15 +10,12 @@ namespace android { DownloadUI::DownloadUI(jobject self) { - JNIEnv * env = jni::GetEnv(); - m_self = env->NewGlobalRef(self); + m_self = jni::GetCurrentThreadJNIEnv()->NewGlobalRef(self); - 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")); + 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")); ASSERT(!g_downloadUI, ("DownloadUI is initialized twice")); g_downloadUI = this; @@ -27,18 +23,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) { - jni::GetEnv()->CallVoidMethod(m_self, m_onChangeCountry, idx.m_group, idx.m_country, idx.m_region); + m_onChangeCountry->CallVoid(m_self, idx.m_group, idx.m_country, idx.m_region); } void DownloadUI::OnProgress(storage::TIndex const & idx, pair const & p) { - jni::GetEnv()->CallVoidMethod(m_self, m_onProgress, idx.m_group, idx.m_country, idx.m_region, p.first, p.second); + m_onProgress->CallVoid(m_self, idx.m_group, idx.m_country, idx.m_region, p.first, p.second); } } @@ -54,20 +50,20 @@ extern "C" if (g_downloadUI) { /// activity has been killed without onDestroy, destroying manually - android::GetFramework().Storage().Unsubscribe(); + g_framework->Storage().Unsubscribe(); delete g_downloadUI; g_downloadUI = 0; } g_downloadUI = new android::DownloadUI(thiz); - android::GetFramework().Storage().Subscribe(bind(&android::DownloadUI::OnChangeCountry, g_downloadUI, _1), + g_framework->Storage().Subscribe(bind(&android::DownloadUI::OnChangeCountry, g_downloadUI, _1), bind(&android::DownloadUI::OnProgress, g_downloadUI, _1, _2)); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_DownloadUI_nativeDestroy(JNIEnv * env, jobject thiz) { - android::GetFramework().Storage().Unsubscribe(); + g_framework->Storage().Unsubscribe(); delete g_downloadUI; g_downloadUI = 0; } @@ -76,14 +72,14 @@ extern "C" Java_com_mapswithme_maps_DownloadUI_countriesCount(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - return static_cast(android::GetFramework().Storage().CountriesCount(storage::TIndex(group, country, region))); + return static_cast(g_framework->Storage().CountriesCount(storage::TIndex(group, country, region))); } JNIEXPORT jstring JNICALL Java_com_mapswithme_maps_DownloadUI_countryName(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - string const name = android::GetFramework().Storage().CountryName(storage::TIndex(group, country, region)); + string const name = g_framework->Storage().CountryName(storage::TIndex(group, country, region)); return env->NewStringUTF(name.c_str()); } @@ -91,35 +87,35 @@ extern "C" Java_com_mapswithme_maps_DownloadUI_countryLocalSizeInBytes(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - return android::GetFramework().Storage().CountrySizeInBytes(storage::TIndex(group, country, region)).first; + return g_framework->Storage().CountrySizeInBytes(storage::TIndex(group, country, region)).first; } JNIEXPORT jlong JNICALL Java_com_mapswithme_maps_DownloadUI_countryRemoteSizeInBytes(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - return android::GetFramework().Storage().CountrySizeInBytes(storage::TIndex(group, country, region)).second; + return g_framework->Storage().CountrySizeInBytes(storage::TIndex(group, country, region)).second; } JNIEXPORT jint JNICALL Java_com_mapswithme_maps_DownloadUI_countryStatus(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - return static_cast(android::GetFramework().Storage().CountryStatus(storage::TIndex(group, country, region))); + return static_cast(g_framework->Storage().CountryStatus(storage::TIndex(group, country, region))); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_DownloadUI_downloadCountry(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - android::GetFramework().Storage().DownloadCountry(storage::TIndex(group, country, region)); + g_framework->Storage().DownloadCountry(storage::TIndex(group, country, region)); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_DownloadUI_deleteCountry(JNIEnv * env, jobject thiz, jint group, jint country, jint region) { - android::GetFramework().Storage().DeleteCountry(storage::TIndex(group, country, region)); + g_framework->Storage().DeleteCountry(storage::TIndex(group, country, region)); } } diff --git a/android/jni/com/mapswithme/maps/DownloadUI.hpp b/android/jni/com/mapswithme/maps/DownloadUI.hpp index ed4e67c953..2ba68ea730 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 "../../../../../storage/storage.hpp" - -#include +#include "../../../../../std/scoped_ptr.hpp" namespace android { @@ -11,8 +11,8 @@ namespace android private: jobject m_self; - jmethodID m_onChangeCountry; - jmethodID m_onProgress; + scoped_ptr m_onChangeCountry; + scoped_ptr m_onProgress; public: diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 56dfd82a21..512f54e1ab 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -21,159 +21,169 @@ #include "../../../../../base/logging.hpp" #include "../../../../../base/math.hpp" -extern android::Framework * g_framework; +android::Framework * g_framework = 0; namespace android { - -Framework & GetFramework() -{ - ASSERT(g_framework, ("Framework is not initialized")); - return *g_framework; -} - -Framework::Framework() -{ - // @TODO refactor storage - m_work.Storage().ReInitCountries(false); -} - -Framework::~Framework() -{ -} - -void Framework::OnLocationStatusChanged(int newStatus) -{ - m_work.OnLocationStatusChanged(static_cast(newStatus)); -} - -void Framework::OnLocationUpdated(uint64_t time, double lat, double lon, float accuracy) -{ - location::GpsInfo info; - info.m_timestamp = static_cast(time); - info.m_latitude = lat; - info.m_longitude = lon; - info.m_horizontalAccuracy = accuracy; - m_work.OnGpsUpdate(info); -} - -void Framework::OnCompassUpdated(uint64_t timestamp, double magneticNorth, double trueNorth, float accuracy) -{ - location::CompassInfo info; - info.m_timestamp = static_cast(timestamp); - info.m_magneticHeading = magneticNorth; - info.m_trueHeading = trueNorth; - info.m_accuracy = accuracy; - m_work.OnCompassUpdate(info); -} - -void Framework::DeleteRenderPolicy() -{ - m_work.SaveState(); - LOG(LDEBUG, ("clearing current render policy.")); - m_work.SetRenderPolicy(0); -} - -bool Framework::InitRenderPolicy() -{ - LOG(LDEBUG, ("AF::InitRenderer 1")); - - yg::ResourceManager::Params rmParams; - rmParams.m_videoMemoryLimit = 10 * 1024 * 1024; - rmParams.m_rtFormat = yg::Data4Bpp; - rmParams.m_texFormat = yg::Data4Bpp; - - try + void Framework::CallRepaint() { - m_work.SetRenderPolicy(CreateRenderPolicy(&m_videoTimer, - true, - rmParams, - make_shared_ptr(new android::RenderContext()))); - m_work.LoadState(); - } - catch (yg::gl::platform_unsupported const & e) - { - LOG(LINFO, ("this android platform is unsupported, reason=", e.what())); - return false; + //LOG(LINFO, ("Calling Repaint")); } - m_work.SetUpdatesEnabled(true); - - LOG(LDEBUG, ("AF::InitRenderer 3")); - - return true; -} - -storage::Storage & Framework::Storage() -{ - return m_work.Storage(); -} - -void Framework::Resize(int w, int h) -{ - m_work.OnSize(w, h); -} - -void Framework::DrawFrame() -{ - if (m_work.NeedRedraw()) + Framework::Framework(JavaVM * jvm) + : m_work(), + m_hasFirst(false), + m_hasSecond(false), + m_mask(0) { - m_work.SetNeedRedraw(false); + ASSERT(g_framework == 0, ()); + g_framework = this; - shared_ptr paintEvent(new PaintEvent(m_work.GetRenderPolicy()->GetDrawer().get())); + m_videoTimer = new VideoTimer(jvm, bind(&Framework::CallRepaint, this)); - m_work.BeginPaint(paintEvent); - m_work.DoPaint(paintEvent); - m_work.EndPaint(paintEvent); + // @TODO refactor storage + m_work.Storage().ReInitCountries(false); + } + + Framework::~Framework() + { + delete m_videoTimer; + } + + void Framework::OnLocationStatusChanged(int newStatus) + { + m_work.OnLocationStatusChanged(static_cast(newStatus)); + } + + void Framework::OnLocationUpdated(uint64_t time, double lat, double lon, float accuracy) + { + location::GpsInfo info; + info.m_timestamp = static_cast(time); + info.m_latitude = lat; + info.m_longitude = lon; + info.m_horizontalAccuracy = accuracy; + m_work.OnGpsUpdate(info); + } + + void Framework::OnCompassUpdated(uint64_t timestamp, double magneticNorth, double trueNorth, float accuracy) + { + location::CompassInfo info; + info.m_timestamp = static_cast(timestamp); + info.m_magneticHeading = magneticNorth; + info.m_trueHeading = trueNorth; + info.m_accuracy = accuracy; + m_work.OnCompassUpdate(info); + } + + void Framework::DeleteRenderPolicy() + { + m_work.SaveState(); + LOG(LDEBUG, ("clearing current render policy.")); + m_work.SetRenderPolicy(0); + } + + bool Framework::InitRenderPolicy() + { + LOG(LDEBUG, ("AF::InitRenderer 1")); + + yg::ResourceManager::Params rmParams; + rmParams.m_videoMemoryLimit = 10 * 1024 * 1024; + rmParams.m_rtFormat = yg::Data4Bpp; + rmParams.m_texFormat = yg::Data4Bpp; + + try + { + m_work.SetRenderPolicy(CreateRenderPolicy(m_videoTimer, + true, + rmParams, + make_shared_ptr(new android::RenderContext()))); + m_work.LoadState(); + } + catch (yg::gl::platform_unsupported const & e) + { + LOG(LINFO, ("this android platform is unsupported, reason=", e.what())); + return false; + } + + m_work.SetUpdatesEnabled(true); + + LOG(LDEBUG, ("AF::InitRenderer 3")); + + return true; + } + + storage::Storage & Framework::Storage() + { + return m_work.Storage(); + } + + void Framework::Resize(int w, int h) + { + m_work.OnSize(w, h); + } + + void Framework::DrawFrame() + { + if (m_work.NeedRedraw()) + { + m_work.SetNeedRedraw(false); + + shared_ptr paintEvent(new PaintEvent(m_work.GetRenderPolicy()->GetDrawer().get())); + + m_work.BeginPaint(paintEvent); + m_work.DoPaint(paintEvent); + +// NVEventSwapBuffersEGL(); + + m_work.EndPaint(paintEvent); + } + } + + void Framework::Move(int mode, double x, double y) + { + DragEvent const e(x, y); + switch (mode) + { + case 0: m_work.StartDrag(e); break; + case 1: m_work.DoDrag(e); break; + case 2: m_work.StopDrag(e); break; + } + } + + void Framework::Zoom(int mode, double x1, double y1, double x2, double y2) + { + ScaleEvent const e(x1, y1, x2, y2); + switch (mode) + { + case 0: m_work.StartScale(e); break; + case 1: m_work.DoScale(e); break; + case 2: m_work.StopScale(e); break; + } + } + + void Framework::LoadState() + { + if (!m_work.LoadState()) + { + LOG(LDEBUG, ("no saved state, showing all world")); + m_work.ShowAll(); + } + else + LOG(LDEBUG, ("state loaded successfully")); + } + + void Framework::SaveState() + { + m_work.SaveState(); + } + + void Framework::Invalidate() + { + m_work.Invalidate(); + } + + void Framework::SetupMeasurementSystem() + { + m_work.SetupMeasurementSystem(); } } - -void Framework::Move(int mode, double x, double y) -{ - DragEvent const e(x, y); - switch (mode) - { - case 0: m_work.StartDrag(e); break; - case 1: m_work.DoDrag(e); break; - case 2: m_work.StopDrag(e); break; - } -} - -void Framework::Zoom(int mode, double x1, double y1, double x2, double y2) -{ - ScaleEvent const e(x1, y1, x2, y2); - switch (mode) - { - case 0: m_work.StartScale(e); break; - case 1: m_work.DoScale(e); break; - case 2: m_work.StopScale(e); break; - } -} - -void Framework::LoadState() -{ - if (!m_work.LoadState()) - { - LOG(LDEBUG, ("no saved state, showing all world")); - m_work.ShowAll(); - } - else - LOG(LDEBUG, ("state loaded successfully")); -} - -void Framework::SaveState() -{ - m_work.SaveState(); -} - -void Framework::Invalidate() -{ - m_work.Invalidate(); -} - -void Framework::SetupMeasurementSystem() -{ - m_work.SetupMeasurementSystem(); -} - -} // namespace android diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index 54d2556510..a8aa930445 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -3,7 +3,6 @@ #include #include "../../../../../map/framework.hpp" -#include "VideoTimer.hpp" namespace android { @@ -12,7 +11,7 @@ namespace android private: ::Framework m_work; - android::VideoTimer m_videoTimer; + VideoTimer * m_videoTimer; void CallRepaint(); @@ -20,9 +19,18 @@ namespace android void CreateResourceManager(); + double m_x1; + double m_y1; + double m_x2; + double m_y2; + + bool m_hasFirst; + bool m_hasSecond; + int m_mask; + public: - Framework(); + Framework(JavaVM * jvm); ~Framework(); storage::Storage & Storage(); @@ -51,6 +59,6 @@ namespace android void AddLocalMaps() { m_work.AddLocalMaps(); } void RemoveLocalMaps() { m_work.RemoveLocalMaps(); } }; - - Framework & GetFramework(); } + +extern android::Framework * g_framework; diff --git a/android/jni/com/mapswithme/maps/MWMActivity.cpp b/android/jni/com/mapswithme/maps/MWMActivity.cpp index aa646e5ff3..cd3e6c9c8c 100644 --- a/android/jni/com/mapswithme/maps/MWMActivity.cpp +++ b/android/jni/com/mapswithme/maps/MWMActivity.cpp @@ -1,29 +1,66 @@ -#include "../core/jni_helper.hpp" +#include + +#include "../core/logging.hpp" #include "Framework.hpp" #include "../platform/Platform.hpp" #include "../../../../../platform/settings.hpp" +#include "../jni/jni_thread.hpp" +#include "../../../../../base/logging.hpp" -android::Framework * g_framework = 0; +JavaVM * g_jvm; extern "C" { + JNIEXPORT jint JNICALL + JNI_OnLoad(JavaVM * jvm, void * reserved) + { + jni::InitSystemLog(); + jni::InitAssertLog(); -JNIEXPORT void JNICALL -Java_com_mapswithme_maps_MWMActivity_nativeInit(JNIEnv * env, jobject thiz, int densityDpi, - jint screenWidth, jint screenHeight, - jstring apkPath, jstring storagePath, jstring tmpPath, jstring extTmpPath, jstring settingsPath) -{ - android::Platform::Instance().Initialize(densityDpi, screenWidth, screenHeight, - jni::GetString(env, apkPath), jni::GetString(env, storagePath), - jni::GetString(env, tmpPath), jni::GetString(env, extTmpPath), - jni::GetString(env, settingsPath)); + LOG(LINFO, ("logging services initialized")); - // @TODO framework is never deleted, it's needed for download activity too - if (!g_framework) - g_framework = new android::Framework(); -} + jni::SetCurrentJVM(jvm); + g_jvm = jvm; + LOG(LDEBUG, ("JNI_OnLoad")); + return JNI_VERSION_1_6; + } + + 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, + jint densityDpi, + jint screenWidth, + jint screenHeight, + jstring apkPath, + jstring storagePath, + jstring tmpPath, + jstring extTmpPath, + jstring settingsPath) + { + if (!g_framework) + { + android::Platform::Instance().Initialize(env, + densityDpi, + screenWidth, + screenHeight, + apkPath, + storagePath, + tmpPath, + extTmpPath, + settingsPath); + + g_framework = new android::Framework(g_jvm); + } + } //////////////////////////////////////////////////////////////////////////////////////////// JNIEXPORT void JNICALL diff --git a/android/jni/com/mapswithme/maps/SmartGLSurfaceView.cpp b/android/jni/com/mapswithme/maps/SmartGLSurfaceView.cpp index 3ce1b96e99..a23260ffb5 100644 --- a/android/jni/com/mapswithme/maps/SmartGLSurfaceView.cpp +++ b/android/jni/com/mapswithme/maps/SmartGLSurfaceView.cpp @@ -9,14 +9,14 @@ JNIEXPORT void JNICALL Java_com_mapswithme_maps_SmartGLSurfaceView_nativeZoom(JNIEnv * env, jobject thiz, jint mode, jfloat x1, jfloat y1, jfloat x2, jfloat y2) { - android::GetFramework().Zoom(mode, x1, y1, x2, y2); + g_framework->Zoom(mode, x1, y1, x2, y2); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_SmartGLSurfaceView_nativeMove(JNIEnv * env, jobject thiz, jint mode, jfloat x, jfloat y) { - android::GetFramework().Move(mode, x, y); + g_framework->Move(mode, x, y); } } diff --git a/android/jni/com/mapswithme/maps/SmartRenderer.cpp b/android/jni/com/mapswithme/maps/SmartRenderer.cpp index cd37c69cd9..576381eb7e 100644 --- a/android/jni/com/mapswithme/maps/SmartRenderer.cpp +++ b/android/jni/com/mapswithme/maps/SmartRenderer.cpp @@ -8,25 +8,25 @@ extern "C" JNIEXPORT void JNICALL Java_com_mapswithme_maps_SmartRenderer_nativeLoadResources(JNIEnv * env, jobject thiz) { - android::GetFramework().InitRenderPolicy(); + g_framework->InitRenderPolicy(); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_SmartRenderer_nativeUnloadResources(JNIEnv * env, jobject thiz) { - android::GetFramework().DeleteRenderPolicy(); + g_framework->DeleteRenderPolicy(); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_SmartRenderer_nativeDrawFrame(JNIEnv * env, jobject thiz) { - android::GetFramework().DrawFrame(); + g_framework->DrawFrame(); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_SmartRenderer_nativeResize(JNIEnv * env, jobject thiz, jint width, jint height) { - android::GetFramework().Resize(width, height); + g_framework->Resize(width, height); } } diff --git a/android/jni/com/mapswithme/maps/VideoTimer.cpp b/android/jni/com/mapswithme/maps/VideoTimer.cpp index 96b63b4f7d..c2d6ee58f4 100644 --- a/android/jni/com/mapswithme/maps/VideoTimer.cpp +++ b/android/jni/com/mapswithme/maps/VideoTimer.cpp @@ -1,58 +1,124 @@ -#include "VideoTimer.hpp" +/* + * VideoTimer.cpp + * + * Created on: Nov 5, 2011 + * Author: siarheirachytski + */ #include "../core/jni_helper.hpp" - +#include "VideoTimer.hpp" #include "../../../../../base/assert.hpp" +#include "../../../../../base/logging.hpp" -static jobject g_smartGLSurfaceView = 0; -static jmethodID g_requestRenderMethodID; +android::VideoTimer * g_timer = 0; + +jclass g_smartGlViewClass = 0; +jmethodID g_smartGlViewRedrawMethodId = 0; extern "C" { JNIEXPORT void JNICALL -Java_com_mapswithme_maps_SmartGLSurfaceView_nativeBind(JNIEnv * env, jobject thiz, jboolean isBound) +Java_com_mapswithme_maps_SmartGLSurfaceView_nativeSetRedraw(JNIEnv * env, jobject thiz, jboolean isValid) { - if (isBound) - { - g_requestRenderMethodID = jni::GetJavaMethodID(env, thiz, "requestRender", "()V"); - ASSERT(g_requestRenderMethodID, ("Can't find method void com/mapswithme/maps/SmartGLSurfaceView.requestRender()")); - - g_smartGLSurfaceView = env->NewGlobalRef(thiz); - } - else - { - jobject refToDelete = g_smartGLSurfaceView; - g_smartGLSurfaceView = 0; - env->DeleteGlobalRef(refToDelete); - } +// if (!g_smartGlViewClass) +// g_smartGlViewClass = env->GetObjectClass(thiz); +// if (isValid) +// g_smartGlViewRedrawMethodId = env->GetMethodID(g_smartGlViewClass, "requestRender", "()V"); +// else +// g_smartGlViewRedrawMethodId = 0; } } namespace android { - VideoTimer::VideoTimer() : ::VideoTimer(TFrameFn()) + VideoTimer::VideoTimer(JavaVM * javaVM, TFrameFn frameFn) + : m_javaVM(javaVM), ::VideoTimer(frameFn) { + ASSERT(g_timer == 0, ()); + g_timer = this; + } + + VideoTimer::~VideoTimer() + { + stop(); + g_timer = 0; + } + + void VideoTimer::SetParentObject(jobject videoTimer) + { + m_videoTimer = videoTimer; } void VideoTimer::start() { - if (g_smartGLSurfaceView) - { - JNIEnv * env = jni::GetEnv(); - ASSERT(env, ("JNIEnv is null")); - env->CallVoidMethod(g_smartGLSurfaceView, g_requestRenderMethodID); - } + /*JNIEnv * env; + m_javaVM->AttachCurrentThread(&env, NULL); + env->CallVoidMethod(m_videoTimer, jni::GetJavaMethodID(env, m_videoTimer, "start", "()V"));*/ + //m_state = ERunning; + +// if (!g_smartGlViewRedrawMethodId) +// { +// ASSERT(m_javaVM, ("m_jvm is NULL")); +// JNIEnv * env = 0; +// if (m_javaVM->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) +// { +// if (m_javaVM->AttachCurrentThread(&env, 0) != JNI_OK) +// { +// LOG(LWARNING, ("Can't attach thread")); +// return; +// } +// } +// +// env->CallStaticVoidMethod(g_smartGlViewClass, g_smartGlViewRedrawMethodId); +// } } void VideoTimer::resume() { + /*JNIEnv * env; + m_javaVM->AttachCurrentThread(&env, NULL); + env->CallVoidMethod(m_videoTimer, jni::GetJavaMethodID(env, m_videoTimer, "resume", "()V"));*/ + //m_state = ERunning; } void VideoTimer::pause() { + /*JNIEnv * env; + m_javaVM->AttachCurrentThread(&env, NULL); + env->CallVoidMethod(m_videoTimer, jni::GetJavaMethodID(env, m_videoTimer, "pause", "()V"));*/ + //m_state = EPaused; } void VideoTimer::stop() { + /*JNIEnv * env; + m_javaVM->AttachCurrentThread(&env, NULL); + env->CallVoidMethod(m_videoTimer, jni::GetJavaMethodID(env, m_videoTimer, "stop", "()V"));*/ + //m_state = EStopped; + } + + void VideoTimer::perform() + { + //m_frameFn(); } } + +extern "C" +{ + JNIEXPORT void JNICALL + Java_com_mapswithme_maps_VideoTimer_nativeRun(JNIEnv * env, jobject thiz) + { + ASSERT ( g_timer, ()); + g_timer->perform(); + } + + JNIEXPORT void JNICALL + Java_com_mapswithme_maps_VideoTimer_nativeInit(JNIEnv * env, jobject thiz) + { + ASSERT ( g_timer, ()); + g_timer->SetParentObject(thiz); + } +} + + + diff --git a/android/jni/com/mapswithme/maps/VideoTimer.hpp b/android/jni/com/mapswithme/maps/VideoTimer.hpp index 5b8702639c..56669eeb10 100644 --- a/android/jni/com/mapswithme/maps/VideoTimer.hpp +++ b/android/jni/com/mapswithme/maps/VideoTimer.hpp @@ -1,16 +1,41 @@ +/* + * VideoTimer.hpp + * + * Created on: Nov 5, 2011 + * Author: siarheirachytski + */ + #pragma once +#include #include "../../../../../platform/video_timer.hpp" namespace android { class VideoTimer : public ::VideoTimer { + private: + JavaVM * m_javaVM; + + jobject m_videoTimer; + public: - VideoTimer(); - virtual void start(); - virtual void stop(); - virtual void resume(); - virtual void pause(); + + VideoTimer(JavaVM * jvm, TFrameFn frameFn); + ~VideoTimer(); + + void SetParentObject(jobject videoTimer); + + void start(); + + void stop(); + + void resume(); + + void pause(); + + void perform(); }; } + +extern android::VideoTimer * g_timer; diff --git a/android/jni/com/mapswithme/platform/HttpThread.cpp b/android/jni/com/mapswithme/platform/HttpThread.cpp index 75af7f875f..0fd9b8656a 100644 --- a/android/jni/com/mapswithme/platform/HttpThread.cpp +++ b/android/jni/com/mapswithme/platform/HttpThread.cpp @@ -1,6 +1,5 @@ #include "../../../../../platform/http_thread_callback.hpp" -#include "../core/jni_helper.hpp" #include "../maps/DownloadUI.hpp" class HttpThread @@ -17,7 +16,7 @@ public: string const & pb) { /// should create java object here. - JNIEnv * env = jni::GetEnv(); + 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")); @@ -36,8 +35,11 @@ public: ~HttpThread() { - JNIEnv * env = jni::GetEnv(); - jmethodID methodId = jni::GetJavaMethodID(env, m_self, "cancel", "(Z)Z"); + 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"); ASSERT(methodId, ("Can't find java method 'cancel' in com/mapswithme/maps/downloader/DownloadChunkTask")); env->CallBooleanMethod(m_self, methodId, false); @@ -70,9 +72,10 @@ extern "C" jlong httpCallbackID, jlong beg, jbyteArray data, jlong size) { downloader::IHttpThreadCallback * cb = reinterpret_cast(httpCallbackID); - jbyte * buf = env->GetByteArrayElements(data, 0); + JNIEnv * env0 = jni::GetCurrentThreadJNIEnv(); + jbyte * buf = env0->GetByteArrayElements(data, 0); cb->OnWrite(beg, buf, size); - env->ReleaseByteArrayElements(data, buf, 0); + env0->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 5fd26aacc7..f462eec79a 100644 --- a/android/jni/com/mapswithme/platform/Language.cpp +++ b/android/jni/com/mapswithme/platform/Language.cpp @@ -1,22 +1,29 @@ #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 = jni::GetEnv(); - if (!env) + ASSERT(g_jvm, ("g_jvm is NULL")); + JNIEnv * env = 0; + bool wasAttached = false; + if (g_jvm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { - LOG(LWARNING, ("Can't get JNIEnv")); - return DEFAULT_LANG; + if (g_jvm->AttachCurrentThread(&env, 0) != JNI_OK) + { + LOG(LWARNING, ("Can't attach thread")); + return DEFAULT_LANG; + } + wasAttached = true; } jclass localeClass = env->FindClass("java/util/Locale"); @@ -42,5 +49,7 @@ string GetAndroidSystemLanguage() env->ReleaseStringUTFChars(langString, langUtf8); } + if (wasAttached) + g_jvm->DetachCurrentThread(); return result; } diff --git a/android/jni/com/mapswithme/platform/PThreadImpl.cpp b/android/jni/com/mapswithme/platform/PThreadImpl.cpp deleted file mode 100644 index e068f9b2aa..0000000000 --- a/android/jni/com/mapswithme/platform/PThreadImpl.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#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 e7983c117f..82c675b76d 100644 --- a/android/jni/com/mapswithme/platform/Platform.cpp +++ b/android/jni/com/mapswithme/platform/Platform.cpp @@ -1,5 +1,7 @@ #include "Platform.hpp" +#include "../core/jni_string.hpp" + #include "../../../../../base/logging.hpp" #include "../../../../../std/algorithm.hpp" @@ -11,7 +13,8 @@ public: PlatformImpl(int densityDpi, int screenWidth, int screenHeight) { // Constants are taken from android.util.DisplayMetrics - // ceiling screen sizes to the nearest power of two, and taking half of it as a tile size + /// ceiling screen sizes to the nearest power of two, and taking half of it as a tile size + double const log2 = log(2.0); screenWidth = static_cast(pow(2.0, ceil(log(double(screenWidth)) / log2))); @@ -19,15 +22,15 @@ public: m_tileSize = min(max(max(screenWidth, screenHeight) / 2, 128), 512); - int const k = static_cast((256.0 / m_tileSize) * (256.0 / m_tileSize)); + int k = static_cast((256.0 / m_tileSize) * (256.0 / m_tileSize)); - // calculating how much tiles we need for the screen of such size + /// calculating how much tiles we need for the screen of such size - // pure magic ;) + /// pure magic ;) - double const rotatedScreenCircleDiameter = sqrt(screenWidth * screenWidth + screenHeight * screenHeight); - int const tilesOnOneSide = ceil(rotatedScreenCircleDiameter / (m_tileSize / 1.05 / 2)); - int const singleScreenTilesCount = tilesOnOneSide * tilesOnOneSide; + double rotatedScreenCircleDiameter = sqrt(screenWidth * screenWidth + screenHeight * screenHeight); + int tilesOnOneSide = ceil(rotatedScreenCircleDiameter / (m_tileSize / 1.05 / 2)); + int singleScreenTilesCount = tilesOnOneSide * tilesOnOneSide; m_maxTilesCount = singleScreenTilesCount * 2; LOG(LINFO, ("minimum amount of tiles needed is", m_maxTilesCount)); @@ -91,19 +94,24 @@ namespace android delete m_impl; } - void Platform::Initialize(int densityDpi, int screenWidth, int screenHeight, - string const & apkPath, - string const & storagePath, string const & tmpPath, - string const & extTmpPath, string const & settingsPath) + void Platform::Initialize(JNIEnv * env, + jint densityDpi, + jint screenWidth, + jint screenHeight, + jstring apkPath, + jstring storagePath, + jstring tmpPath, + jstring extTmpPath, + jstring settingsPath) { m_impl = new PlatformImpl(densityDpi, screenWidth, screenHeight); - m_resourcesDir = apkPath; - m_writableDir = storagePath; - m_settingsDir = settingsPath; + m_resourcesDir = jni::ToString(env, apkPath); + m_writableDir = jni::ToString(env, storagePath); + m_settingsDir = jni::ToString(env, settingsPath); - m_localTmpPath = tmpPath; - m_externalTmpPath = extTmpPath; + m_localTmpPath = jni::ToString(env, tmpPath); + m_externalTmpPath = jni::ToString(env, extTmpPath); // By default use external temporary folder m_tmpDir = m_externalTmpPath; diff --git a/android/jni/com/mapswithme/platform/Platform.hpp b/android/jni/com/mapswithme/platform/Platform.hpp index 4ac09d19f4..002032b20e 100644 --- a/android/jni/com/mapswithme/platform/Platform.hpp +++ b/android/jni/com/mapswithme/platform/Platform.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "../../../../../platform/platform.hpp" namespace android @@ -13,10 +15,15 @@ namespace android public: ~Platform(); - void Initialize(int densityDpi, int screenWidth, int screenHeight, - string const & apkPath, - string const & storagePath, string const & tmpPath, - string const & extTmpPath, string const & settingsPath); + void Initialize(JNIEnv * env, + jint densityDpi, + jint screenWidth, + jint screenHeight, + jstring apkPath, + jstring storagePath, + jstring tmpPath, + jstring extTmpPath, + jstring settingsPath); void OnExternalStorageStatusChanged(bool isAvailable); diff --git a/android/src/com/mapswithme/maps/MWMActivity.java b/android/src/com/mapswithme/maps/MWMActivity.java index 0c163ea887..05b897595d 100644 --- a/android/src/com/mapswithme/maps/MWMActivity.java +++ b/android/src/com/mapswithme/maps/MWMActivity.java @@ -26,6 +26,8 @@ import android.util.Log; public class MWMActivity extends SmartGLActivity implements LocationService.Listener { + VideoTimer m_timer; + private static String TAG = "MWMActivity"; private final static String PACKAGE_NAME = "com.mapswithme.maps"; @@ -171,6 +173,8 @@ public class MWMActivity extends SmartGLActivity implements checkMeasurementSystem(); + m_timer = new VideoTimer(); + m_locationService = new LocationService(this); } @@ -361,6 +365,7 @@ public class MWMActivity extends SmartGLActivity implements private native void nativeInit(int densityDpi, int screenWidth, int screenHeight, String apkPath, String storagePath, String tmpPath, String extTmpPath, String settingsPath); + private native void nativeDestroy(); private native void nativeLocationStatusChanged(int newStatus); private native void nativeLocationUpdated(long time, double lat, double lon, float accuracy); private native void nativeCompassUpdated(long time, double magneticNorth, double trueNorth, float accuracy); diff --git a/android/src/com/mapswithme/maps/SmartGLSurfaceView.java b/android/src/com/mapswithme/maps/SmartGLSurfaceView.java index 8118a21964..1c79a1f049 100644 --- a/android/src/com/mapswithme/maps/SmartGLSurfaceView.java +++ b/android/src/com/mapswithme/maps/SmartGLSurfaceView.java @@ -1,12 +1,9 @@ package com.mapswithme.maps; -import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.opengles.GL10; import android.content.Context; -import android.graphics.Color; import android.opengl.GLSurfaceView; import android.util.Log; import android.view.MotionEvent; @@ -37,7 +34,7 @@ public class SmartGLSurfaceView extends GLSurfaceView private void init() { setEGLConfigChooser(true); - m_renderer = new SmartRenderer(this); + m_renderer = new SmartRenderer(); setRenderer(m_renderer); setRenderMode(RENDERMODE_WHEN_DIRTY); @@ -59,6 +56,7 @@ public class SmartGLSurfaceView extends GLSurfaceView { Log.d(TAG, "surfaceCreated"); m_renderer.m_isBaseSurfaceReady = false; + nativeSetRedraw(false); super.surfaceCreated(holder); } @@ -67,9 +65,9 @@ public class SmartGLSurfaceView extends GLSurfaceView { Log.d(TAG, "surfaceChanged " + w + " " + h); m_renderer.m_isBaseSurfaceReady = true; + nativeSetRedraw(true); super.surfaceChanged(holder, format, w, h); queueEvent(m_tryToLoadResourcesIfReady); - nativeBind(true); } @Override @@ -78,9 +76,9 @@ public class SmartGLSurfaceView extends GLSurfaceView Log.d(TAG, "surfaceDestroyed"); m_renderer.m_isBaseSurfaceReady = false; m_renderer.m_isLocalSurfaceReady = false; + nativeSetRedraw(false); super.surfaceDestroyed(holder); queueEvent(m_unloadResources); - nativeBind(false); } @Override @@ -124,85 +122,50 @@ public class SmartGLSurfaceView extends GLSurfaceView @Override public boolean onTouchEvent (MotionEvent event) { - final float x1, y1, x2, y2; switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: - x1 = event.getX(); y1 = event.getY(); - queueEvent(new Runnable() {@Override public void run() {nativeMove(START_CMD, x1, y1);}}); + nativeMove(START_CMD, event.getX(), event.getY()); break; case MotionEvent.ACTION_POINTER_DOWN: if (event.getPointerId(0) < event.getPointerId(1)) - { - x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1); - } + nativeZoom(START_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1)); else - { - x1 = event.getX(1); y1 = event.getY(1); x2 = event.getX(0); y2 = event.getY(0); - } - queueEvent(new Runnable() {@Override public void run() {nativeZoom(START_CMD, x1, y1, x2, y2);}}); + nativeZoom(START_CMD, event.getX(1), event.getY(1), event.getX(0), event.getY(0)); break; case MotionEvent.ACTION_MOVE: if (event.getPointerCount() > 1) { if (event.getPointerId(0) < event.getPointerId(1)) - { - x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1); - } + nativeZoom(DO_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1)); else - { - x1 = event.getX(1); y1 = event.getY(1); x2 = event.getX(0); y2 = event.getY(0); - } - queueEvent(new Runnable() {@Override public void run() {nativeZoom(DO_CMD, x1, y1, x2, y2);}}); + nativeZoom(DO_CMD, event.getX(1), event.getY(1), event.getX(0), event.getY(0)); } else - { - x1 = event.getX(); y1 = event.getY(); - queueEvent(new Runnable() {@Override public void run() {nativeMove(DO_CMD, x1, y1);}}); - } + nativeMove(DO_CMD, event.getX(), event.getY()); break; case MotionEvent.ACTION_POINTER_UP: if (event.getPointerId(0) < event.getPointerId(1)) - { - x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1); - } + nativeZoom(STOP_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1)); else - { - x1 = event.getX(1); y1 = event.getY(1); x2 = event.getX(0); y2 = event.getY(0); - } - queueEvent(new Runnable() {@Override public void run() {nativeZoom(STOP_CMD, x1, y1, x2, y2);}}); + nativeZoom(STOP_CMD, event.getX(1), event.getY(1), event.getX(0), event.getY(0)); final int leftIndex = ((event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0 ? 1 : 0; - final float x = event.getX(leftIndex), y = event.getY(leftIndex); - queueEvent(new Runnable() {@Override public void run() {nativeMove(START_CMD, x, y);}}); + nativeMove(START_CMD, event.getX(leftIndex), event.getY(leftIndex)); break; case MotionEvent.ACTION_UP: - x1 = event.getX(); y1 = event.getY(); - queueEvent(new Runnable() {@Override public void run() {nativeMove(STOP_CMD, x1, y1);}}); + nativeMove(STOP_CMD, event.getX(), event.getY()); break; case MotionEvent.ACTION_CANCEL: if (event.getPointerCount() > 1) - { - if (event.getPointerId(0) < event.getPointerId(1)) - { - x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1); - } - else - { - x1 = event.getX(1); y1 = event.getY(1); x2 = event.getX(0); y2 = event.getY(0); - } - queueEvent(new Runnable() {@Override public void run() {nativeZoom(STOP_CMD, x1, y1, x2, y2);}}); - } + nativeZoom(STOP_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1)); else - { - x1 = event.getX(); y1 = event.getY(); - queueEvent(new Runnable() {@Override public void run() {nativeMove(STOP_CMD, x1, y1);}}); - } + nativeMove(STOP_CMD, event.getX(), event.getY()); } requestRender(); @@ -212,7 +175,7 @@ public class SmartGLSurfaceView extends GLSurfaceView // Mode 0 - Start, 1 - Do, 2 - Stop private native void nativeMove(int mode, float x, float y); private native void nativeZoom(int mode, float x1, float y1, float x2, float y2); - private native void nativeBind(boolean isBound); + private native void nativeSetRedraw(boolean isValid); } class SmartRenderer implements GLSurfaceView.Renderer @@ -228,11 +191,8 @@ class SmartRenderer implements GLSurfaceView.Renderer private boolean m_areResourcesLoaded = false; - private SmartGLSurfaceView m_view; - - public SmartRenderer(SmartGLSurfaceView view) + public SmartRenderer() { - m_view = view; } public void loadResources() diff --git a/android/src/com/mapswithme/maps/VideoTimer.java b/android/src/com/mapswithme/maps/VideoTimer.java new file mode 100644 index 0000000000..ee75de76ba --- /dev/null +++ b/android/src/com/mapswithme/maps/VideoTimer.java @@ -0,0 +1,59 @@ +package com.mapswithme.maps; + +import java.util.Timer; +import java.util.TimerTask; + +public class VideoTimer { + + private static String TAG = "VideoTimer"; + + Timer m_timer; + + private native void nativeInit(); + private native void nativeRun(); + + + public class VideoTimerTask extends TimerTask { + + @Override + public void run() { + nativeRun(); + } + } + + VideoTimerTask m_timerTask; + int m_interval; + + public VideoTimer() + { + m_interval = 1000 / 60; + nativeInit(); + } + + void start() + { + m_timerTask = new VideoTimerTask(); + m_timer = new Timer("VideoTimer"); + m_timer.scheduleAtFixedRate(m_timerTask, 0, m_interval); + } + + void resume() + { + m_timerTask = new VideoTimerTask(); + m_timer = new Timer("VideoTimer"); + m_timer.scheduleAtFixedRate(m_timerTask, 0, m_interval); + } + + void pause() + { + m_timer.cancel(); +// m_timer.purge(); + } + + void stop() + { + m_timer.cancel(); +// m_timer.purge(); + } + +} diff --git a/base/thread.cpp b/base/thread.cpp index afc8f8b022..33f0bce5e1 100644 --- a/base/thread.cpp +++ b/base/thread.cpp @@ -7,11 +7,6 @@ #include "../std/windows.hpp" #else #include - #if defined (OMIM_OS_ANDROID) - /// External implementations are in android/jni code - void AndroidThreadAttachToJVM(); - void AndroidThreadDetachFromJVM(); - #endif #endif @@ -104,19 +99,9 @@ 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; } @@ -171,7 +156,7 @@ namespace threads { if (m_routine) { - int const error = m_impl->Join(); + int error = m_impl->Join(); if (0 != error) { ASSERT ( !"Thread join failed. See error value.", (error) );