[android] - Refactored jni system

- Added automatic thread attach/deattach
- Multitouch events are handled on the separate thread
This commit is contained in:
Alex Zolotarev 2012-01-16 13:12:47 +03:00 committed by Alex Zolotarev
parent 51e16db032
commit 0e7577016c
31 changed files with 421 additions and 886 deletions

View file

@ -12,16 +12,14 @@ 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 \
@ -33,8 +31,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 \
LOCAL_LDLIBS := -llog -lGLESv1_CM \
-lmap -lversion -lsearch -lstorage -lindexer -lyg -lplatform \

View file

@ -1,21 +1,69 @@
#include "jni_helper.hpp"
#include "logging.hpp"
#include "../../../../../base/assert.hpp"
static JavaVM * g_jvm = 0;
namespace jni {
extern "C"
{
// 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)
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)
{
ASSERT ( env != 0 && obj != 0, () );
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 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;
}
}

View file

@ -2,28 +2,16 @@
#include <jni.h>
#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);
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");
}
*/
JNIEnv * GetEnv();
JavaVM * GetJVM();
}

View file

@ -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();
}
}

View file

@ -1,23 +0,0 @@
#pragma once
#include <string.h>
#include <jni.h>
#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);
}

View file

@ -2,6 +2,7 @@
#include <android/log.h>
#include "../../../../../base/logging.hpp"
#include "../../../../../base/assert.hpp"
namespace jni {

View file

@ -1,7 +1,5 @@
#pragma once
#include "../../../../../base/logging.hpp"
namespace jni
{
void InitSystemLog();

View file

@ -1,10 +1,3 @@
/*
* render_context.cpp
*
* Created on: Oct 14, 2011
* Author: siarheirachytski
*/
#include "render_context.hpp"
namespace android

View file

@ -1,16 +1,7 @@
/*
* 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
@ -19,9 +10,7 @@ namespace android
RenderContext();
virtual void makeCurrent();
virtual shared_ptr<yg::gl::RenderContext> createShared();
virtual void endThreadDrawing();
};
}

View file

@ -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;
}
}

View file

@ -1,73 +0,0 @@
/*
* method_ref.hpp
*
* Created on: Nov 27, 2011
* Author: siarheirachytski
*/
#pragma once
#include <jni.h>
#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 <typename A1>
void CallVoid(jobject self, A1 a1)
{
GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1);
}
template <typename A1, typename A2>
void CallVoid(jobject self, A1 a1, A2 a2)
{
GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2);
}
template <typename A1, typename A2, typename A3>
void CallVoid(jobject self, A1 a1, A2 a2, A3 a3)
{
GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2, a3);
}
template <typename A1, typename A2, typename A3, typename A4>
void CallVoid(jobject self, A1 a1, A2 a2, A3 a3, A4 a4)
{
GetCurrentThreadJNIEnv()->CallVoidMethod(self, m_index, a1, a2, a3, a4);
}
template <typename A1, typename A2, typename A3, typename A4, typename A5>
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);
};
}

View file

@ -1,65 +0,0 @@
/*
* jni_thread.cpp
*
* Created on: Nov 27, 2011
* Author: siarheirachytski
*/
#include "jni_thread.hpp"
#include <pthread.h>
#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;
}
}

View file

@ -1,18 +0,0 @@
/*
* jni_thread.hpp
*
* Created on: Nov 27, 2011
* Author: siarheirachytski
*/
#pragma once
#include <jni.h>
namespace jni
{
void SetCurrentJVM(JavaVM * jvm);
JavaVM * GetCurrentJVM();
JNIEnv * GetCurrentThreadJNIEnv();
}

View file

