From 53b5808d4f16a44779ef5fd8a5c8ca5e262e0379 Mon Sep 17 00:00:00 2001 From: dhewg Date: Thu, 24 Feb 2011 00:45:41 +0100 Subject: [PATCH] ANDROID: Move rest of everything JNI --- backends/platform/android/android.cpp | 162 ++--------------- backends/platform/android/android.h | 23 +-- backends/platform/android/asset-archive.h | 5 + backends/platform/android/gfx.cpp | 24 +-- backends/platform/android/jni.cpp | 201 +++++++++++++++++++++- backends/platform/android/jni.h | 54 +++++- 6 files changed, 274 insertions(+), 195 deletions(-) diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index 9437bf540c80..36399873cdc8 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -40,8 +40,8 @@ #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" +#include "backends/platform/android/jni.h" #include "backends/platform/android/android.h" -#include "backends/platform/android/asset-archive.h" const char *android_log_tag = "ScummVM"; @@ -98,7 +98,7 @@ static inline T scalef(T in, float numerator, float denominator) { return static_cast(in) * numerator / denominator; } -OSystem_Android::OSystem_Android(jobject am) : +OSystem_Android::OSystem_Android() : _screen_changeid(0), _force_redraw(false), _game_texture(0), @@ -112,7 +112,6 @@ OSystem_Android::OSystem_Android(jobject am) : _mixer(0), _timer(0), _fsFactory(new POSIXFilesystemFactory()), - _asset_archive(new AndroidAssetArchive(am)), _shake_offset(0), _event_queue_lock(createMutex()) { } @@ -124,42 +123,16 @@ OSystem_Android::~OSystem_Android() { delete _overlay_texture; delete _mouse_texture; - destroyScummVMSurface(); + JNI::destroySurface(); delete _savefile; delete _mixer; delete _timer; delete _fsFactory; - delete _asset_archive; deleteMutex(_event_queue_lock); } -bool OSystem_Android::initJavaHooks(JNIEnv *env) { - jclass cls = env->GetObjectClass(back_ptr); - -#define FIND_METHOD(name, signature) do { \ - MID_ ## name = env->GetMethodID(cls, #name, signature); \ - if (MID_ ## name == 0) \ - return false; \ - } while (0) - - FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V"); - FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V"); - FIND_METHOD(initBackend, "()V"); - FIND_METHOD(audioSampleRate, "()I"); - FIND_METHOD(showVirtualKeyboard, "(Z)V"); - FIND_METHOD(getSysArchives, "()[Ljava/lang/String;"); - FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;"); - FIND_METHOD(setupScummVMSurface, "()V"); - FIND_METHOD(destroyScummVMSurface, "()V"); - FIND_METHOD(swapBuffers, "()Z"); - -#undef FIND_METHOD - - return true; -} - void *OSystem_Android::timerThreadFunc(void *arg) { OSystem_Android *system = (OSystem_Android *)arg; DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer); @@ -183,8 +156,6 @@ void *OSystem_Android::timerThreadFunc(void *arg) { void OSystem_Android::initBackend() { ENTER(); - JNIEnv *env = JNI::getEnv(); - ConfMan.setInt("autosave_period", 0); ConfMan.setInt("FM_medium_quality", true); @@ -200,74 +171,23 @@ void OSystem_Android::initBackend() { gettimeofday(&_startTime, 0); - jint sample_rate = env->CallIntMethod(back_ptr, MID_audioSampleRate); - if (env->ExceptionCheck()) { - warning("Error finding audio sample rate - assuming 11025HZ"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - - sample_rate = 11025; - } - - _mixer = new Audio::MixerImpl(this, sample_rate); + _mixer = new Audio::MixerImpl(this, JNI::getAudioSampleRate()); _mixer->setReady(true); - env->CallVoidMethod(back_ptr, MID_initBackend); - - if (env->ExceptionCheck()) { - error("Error in Java initBackend"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } + JNI::initBackend(); _timer_thread_exit = false; pthread_create(&_timer_thread, 0, timerThreadFunc, this); OSystem::initBackend(); - setupScummVMSurface(); + setupSurface(); } void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const { ENTER(); - JNIEnv *env = JNI::getEnv(); - jobjectArray array = - (jobjectArray)env->CallObjectMethod(back_ptr, MID_getPluginDirectories); - - if (env->ExceptionCheck()) { - warning("Error finding plugin directories"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - - return; - } - - jsize size = env->GetArrayLength(array); - for (jsize i = 0; i < size; ++i) { - jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); - - if (path_obj == 0) - continue; - - const char *path = env->GetStringUTFChars(path_obj, 0); - if (path == 0) { - warning("Error getting string characters from plugin directory"); - - env->ExceptionClear(); - env->DeleteLocalRef(path_obj); - - continue; - } - - dirs.push_back(Common::FSNode(path)); - - env->ReleaseStringUTFChars(path_obj, path); - env->DeleteLocalRef(path_obj); - } + JNI::getPluginDirectories(dirs); } bool OSystem_Android::hasFeature(Feature f) { @@ -380,8 +300,8 @@ bool OSystem_Android::pollEvent(Common::Event &event) { case Common::EVENT_SCREEN_CHANGED: debug("EVENT_SCREEN_CHANGED"); _screen_changeid++; - destroyScummVMSurface(); - setupScummVMSurface(); + JNI::destroySurface(); + setupSurface(); break; default: break; @@ -475,49 +395,19 @@ void OSystem_Android::quit() { void OSystem_Android::setWindowCaption(const char *caption) { ENTER("%s", caption); - JNIEnv *env = JNI::getEnv(); - jstring java_caption = env->NewStringUTF(caption); - env->CallVoidMethod(back_ptr, MID_setWindowCaption, java_caption); - - if (env->ExceptionCheck()) { - warning("Failed to set window caption"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } - - env->DeleteLocalRef(java_caption); + JNI::setWindowCaption(caption); } void OSystem_Android::displayMessageOnOSD(const char *msg) { ENTER("%s", msg); - JNIEnv *env = JNI::getEnv(); - jstring java_msg = env->NewStringUTF(msg); - env->CallVoidMethod(back_ptr, MID_displayMessageOnOSD, java_msg); - - if (env->ExceptionCheck()) { - warning("Failed to display OSD message"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } - - env->DeleteLocalRef(java_msg); + JNI::displayMessageOnOSD(msg); } void OSystem_Android::showVirtualKeyboard(bool enable) { ENTER("%d", enable); - JNIEnv *env = JNI::getEnv(); - env->CallVoidMethod(back_ptr, MID_showVirtualKeyboard, enable); - - if (env->ExceptionCheck()) { - error("Error trying to show virtual keyboard"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } + JNI::showVirtualKeyboard(enable); } Common::SaveFileManager *OSystem_Android::getSavefileManager() { @@ -554,33 +444,9 @@ FilesystemFactory *OSystem_Android::getFilesystemFactory() { void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { - s.add("ASSET", _asset_archive, priority, false); - - JNIEnv *env = JNI::getEnv(); - jobjectArray array = - (jobjectArray)env->CallObjectMethod(back_ptr, MID_getSysArchives); - - if (env->ExceptionCheck()) { - warning("Error finding system archive path"); - - env->ExceptionDescribe(); - env->ExceptionClear(); + ENTER(""); - return; - } - - jsize size = env->GetArrayLength(array); - for (jsize i = 0; i < size; ++i) { - jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); - const char *path = env->GetStringUTFChars(path_obj, 0); - - if (path != 0) { - s.addDirectory(path, path, priority); - env->ReleaseStringUTFChars(path_obj, path); - } - - env->DeleteLocalRef(path_obj); - } + JNI::addSysArchivesToSearchSet(s, priority); } void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) { diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index 0ccf57e7c16e..8fc138d42b47 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -36,12 +36,10 @@ #include "backends/plugins/posix/posix-provider.h" #include "backends/fs/posix/posix-fs-factory.h" -#include "backends/platform/android/jni.h" #include "backends/platform/android/texture.h" #include -#include #include #include @@ -79,9 +77,6 @@ extern void checkGlError(const char *expr, const char *file, int line); #define GLCALL(x) do { (x); } while (false) #endif -// back pointer to (java) peer instance -extern jobject back_ptr; - #ifdef DYNAMIC_MODULES class AndroidPluginProvider : public POSIXPluginProvider { protected: @@ -91,17 +86,6 @@ class AndroidPluginProvider : public POSIXPluginProvider { class OSystem_Android : public BaseBackend, public PaletteManager { private: - jmethodID MID_displayMessageOnOSD; - jmethodID MID_setWindowCaption; - jmethodID MID_initBackend; - jmethodID MID_audioSampleRate; - jmethodID MID_showVirtualKeyboard; - jmethodID MID_getSysArchives; - jmethodID MID_getPluginDirectories; - jmethodID MID_setupScummVMSurface; - jmethodID MID_destroyScummVMSurface; - jmethodID MID_swapBuffers; - int _screen_changeid; int _egl_surface_width; int _egl_surface_height; @@ -138,18 +122,15 @@ class OSystem_Android : public BaseBackend, public PaletteManager { Audio::MixerImpl *_mixer; Common::TimerManager *_timer; FilesystemFactory *_fsFactory; - Common::Archive *_asset_archive; timeval _startTime; - void setupScummVMSurface(); - void destroyScummVMSurface(); + void setupSurface(); void setupKeymapper(); void _setCursorPalette(const byte *colors, uint start, uint num); public: - OSystem_Android(jobject am); + OSystem_Android(); virtual ~OSystem_Android(); - bool initJavaHooks(JNIEnv *env); virtual void initBackend(); void addPluginDirectories(Common::FSList &dirs) const; diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h index 28e48426e9ad..6ec86e4cd0be 100644 --- a/backends/platform/android/asset-archive.h +++ b/backends/platform/android/asset-archive.h @@ -23,6 +23,9 @@ * */ +#ifndef _ANDROID_ASSET_H_ +#define _ANDROID_ASSET_H_ + #if defined(__ANDROID__) #include @@ -51,3 +54,5 @@ class AndroidAssetArchive : public Common::Archive { }; #endif +#endif + diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index 2370958d3071..838e5bc22345 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -26,6 +26,7 @@ #if defined(__ANDROID__) #include "backends/platform/android/android.h" +#include "backends/platform/android/jni.h" static inline GLfixed xdiv(int numerator, int denominator) { assert(numerator < (1 << 16)); @@ -47,11 +48,13 @@ int OSystem_Android::getDefaultGraphicsMode() const { bool OSystem_Android::setGraphicsMode(const char *mode) { ENTER("%s", mode); + return true; } bool OSystem_Android::setGraphicsMode(int mode) { ENTER("%d", mode); + return true; } @@ -59,13 +62,10 @@ int OSystem_Android::getGraphicsMode() const { return 1; } -void OSystem_Android::setupScummVMSurface() { +void OSystem_Android::setupSurface() { ENTER(); - JNIEnv *env = JNI::getEnv(); - env->CallVoidMethod(back_ptr, MID_setupScummVMSurface); - - if (env->ExceptionCheck()) + if (!JNI::setupSurface()) return; // EGL set up with a new surface. Initialise OpenGLES context. @@ -115,12 +115,6 @@ void OSystem_Android::setupScummVMSurface() { clearFocusRectangle(); } -void OSystem_Android::destroyScummVMSurface() { - JNIEnv *env = JNI::getEnv(); - env->CallVoidMethod(back_ptr, MID_destroyScummVMSurface); - // Can't use OpenGLES functions after this -} - void OSystem_Android::initSize(uint width, uint height, const Graphics::PixelFormat *format) { ENTER("%d, %d, %p", width, height, format); @@ -158,6 +152,7 @@ void OSystem_Android::setPalette(const byte *colors, uint start, uint num) { void OSystem_Android::grabPalette(byte *colors, uint start, uint num) { ENTER("%p, %u, %u", colors, start, num); + memcpy(colors, _game_texture->palette_const() + start * 3, num * 3); } @@ -261,11 +256,10 @@ void OSystem_Android::updateScreen() { GLCALL(glPopMatrix()); - JNIEnv *env = JNI::getEnv(); - if (!env->CallBooleanMethod(back_ptr, MID_swapBuffers)) { + if (!JNI::swapBuffers()) { // Context lost -> need to reinit GL - destroyScummVMSurface(); - setupScummVMSurface(); + JNI::destroySurface(); + setupSurface(); } } diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp index 4fa08ef7abd7..f24a60d48d2f 100644 --- a/backends/platform/android/jni.cpp +++ b/backends/platform/android/jni.cpp @@ -29,8 +29,8 @@ #include "common/config-manager.h" #include "backends/platform/android/android.h" - -jobject back_ptr; +#include "backends/platform/android/asset-archive.h" +#include "backends/platform/android/jni.h" __attribute__ ((visibility("default"))) jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { @@ -39,6 +39,8 @@ jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { JavaVM *JNI::_vm = 0; jobject JNI::_jobj = 0; + +Common::Archive *JNI::_asset_archive = 0; OSystem_Android *JNI::_system = 0; jfieldID JNI::_FID_Event_type = 0; @@ -51,6 +53,17 @@ jfieldID JNI::_FID_Event_mouse_y = 0; jfieldID JNI::_FID_Event_mouse_relative = 0; jfieldID JNI::_FID_ScummVM_nativeScummVM = 0; +jmethodID JNI::_MID_displayMessageOnOSD = 0; +jmethodID JNI::_MID_setWindowCaption = 0; +jmethodID JNI::_MID_initBackend = 0; +jmethodID JNI::_MID_audioSampleRate = 0; +jmethodID JNI::_MID_showVirtualKeyboard = 0; +jmethodID JNI::_MID_getSysArchives = 0; +jmethodID JNI::_MID_getPluginDirectories = 0; +jmethodID JNI::_MID_setupScummVMSurface = 0; +jmethodID JNI::_MID_destroyScummVMSurface = 0; +jmethodID JNI::_MID_swapBuffers = 0; + const JNINativeMethod JNI::_natives[] = { { "create", "(Landroid/content/res/AssetManager;)V", (void *)JNI::create }, @@ -179,21 +192,192 @@ void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) { env->DeleteLocalRef(cls); } +// calls to the dark side + +int JNI::getAudioSampleRate() { + JNIEnv *env = JNI::getEnv(); + + jint sample_rate = env->CallIntMethod(_jobj, _MID_audioSampleRate); + + if (env->ExceptionCheck()) { + warning("Error finding audio sample rate - assuming 11025HZ"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return 11025; + } + + return sample_rate; +} + +void JNI::initBackend() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj, _MID_initBackend); + + if (env->ExceptionCheck()) { + error("Error in Java initBackend"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + // TODO now what? + } +} + +void JNI::getPluginDirectories(Common::FSList &dirs) { + JNIEnv *env = JNI::getEnv(); + + jobjectArray array = + (jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories); + + if (env->ExceptionCheck()) { + warning("Error finding plugin directories"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return; + } + + jsize size = env->GetArrayLength(array); + for (jsize i = 0; i < size; ++i) { + jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); + + if (path_obj == 0) + continue; + + const char *path = env->GetStringUTFChars(path_obj, 0); + + if (path == 0) { + warning("Error getting string characters from plugin directory"); + + env->ExceptionClear(); + env->DeleteLocalRef(path_obj); + + continue; + } + + dirs.push_back(Common::FSNode(path)); + + env->ReleaseStringUTFChars(path_obj, path); + env->DeleteLocalRef(path_obj); + } +} + +void JNI::setWindowCaption(const char *caption) { + JNIEnv *env = JNI::getEnv(); + jstring java_caption = env->NewStringUTF(caption); + + env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption); + + if (env->ExceptionCheck()) { + warning("Failed to set window caption"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } + + env->DeleteLocalRef(java_caption); +} + +void JNI::displayMessageOnOSD(const char *msg) { + JNIEnv *env = JNI::getEnv(); + jstring java_msg = env->NewStringUTF(msg); + + env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg); + + if (env->ExceptionCheck()) { + warning("Failed to display OSD message"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } + + env->DeleteLocalRef(java_msg); +} + +void JNI::showVirtualKeyboard(bool enable) { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable); + + if (env->ExceptionCheck()) { + error("Error trying to show virtual keyboard"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + JNIEnv *env = JNI::getEnv(); + + s.add("ASSET", _asset_archive, priority, false); + + jobjectArray array = + (jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives); + + if (env->ExceptionCheck()) { + warning("Error finding system archive path"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return; + } + + jsize size = env->GetArrayLength(array); + for (jsize i = 0; i < size; ++i) { + jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); + const char *path = env->GetStringUTFChars(path_obj, 0); + + if (path != 0) { + s.addDirectory(path, path, priority); + env->ReleaseStringUTFChars(path_obj, path); + } + + env->DeleteLocalRef(path_obj); + } +} + +// natives for the dark side + void JNI::create(JNIEnv *env, jobject self, jobject am) { assert(!_system); - _system = new OSystem_Android(am); + _asset_archive = new AndroidAssetArchive(am); + assert(_asset_archive); + + _system = new OSystem_Android(); assert(_system); // weak global ref to allow class to be unloaded // ... except dalvik implements NewWeakGlobalRef only on froyo //_jobj = env->NewWeakGlobalRef(self); _jobj = env->NewGlobalRef(self); - back_ptr = _jobj; - // Exception already thrown by initJavaHooks? - if (!_system->initJavaHooks(env)) - return; + jclass cls = env->GetObjectClass(_jobj); + +#define FIND_METHOD(name, signature) do { \ + _MID_ ## name = env->GetMethodID(cls, #name, signature); \ + if (_MID_ ## name == 0) \ + return; \ + } while (0) + + FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V"); + FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V"); + FIND_METHOD(initBackend, "()V"); + FIND_METHOD(audioSampleRate, "()I"); + FIND_METHOD(showVirtualKeyboard, "(Z)V"); + FIND_METHOD(getSysArchives, "()[Ljava/lang/String;"); + FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;"); + FIND_METHOD(setupScummVMSurface, "()V"); + FIND_METHOD(destroyScummVMSurface, "()V"); + FIND_METHOD(swapBuffers, "()Z"); + +#undef FIND_METHOD env->SetLongField(self, _FID_ScummVM_nativeScummVM, (jlong)_system); @@ -208,6 +392,9 @@ void JNI::destroy(JNIEnv *env, jobject self) { _system = 0; delete tmp; + delete _asset_archive; + _asset_archive = 0; + // see above //JNI::getEnv()->DeleteWeakGlobalRef(_jobj); JNI::getEnv()->DeleteGlobalRef(_jobj); diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h index 39276b9388fb..02eabba5696e 100644 --- a/backends/platform/android/jni.h +++ b/backends/platform/android/jni.h @@ -30,11 +30,16 @@ #include -extern jobject back_ptr; +#include "common/fs.h" +#include "common/archive.h" class OSystem_Android; class JNI { +private: + JNI(); + virtual ~JNI(); + public: static jint onLoad(JavaVM *vm); @@ -43,14 +48,24 @@ class JNI { static void attachThread(); static void detachThread(); -private: - JNI(); - virtual ~JNI(); + static int getAudioSampleRate(); + static void initBackend(); + static void getPluginDirectories(Common::FSList &dirs); + static void setWindowCaption(const char *caption); + static void displayMessageOnOSD(const char *msg); + static void showVirtualKeyboard(bool enable); + static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); + + static inline bool setupSurface(); + static inline void destroySurface(); + static inline bool swapBuffers(); private: static JavaVM *_vm; // back pointer to (java) peer instance static jobject _jobj; + + static Common::Archive *_asset_archive; static OSystem_Android *_system; static jfieldID _FID_Event_type; @@ -63,6 +78,17 @@ class JNI { static jfieldID _FID_Event_mouse_relative; static jfieldID _FID_ScummVM_nativeScummVM; + static jmethodID _MID_displayMessageOnOSD; + static jmethodID _MID_setWindowCaption; + static jmethodID _MID_initBackend; + static jmethodID _MID_audioSampleRate; + static jmethodID _MID_showVirtualKeyboard; + static jmethodID _MID_getSysArchives; + static jmethodID _MID_getPluginDirectories; + static jmethodID _MID_setupScummVMSurface; + static jmethodID _MID_destroyScummVMSurface; + static jmethodID _MID_swapBuffers; + static const JNINativeMethod _natives[]; static void throwByName(JNIEnv *env, const char *name, const char *msg); @@ -82,6 +108,26 @@ class JNI { jint height); }; +inline bool JNI::setupSurface() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj, _MID_setupScummVMSurface); + + return !env->ExceptionCheck(); +} + +inline void JNI::destroySurface() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj, _MID_destroyScummVMSurface); +} + +inline bool JNI::swapBuffers() { + JNIEnv *env = JNI::getEnv(); + + return env->CallBooleanMethod(_jobj, _MID_swapBuffers); +} + #endif #endif