diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-06-30 15:32:54 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-06-30 15:32:54 -0700 |
commit | 7f6c6e8ffa3c6e036bf8037012a930e52f54e296 (patch) | |
tree | 1b3319e049eaf96e5783350e33894d830f41e6e4 /core/jni | |
parent | b2d1a71bcc7d40f2a6ca06ddcc92e3cd2a135d1e (diff) | |
parent | 3c80a4a044865bdf1289c7896baffa1c082d835c (diff) | |
download | frameworks_base-7f6c6e8ffa3c6e036bf8037012a930e52f54e296.zip frameworks_base-7f6c6e8ffa3c6e036bf8037012a930e52f54e296.tar.gz frameworks_base-7f6c6e8ffa3c6e036bf8037012a930e52f54e296.tar.bz2 |
am 3c80a4a0: Implement default key handling for native code.
Merge commit '3c80a4a044865bdf1289c7896baffa1c082d835c' into gingerbread-plus-aosp
* commit '3c80a4a044865bdf1289c7896baffa1c082d835c':
Implement default key handling for native code.
Diffstat (limited to 'core/jni')
-rw-r--r-- | core/jni/android_app_NativeActivity.cpp | 137 | ||||
-rw-r--r-- | core/jni/android_view_KeyEvent.cpp | 23 |
2 files changed, 144 insertions, 16 deletions
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp index a22b353..dd59d63 100644 --- a/core/jni/android_app_NativeActivity.cpp +++ b/core/jni/android_app_NativeActivity.cpp @@ -17,17 +17,63 @@ #define LOG_TAG "NativeActivity" #include <utils/Log.h> -#include "JNIHelp.h" -#include "android_view_InputChannel.h" +#include <poll.h> +#include <dlfcn.h> + #include <android_runtime/AndroidRuntime.h> #include <android/native_activity.h> #include <ui/InputTransport.h> +#include <utils/PollLoop.h> -#include <dlfcn.h> +#include "JNIHelp.h" +#include "android_os_MessageQueue.h" +#include "android_view_InputChannel.h" +#include "android_view_KeyEvent.h" namespace android { +static struct { + jclass clazz; + + jmethodID dispatchUnhandledKeyEvent; +} gNativeActivityClassInfo; + +struct MyInputQueue : AInputQueue { + explicit MyInputQueue(const android::sp<android::InputChannel>& channel, int workWrite) + : AInputQueue(channel), mWorkWrite(workWrite) { + } + + virtual void doDefaultKey(android::KeyEvent* keyEvent) { + mLock.lock(); + LOGI("Default key: pending=%d write=%d\n", mPendingKeys.size(), mWorkWrite); + if (mPendingKeys.size() <= 0 && mWorkWrite >= 0) { + int8_t cmd = 1; + write(mWorkWrite, &cmd, sizeof(cmd)); + } + mPendingKeys.add(keyEvent); + mLock.unlock(); + } + + KeyEvent* getNextEvent() { + KeyEvent* event = NULL; + + mLock.lock(); + if (mPendingKeys.size() > 0) { + event = mPendingKeys[0]; + mPendingKeys.removeAt(0); + } + mLock.unlock(); + + return event; + } + + int mWorkWrite; + + Mutex mLock; + Vector<KeyEvent*> mPendingKeys; +}; + struct NativeCode { NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) { memset(&activity, sizeof(activity), 0); @@ -37,14 +83,26 @@ struct NativeCode { surface = NULL; inputChannel = NULL; nativeInputQueue = NULL; + mainWorkRead = mainWorkWrite = -1; } ~NativeCode() { + if (activity.env != NULL && activity.clazz != NULL) { + activity.env->DeleteGlobalRef(activity.clazz); + } + if (pollLoop != NULL && mainWorkRead >= 0) { + pollLoop->removeCallback(mainWorkRead); + } + if (nativeInputQueue != NULL) { + nativeInputQueue->mWorkWrite = -1; + } setSurface(NULL); setInputChannel(NULL); if (callbacks.onDestroy != NULL) { callbacks.onDestroy(&activity); } + if (mainWorkRead >= 0) close(mainWorkRead); + if (mainWorkWrite >= 0) close(mainWorkWrite); if (dlhandle != NULL) { dlclose(dlhandle); } @@ -73,7 +131,7 @@ struct NativeCode { sp<InputChannel> ic = android_view_InputChannel_getInputChannel(activity.env, _channel); if (ic != NULL) { - nativeInputQueue = new AInputQueue(ic); + nativeInputQueue = new MyInputQueue(ic, mainWorkWrite); if (nativeInputQueue->getConsumer().initialize() != android::OK) { delete nativeInputQueue; nativeInputQueue = NULL; @@ -94,11 +152,36 @@ struct NativeCode { jobject surface; jobject inputChannel; - struct AInputQueue* nativeInputQueue; + struct MyInputQueue* nativeInputQueue; + + // These are used to wake up the main thread to process work. + int mainWorkRead; + int mainWorkWrite; + sp<PollLoop> pollLoop; }; +static bool mainWorkCallback(int fd, int events, void* data) { + NativeCode* code = (NativeCode*)data; + if ((events & POLLIN) != 0) { + KeyEvent* keyEvent; + while ((keyEvent=code->nativeInputQueue->getNextEvent()) != NULL) { + jobject inputEventObj = android_view_KeyEvent_fromNative( + code->activity.env, keyEvent); + code->activity.env->CallVoidMethod(code->activity.clazz, + gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj); + int32_t res = code->nativeInputQueue->getConsumer().sendFinishedSignal(); + if (res != OK) { + LOGW("Failed to send finished signal on channel '%s'. status=%d", + code->nativeInputQueue->getConsumer().getChannel()->getName().string(), res); + } + } + } + + return true; +} + static jint -loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path) +loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQueue) { const char* pathStr = env->GetStringUTFChars(path, NULL); NativeCode* code = NULL; @@ -115,6 +198,24 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path) delete code; return 0; } + + code->pollLoop = android_os_MessageQueue_getPollLoop(env, messageQueue); + if (code->pollLoop == NULL) { + LOGW("Unable to retrieve MessageQueue's PollLoop"); + delete code; + return 0; + } + + int msgpipe[2]; + if (pipe(msgpipe)) { + LOGW("could not create pipe: %s", strerror(errno)); + delete code; + return 0; + } + code->mainWorkRead = msgpipe[0]; + code->mainWorkWrite = msgpipe[1]; + code->pollLoop->setCallback(code->mainWorkRead, POLLIN, mainWorkCallback, code); + code->activity.callbacks = &code->callbacks; if (env->GetJavaVM(&code->activity.vm) < 0) { LOGW("NativeActivity GetJavaVM failed"); @@ -122,7 +223,7 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path) return 0; } code->activity.env = env; - code->activity.clazz = clazz; + code->activity.clazz = env->NewGlobalRef(clazz); code->createActivityFunc(&code->activity, NULL, 0); } @@ -288,7 +389,7 @@ onInputChannelDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject } static const JNINativeMethod g_methods[] = { - { "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native }, + { "loadNativeCode", "(Ljava/lang/String;Landroid/os/MessageQueue;)I", (void*)loadNativeCode_native }, { "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native }, { "onStartNative", "(I)V", (void*)onStart_native }, { "onResumeNative", "(I)V", (void*)onResume_native }, @@ -306,15 +407,25 @@ static const JNINativeMethod g_methods[] = { static const char* const kNativeActivityPathName = "android/app/NativeActivity"; +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(! var, "Unable to find class " className); \ + var = jclass(env->NewGlobalRef(var)); + +#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ + var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find method" methodName); + int register_android_app_NativeActivity(JNIEnv* env) { //LOGD("register_android_app_NativeActivity"); - jclass clazz; - - clazz = env->FindClass(kNativeActivityPathName); - LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity"); - + FIND_CLASS(gNativeActivityClassInfo.clazz, kNativeActivityPathName); + + GET_METHOD_ID(gNativeActivityClassInfo.dispatchUnhandledKeyEvent, + gNativeActivityClassInfo.clazz, + "dispatchUnhandledKeyEvent", "(Landroid/view/KeyEvent;)V"); + return AndroidRuntime::registerNativeMethods( env, kNativeActivityPathName, g_methods, NELEM(g_methods)); diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp index df3b952..8f648f4 100644 --- a/core/jni/android_view_KeyEvent.cpp +++ b/core/jni/android_view_KeyEvent.cpp @@ -76,8 +76,23 @@ void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, int32_t natur milliseconds_to_nanoseconds(eventTime)); } +static jboolean native_isSystemKey(JNIEnv* env, jobject clazz, jint keyCode) { + return KeyEvent::isSystemKey(keyCode); +} + +static jboolean native_hasDefaultAction(JNIEnv* env, jobject clazz, jint keyCode) { + return KeyEvent::hasDefaultAction(keyCode); +} + // ---------------------------------------------------------------------------- +static const JNINativeMethod g_methods[] = { + { "native_isSystemKey", "(I)Z", (void*)native_isSystemKey }, + { "native_hasDefaultAction", "(I)Z", (void*)native_hasDefaultAction }, +}; + +static const char* const kKeyEventPathName = "android/view/KeyEvent"; + #define FIND_CLASS(var, className) \ var = env->FindClass(className); \ LOG_FATAL_IF(! var, "Unable to find class " className); \ @@ -92,8 +107,8 @@ void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, int32_t natur LOG_FATAL_IF(! var, "Unable to find field " fieldName); int register_android_view_KeyEvent(JNIEnv* env) { - FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); - + FIND_CLASS(gKeyEventClassInfo.clazz, kKeyEventPathName); + GET_METHOD_ID(gKeyEventClassInfo.ctor, gKeyEventClassInfo.clazz, "<init>", "(JJIIIIIII)V"); @@ -118,7 +133,9 @@ int register_android_view_KeyEvent(JNIEnv* env) { GET_FIELD_ID(gKeyEventClassInfo.mCharacters, gKeyEventClassInfo.clazz, "mCharacters", "Ljava/lang/String;"); - return 0; + return AndroidRuntime::registerNativeMethods( + env, kKeyEventPathName, + g_methods, NELEM(g_methods)); } } // namespace android |