@ -1,7 +1,8 @@
#include <jni.h>
#include "Framework.hpp"
#include "DownloadUI.hpp"
#include "../jni/jni_thread.hpp"
#include "../core/jni_helper.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<int64_t, int64_t> 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);
}
}
@ -50,20 +54,20 @@ extern "C"
if (g_downloadUI)
{
/// activity has been killed without onDestroy, destroying manually
g_framework->Storage().Unsubscribe();
android::GetFramework().Storage().Unsubscribe();
delete g_downloadUI;
g_downloadUI = 0;
}
g_downloadUI = new android::DownloadUI(thiz);
g_framework->Storage().Subscribe(bind(&android::DownloadUI::OnChangeCountry, g_downloadUI, _1),
android::GetFramework().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)
{
g_framework->Storage().Unsubscribe();
android::GetFramework().Storage().Unsubscribe();
delete g_downloadUI;
g_downloadUI = 0;
}
@ -72,14 +76,14 @@ extern "C"
Java_com_mapswithme_maps_DownloadUI_countriesCount(JNIEnv * env, jobject thiz,
jint group, jint country, jint region)
{
return static_cast<jint>(g_framework->Storage().CountriesCount(storage::TIndex(group, country, region)));
return static_cast<jint>(android::GetFramework().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 = g_framework->Storage().CountryName(storage::TIndex(group, country, region));
string const name = android::GetFramework().Storage().CountryName(storage::TIndex(group, country, region));
return env->NewStringUTF(name.c_str());
}
@ -87,35 +91,35 @@ extern "C"
Java_com_mapswithme_maps_DownloadUI_countryLocalSizeInBytes(JNIEnv * env, jobject thiz,
jint group, jint country, jint region)
{
return g_framework->Storage().CountrySizeInBytes(storage::TIndex(group, country, region)).first;
return android::GetFramework().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 g_framework->Storage().CountrySizeInBytes(storage::TIndex(group, country, region)).second;
return android::GetFramework().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<jint>(g_framework->Storage().CountryStatus(storage::TIndex(group, country, region)));
return static_cast<jint>(android::GetFramework().Storage().CountryStatus(storage::TIndex(group, country, region)));
}
JNIEXPORT jint JNICALL
Java_com_mapswithme_maps_DownloadUI_downloadCountry(JNIEnv * env, jobject thiz,
jint group, jint country, jint region)
{
g_framework->Storage().DownloadCountry(storage::TIndex(group, country, region));
android::GetFramework().Storage().DownloadCountry(storage::TIndex(group, country, region));
}
JNIEXPORT jint JNICALL
Java_com_mapswithme_maps_DownloadUI_deleteCountry(JNIEnv * env, jobject thiz,
jint group, jint country, jint region)
{
g_framework->Storage().DeleteCountry(storage::TIndex(group, country, region));
android::GetFramework().Storage().DeleteCountry(storage::TIndex(group, country, region));
}
}

View file

