146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/*
246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Copyright (C) 2010 The Android Open Source Project
346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *
446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * you may not use this file except in compliance with the License.
646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * You may obtain a copy of the License at
746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *
846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *
1046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Unless required by applicable law or agreed to in writing, software
1146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * See the License for the specific language governing permissions and
1446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * limitations under the License.
1546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */
1646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define LOG_TAG "KeyEvent-JNI"
1846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "JNIHelp.h"
2046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <android_runtime/AndroidRuntime.h>
2246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <utils/Log.h>
2346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <ui/Input.h>
2446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_view_KeyEvent.h"
2546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android {
2746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
2946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
3046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic struct {
3146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jclass clazz;
3246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
331f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    jmethodID obtain;
341f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    jmethodID recycle;
3546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
36c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jfieldID mDeviceId;
37c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jfieldID mSource;
3846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mMetaState;
3946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mAction;
4046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mKeyCode;
4146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mScanCode;
4246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mRepeatCount;
4346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mFlags;
4446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mDownTime;
4546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mEventTime;
4646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mCharacters;
4746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} gKeyEventClassInfo;
4846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
4946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
5046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
5146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownjobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
521f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
531f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            gKeyEventClassInfo.obtain,
5446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            nanoseconds_to_milliseconds(event->getDownTime()),
5546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            nanoseconds_to_milliseconds(event->getEventTime()),
5646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getAction(),
5746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getKeyCode(),
5846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getRepeatCount(),
5946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getMetaState(),
6046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getDeviceId(),
6146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getScanCode(),
62c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown            event->getFlags(),
631f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            event->getSource(),
641f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            NULL);
651f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    if (env->ExceptionCheck()) {
661f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOGE("An exception occurred while obtaining a key event.");
671f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOGE_EX(env);
681f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        env->ExceptionClear();
691f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        return NULL;
701f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    }
711f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    return eventObj;
7246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
7346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
741f2451007c660091b7b090c1ea332f9044515d2dJeff Brownstatus_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
7546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        KeyEvent* event) {
76c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
77c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
7846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
7946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
8046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
8146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint scanCode = env->GetIntField(eventObj, gKeyEventClassInfo.mScanCode);
8246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint repeatCount = env->GetIntField(eventObj, gKeyEventClassInfo.mRepeatCount);
8346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint flags = env->GetIntField(eventObj, gKeyEventClassInfo.mFlags);
8446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
8546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
8646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
87c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
8846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            milliseconds_to_nanoseconds(downTime),
8946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            milliseconds_to_nanoseconds(eventTime));
901f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    return OK;
911f2451007c660091b7b090c1ea332f9044515d2dJeff Brown}
921f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
931f2451007c660091b7b090c1ea332f9044515d2dJeff Brownstatus_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj) {
941f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    env->CallVoidMethod(eventObj, gKeyEventClassInfo.recycle);
951f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    if (env->ExceptionCheck()) {
961f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOGW("An exception occurred while recycling a key event.");
971f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOGW_EX(env);
981f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        env->ExceptionClear();
991f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        return UNKNOWN_ERROR;
1001f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    }
1011f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    return OK;
10246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
10346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1043c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornstatic jboolean native_isSystemKey(JNIEnv* env, jobject clazz, jint keyCode) {
1053c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return KeyEvent::isSystemKey(keyCode);
1063c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1073c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1083c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornstatic jboolean native_hasDefaultAction(JNIEnv* env, jobject clazz, jint keyCode) {
1093c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return KeyEvent::hasDefaultAction(keyCode);
1103c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1113c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1121f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
11346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
11446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1153c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornstatic const JNINativeMethod g_methods[] = {
1163c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    { "native_isSystemKey", "(I)Z", (void*)native_isSystemKey },
1173c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    { "native_hasDefaultAction", "(I)Z", (void*)native_hasDefaultAction },
1183c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn};
1193c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
12046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define FIND_CLASS(var, className) \
12146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = env->FindClass(className); \
12246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
12346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = jclass(env->NewGlobalRef(var));
12446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1251f2451007c660091b7b090c1ea332f9044515d2dJeff Brown#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
1261f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
1271f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOG_FATAL_IF(! var, "Unable to find static method" methodName);
1281f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
12946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
13046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
13146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        LOG_FATAL_IF(! var, "Unable to find method" methodName);
13246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
13346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
13446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
13546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
13646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
13746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownint register_android_view_KeyEvent(JNIEnv* env) {
138c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
1391f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
1401f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    GET_STATIC_METHOD_ID(gKeyEventClassInfo.obtain, gKeyEventClassInfo.clazz,
1411f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            "obtain", "(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
1421f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    GET_METHOD_ID(gKeyEventClassInfo.recycle, gKeyEventClassInfo.clazz,
1431f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            "recycle", "()V");
14446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
145c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mDeviceId, gKeyEventClassInfo.clazz,
146c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown            "mDeviceId", "I");
147c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mSource, gKeyEventClassInfo.clazz,
148c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown            "mSource", "I");
14946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mMetaState, gKeyEventClassInfo.clazz,
15046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mMetaState", "I");
15146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mAction, gKeyEventClassInfo.clazz,
15246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mAction", "I");
15346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mKeyCode, gKeyEventClassInfo.clazz,
15446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mKeyCode", "I");
15546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mScanCode, gKeyEventClassInfo.clazz,
15646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mScanCode", "I");
15746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mRepeatCount, gKeyEventClassInfo.clazz,
15846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mRepeatCount", "I");
15946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mFlags, gKeyEventClassInfo.clazz,
16046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mFlags", "I");
16146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mDownTime, gKeyEventClassInfo.clazz,
16246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mDownTime", "J");
16346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mEventTime, gKeyEventClassInfo.clazz,
16446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mEventTime", "J");
16546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gKeyEventClassInfo.mCharacters, gKeyEventClassInfo.clazz,
16646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mCharacters", "Ljava/lang/String;");
16746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1683c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return AndroidRuntime::registerNativeMethods(
169c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown        env, "android/view/KeyEvent", g_methods, NELEM(g_methods));
17046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
17146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
17246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android
173