@ -1,8 +1,8 @@
#pragma once
#include "../jni/jni_method.hpp"
#include "../../../../../storage/storage.hpp"
#include "../../../../../std/scoped_ptr.hpp"
#include <jni.h>
namespace android
{
@ -11,8 +11,8 @@ namespace android
private:
jobject m_self;
scoped_ptr<jni::Method> m_onChangeCountry;
scoped_ptr<jni::Method> m_onProgress;
jmethodID m_onChangeCountry;
jmethodID m_onProgress;
public:

View file

@ -21,169 +21,159 @@
#include "../../../../../base/logging.hpp"
#include "../../../../../base/math.hpp"
android::Framework * g_framework = 0;
extern android::Framework * g_framework;
namespace android
{
void Framework::CallRepaint()
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<location::TLocationStatus>(newStatus));
}
void Framework::OnLocationUpdated(uint64_t time, double lat, double lon, float accuracy)
{
location::GpsInfo info;
info.m_timestamp = static_cast<double>(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<double>(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
{
//LOG(LINFO, ("Calling Repaint"));
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;
}
Framework::Framework(JavaVM * jvm)
: m_work(),
m_hasFirst(false),
m_hasSecond(false),
m_mask(0)
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())
{
ASSERT(g_framework == 0, ());
g_framework = this;
m_work.SetNeedRedraw(false);
m_videoTimer = new VideoTimer(jvm, bind(&Framework::CallRepaint, this));
shared_ptr<PaintEvent> paintEvent(new PaintEvent(m_work.GetRenderPolicy()->GetDrawer().get()));
// @TODO refactor storage
m_work.Storage().ReInitCountries(false);
}
Framework::~Framework()
{
delete m_videoTimer;
}
void Framework::OnLocationStatusChanged(int newStatus)
{
m_work.OnLocationStatusChanged(static_cast<location::TLocationStatus>(newStatus));
}
void Framework::OnLocationUpdated(uint64_t time, double lat, double lon, float accuracy)
{
location::GpsInfo info;
info.m_timestamp = static_cast<double>(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<double>(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> 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();
m_work.BeginPaint(paintEvent);
m_work.DoPaint(paintEvent);
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();
}
} // namespace android

View file

@ -3,6 +3,7 @@
#include <jni.h>
#include "../../../../../map/framework.hpp"
#include "VideoTimer.hpp"
namespace android
{
@ -11,7 +12,7 @@ namespace android
private:
::Framework m_work;
VideoTimer * m_videoTimer;
android::VideoTimer m_videoTimer;
void CallRepaint();
@ -19,18 +20,9 @@ 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(JavaVM * jvm);
Framework();
~Framework();
storage::Storage & Storage();
@ -59,6 +51,6 @@ namespace android
void AddLocalMaps() { m_work.AddLocalMaps(); }
void RemoveLocalMaps() { m_work.RemoveLocalMaps(); }
};
}
extern android::Framework * g_framework;
Framework & GetFramework();
}

View file

@ -1,65 +1,32 @@
#include <jni.h>
#include "../core/logging.hpp"
#include "../core/jni_helper.hpp"
#include "Framework.hpp"
#include "../platform/Platform.hpp"
#include "../../../../../platform/settings.hpp"
#include "../jni/jni_thread.hpp"
#include "../../../../../base/logging.hpp"
JavaVM * g_jvm;
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"));
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));
g_framework = new android::Framework();
}
jni::SetCurrentJVM(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,
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
Java_com_mapswithme_maps_MWMActivity_nativeDestroy(JNIEnv * env, jobject thiz)
{
delete g_framework;
g_framework = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -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)
{
g_framework->Zoom(mode, x1, y1, x2, y2);
android::GetFramework().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)
{
g_framework->Move(mode, x, y);
android::GetFramework().Move(mode, x, y);
}
}

View file

@ -8,25 +8,25 @@ extern "C"
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_SmartRenderer_nativeLoadResources(JNIEnv * env, jobject thiz)
{
g_framework->InitRenderPolicy();
android::GetFramework().InitRenderPolicy();
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_SmartRenderer_nativeUnloadResources(JNIEnv * env, jobject thiz)
{
g_framework->DeleteRenderPolicy();
android::GetFramework().DeleteRenderPolicy();
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_SmartRenderer_nativeDrawFrame(JNIEnv * env, jobject thiz)
{
g_framework->DrawFrame();
android::GetFramework().DrawFrame();
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_SmartRenderer_nativeResize(JNIEnv * env, jobject thiz, jint width, jint height)
{
g_framework->Resize(width, height);
android::GetFramework().Resize(width, height);
}
}

View file

@ -1,124 +1,58 @@
/*
* VideoTimer.cpp
*
* Created on: Nov 5, 2011
* Author: siarheirachytski
*/
#include "VideoTimer.hpp"
#include "../core/jni_helper.hpp"
#include "VideoTimer.hpp"
#include "../../../../../base/assert.hpp"
#include "../../../../../base/logging.hpp"
android::VideoTimer * g_timer = 0;
jclass g_smartGlViewClass = 0;
jmethodID g_smartGlViewRedrawMethodId = 0;
static jobject g_smartGLSurfaceView = 0;
static jmethodID g_requestRenderMethodID;
extern "C"
{
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_SmartGLSurfaceView_nativeSetRedraw(JNIEnv * env, jobject thiz, jboolean isValid)
Java_com_mapswithme_maps_SmartGLSurfaceView_nativeBind(JNIEnv * env, jobject thiz, jboolean isBound)
{
// if (!g_smartGlViewClass)
// g_smartGlViewClass = env->GetObjectClass(thiz);
// if (isValid)
// g_smartGlViewRedrawMethodId = env->GetMethodID(g_smartGlViewClass, "requestRender", "()V");
// else
// g_smartGlViewRedrawMethodId = 0;
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);
}
}
}
namespace android
{
VideoTimer::VideoTimer(JavaVM * javaVM, TFrameFn frameFn)
: m_javaVM(javaVM), ::VideoTimer(frameFn)
VideoTimer::VideoTimer() : ::VideoTimer(TFrameFn())
{
ASSERT(g_timer == 0, ());
g_timer = this;
}
VideoTimer::~VideoTimer()
{
stop();
g_timer = 0;
}
void VideoTimer::SetParentObject(jobject videoTimer)
{
m_videoTimer = videoTimer;
}
void VideoTimer::start()
{
/*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);
// }
if (g_smartGLSurfaceView)
{
JNIEnv * env = jni::GetEnv();
ASSERT(env, ("JNIEnv is null"));
env->CallVoidMethod(g_smartGLSurfaceView, g_requestRenderMethodID);
}
}
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);
}
}

View file

@ -1,41 +1,16 @@
/*
* VideoTimer.hpp
*
* Created on: Nov 5, 2011
* Author: siarheirachytski
*/
#pragma once
#include <jni.h>
#include "../../../../../platform/video_timer.hpp"
namespace android
{
class VideoTimer : public ::VideoTimer
{
private:
JavaVM * m_javaVM;
jobject m_videoTimer;
public:
VideoTimer(JavaVM * jvm, TFrameFn frameFn);
~VideoTimer();
void SetParentObject(jobject videoTimer);
void start();
void stop();
void resume();
void pause();
void perform();
VideoTimer();
virtual void start();
virtual void stop();
virtual void resume();
virtual void pause();
};
}
extern android::VideoTimer * g_timer;

View file

@ -1,5 +1,6 @@
#include "../../../../../platform/http_thread_callback.hpp"
#include "../core/jni_helper.hpp"
#include "../maps/DownloadUI.hpp"
class HttpThread
@ -16,7 +17,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 +36,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);
@ -72,10 +70,9 @@ extern "C"
jlong httpCallbackID, jlong beg, jbyteArray data, jlong size)
{
downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(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

View file

@ -1,29 +1,22 @@
#include <jni.h>
#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()
{
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)
JNIEnv * env = jni::GetEnv();
if (!env)
{
if (g_jvm->AttachCurrentThread(&env, 0) != JNI_OK)
{
LOG(LWARNING, ("Can't attach thread"));
return DEFAULT_LANG;
}
wasAttached = true;
LOG(LWARNING, ("Can't get JNIEnv"));
return DEFAULT_LANG;
}
jclass localeClass = env->FindClass("java/util/Locale");
@ -49,7 +42,5 @@ string GetAndroidSystemLanguage()
env->ReleaseStringUTFChars(langString, langUtf8);
}
if (wasAttached)
g_jvm->DetachCurrentThread();
return result;
}

View file

@ -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();
}

View file

@ -1,68 +1,24 @@
#include "Platform.hpp"
#include "../core/jni_string.hpp"
#include <math.h>
#include "../../../../../base/logging.hpp"
class Platform::PlatformImpl
{
public:
PlatformImpl(int densityDpi, int screenWidth, int screenHeight)
PlatformImpl(int densityDpi)
{ // 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
double const log2 = log(2.0);
screenWidth = static_cast<int>(pow(2.0, ceil(log(double(screenWidth)) / log2)));
screenHeight = static_cast<int>(pow(2.0, ceil(log(double(screenHeight)) / log2)));
m_tileSize = min(max(max(screenWidth, screenHeight) / 2, 128), 512);
int k = static_cast<int>((256.0 / m_tileSize) * (256.0 / m_tileSize));
/// calculating how much tiles we need for the screen of such size
/// pure magic ;)
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));
m_maxTilesCount = max(120 * k, m_maxTilesCount);
switch (densityDpi)
{
case 120:
m_visualScale = 0.75;
m_skinName = "basic_ldpi.skn";
LOG(LINFO, ("using LDPI resources"));
break;
case 160:
m_visualScale = 1.0;
m_skinName = "basic_mdpi.skn";
LOG(LINFO, ("using MDPI resources"));
break;
case 240:
m_visualScale = 1.5;
m_skinName = "basic_hdpi.skn";
LOG(LINFO, ("using HDPI resources"));
break;
default:
m_visualScale = 2.0;
m_skinName = "basic_xhdpi.skn";
LOG(LINFO, ("using XHDPI resources"));
break;
case 120: m_visualScale = 0.75; m_skinName = "basic_ldpi.skn"; break;
case 160: m_visualScale = 1.0; m_skinName = "basic_mdpi.skn"; break;
case 240: m_visualScale = 1.5; m_skinName = "basic_hdpi.skn"; break;
default: m_visualScale = 2.0; m_skinName = "basic_xhdpi.skn"; break;
}
}
double m_visualScale;
string m_skinName;
int m_maxTilesCount;
size_t m_tileSize;
};
double Platform::VisualScale() const
@ -75,16 +31,6 @@ string Platform::SkinName() const
return m_impl->m_skinName;
}
int Platform::MaxTilesCount() const
{
return m_impl->m_maxTilesCount;
}
int Platform::TileSize() const
{
return m_impl->m_tileSize;
}
namespace android
{
Platform::~Platform()
@ -92,15 +38,10 @@ namespace android
delete m_impl;
}
void Platform::Initialize(JNIEnv * env,
jint densityDpi,
jint screenWidth,
jint screenHeight,
jstring apkPath,
jstring storagePath,
jstring tmpPath,
jstring extTmpPath,
jstring settingsPath)
void Platform::Initialize(int densityDpi, string const & apkPath,
jint screenWidth, jint screenHeight,
string const & storagePath, string const & tmpPath,
string const & extTmpPath, string const & settingsPath)
{
m_impl = new PlatformImpl(densityDpi, screenWidth, screenHeight);

View file

@ -1,7 +1,5 @@
#pragma once
#include <jni.h>
#include "../../../../../platform/platform.hpp"
namespace android
@ -15,15 +13,10 @@ namespace android
public:
~Platform();
void Initialize(JNIEnv * env,
jint densityDpi,
jint screenWidth,
jint screenHeight,
jstring apkPath,
jstring storagePath,
jstring tmpPath,
jstring extTmpPath,
jstring settingsPath);
void Initialize(int densityDpi, jint screenWidth, jint screenHeight,
string const & apkPath,
string const & storagePath, string const & tmpPath,
string const & extTmpPath, string const & settingsPath);
void OnExternalStorageStatusChanged(bool isAvailable);

View file

@ -26,8 +26,6 @@ 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";
@ -173,11 +171,15 @@ public class MWMActivity extends SmartGLActivity implements
checkMeasurementSystem();
m_timer = new VideoTimer();
m_locationService = new LocationService(this);
}
@Override
public void onDestroy()
{
nativeDestroy();
}
// From Location interface
public void onLocationStatusChanged(int newStatus)
{
@ -362,15 +364,10 @@ public class MWMActivity extends SmartGLActivity implements
private native void nativeStorageConnected();
private native void nativeStorageDisconnected();
private native void nativeInit(int densityDpi,
int width,
int height,
String apkPath,
String storagePath,
String tmpPath,
String extTmpPath,
String settingsPath);
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);

View file

@ -1,9 +1,12 @@
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;
@ -34,7 +37,7 @@ public class SmartGLSurfaceView extends GLSurfaceView
private void init()
{
setEGLConfigChooser(true);
m_renderer = new SmartRenderer();
m_renderer = new SmartRenderer(this);
setRenderer(m_renderer);
setRenderMode(RENDERMODE_WHEN_DIRTY);
@ -56,7 +59,6 @@ public class SmartGLSurfaceView extends GLSurfaceView
{
Log.d(TAG, "surfaceCreated");
m_renderer.m_isBaseSurfaceReady = false;
nativeSetRedraw(false);
super.surfaceCreated(holder);
}
@ -65,9 +67,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
@ -76,9 +78,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
@ -122,50 +124,85 @@ 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:
nativeMove(START_CMD, event.getX(), event.getY());
x1 = event.getX(); y1 = event.getY();
queueEvent(new Runnable() {@Override public void run() {nativeMove(START_CMD, x1, y1);}});
break;
case MotionEvent.ACTION_POINTER_DOWN:
if (event.getPointerId(0) < event.getPointerId(1))
nativeZoom(START_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1));
{
x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1);
}
else
nativeZoom(START_CMD, event.getX(1), event.getY(1), event.getX(0), event.getY(0));
{
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);}});
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() > 1)
{
if (event.getPointerId(0) < event.getPointerId(1))
nativeZoom(DO_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1));
{
x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1);
}
else
nativeZoom(DO_CMD, event.getX(1), event.getY(1), event.getX(0), event.getY(0));
{
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);}});
}
else
nativeMove(DO_CMD, event.getX(), event.getY());
{
x1 = event.getX(); y1 = event.getY();
queueEvent(new Runnable() {@Override public void run() {nativeMove(DO_CMD, x1, y1);}});
}
break;
case MotionEvent.ACTION_POINTER_UP:
if (event.getPointerId(0) < event.getPointerId(1))
nativeZoom(STOP_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(1));
{
x1 = event.getX(0); y1 = event.getY(0); x2 = event.getX(1); y2 = event.getY(1);
}
else
nativeZoom(STOP_CMD, event.getX(1), event.getY(1), event.getX(0), event.getY(0));
{
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);}});
final int leftIndex = ((event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0 ? 1 : 0;
nativeMove(START_CMD, event.getX(leftIndex), event.getY(leftIndex));
final float x = event.getX(leftIndex), y = event.getY(leftIndex);
queueEvent(new Runnable() {@Override public void run() {nativeMove(START_CMD, x, y);}});
break;
case MotionEvent.ACTION_UP:
nativeMove(STOP_CMD, event.getX(), event.getY());
x1 = event.getX(); y1 = event.getY();
queueEvent(new Runnable() {@Override public void run() {nativeMove(STOP_CMD, x1, y1);}});
break;
case MotionEvent.ACTION_CANCEL:
if (event.getPointerCount() > 1)
nativeZoom(STOP_CMD, event.getX(0), event.getY(0), event.getX(1), event.getY(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);}});
}
else
nativeMove(STOP_CMD, event.getX(), event.getY());
{
x1 = event.getX(); y1 = event.getY();
queueEvent(new Runnable() {@Override public void run() {nativeMove(STOP_CMD, x1, y1);}});
}
}
requestRender();
@ -175,7 +212,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 nativeSetRedraw(boolean isValid);
private native void nativeBind(boolean isBound);
}
class SmartRenderer implements GLSurfaceView.Renderer
@ -191,8 +228,11 @@ class SmartRenderer implements GLSurfaceView.Renderer
private boolean m_areResourcesLoaded = false;
public SmartRenderer()
private SmartGLSurfaceView m_view;
public SmartRenderer(SmartGLSurfaceView view)
{
m_view = view;
}
public void loadResources()

View file

@ -1,59 +0,0 @@
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();
}
}

View file

@ -7,6 +7,11 @@
#include "../std/windows.hpp"
#else
#include <pthread.h>
#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<IRoutine *>(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) );