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>
2287eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include <android_runtime/Log.h>
2346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <utils/Log.h>
249d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <input/Input.h>
25337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright#include <ScopedUtfChars.h>
2646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_view_KeyEvent.h"
2746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
28987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe#include "core_jni_helpers.h"
29987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
3046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android {
3146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
3246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
3346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
3446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic struct {
3546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jclass clazz;
3646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
371f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    jmethodID obtain;
381f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    jmethodID recycle;
3946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
40c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jfieldID mDeviceId;
41c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jfieldID mSource;
4246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mMetaState;
4346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mAction;
4446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mKeyCode;
4546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mScanCode;
4646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mRepeatCount;
4746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mFlags;
4846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mDownTime;
4946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mEventTime;
5046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mCharacters;
5146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} gKeyEventClassInfo;
5246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
5346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
5446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
5546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownjobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
561f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
571f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            gKeyEventClassInfo.obtain,
5846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            nanoseconds_to_milliseconds(event->getDownTime()),
5946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            nanoseconds_to_milliseconds(event->getEventTime()),
6046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getAction(),
6146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getKeyCode(),
6246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getRepeatCount(),
6346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getMetaState(),
6446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getDeviceId(),
6546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            event->getScanCode(),
66c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown            event->getFlags(),
671f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            event->getSource(),
681f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            NULL);
691f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    if (env->ExceptionCheck()) {
703762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("An exception occurred while obtaining a key event.");
711f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOGE_EX(env);
721f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        env->ExceptionClear();
731f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        return NULL;
741f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    }
751f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    return eventObj;
7646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
7746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
781f2451007c660091b7b090c1ea332f9044515d2dJeff Brownstatus_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
7946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        KeyEvent* event) {
80c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
81c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
8246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
8346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
8446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
8546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint scanCode = env->GetIntField(eventObj, gKeyEventClassInfo.mScanCode);
8646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint repeatCount = env->GetIntField(eventObj, gKeyEventClassInfo.mRepeatCount);
8746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint flags = env->GetIntField(eventObj, gKeyEventClassInfo.mFlags);
8846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
8946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
9046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
91c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
9246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            milliseconds_to_nanoseconds(downTime),
9346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            milliseconds_to_nanoseconds(eventTime));
941f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    return OK;
951f2451007c660091b7b090c1ea332f9044515d2dJeff Brown}
961f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
971f2451007c660091b7b090c1ea332f9044515d2dJeff Brownstatus_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj) {
981f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    env->CallVoidMethod(eventObj, gKeyEventClassInfo.recycle);
991f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    if (env->ExceptionCheck()) {
1008564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("An exception occurred while recycling a key event.");
1011f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        LOGW_EX(env);
1021f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        env->ExceptionClear();
1031f2451007c660091b7b090c1ea332f9044515d2dJeff Brown        return UNKNOWN_ERROR;
1041f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    }
1051f2451007c660091b7b090c1ea332f9044515d2dJeff Brown    return OK;
10646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
10746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
108337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wrightstatic jstring android_view_KeyEvent_nativeKeyCodeToString(JNIEnv* env, jobject clazz,
109337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright        jint keyCode) {
110337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright    return env->NewStringUTF(KeyEvent::getLabel(keyCode));
1113c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1123c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
113337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wrightstatic jint android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv* env, jobject clazz,
114337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright        jstring label) {
115337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright    ScopedUtfChars keyLabel(env, label);
116337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright    return KeyEvent::getKeyCodeFromLabel(keyLabel.c_str());
1173c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1183c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1191f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
12046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
12146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1223c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornstatic const JNINativeMethod g_methods[] = {
123337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright    { "nativeKeyCodeToString", "(I)Ljava/lang/String;",
124337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright        (void*)android_view_KeyEvent_nativeKeyCodeToString},
125337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright    { "nativeKeyCodeFromString", "(Ljava/lang/String;)I",
126337d9d2edc262141f9b8f684e53aae5e47f0ae13Michael Wright        (void*)android_view_KeyEvent_nativeKeyCodeFromString},
1273c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn};
1283c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
12946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownint register_android_view_KeyEvent(JNIEnv* env) {
130987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    jclass clazz = FindClassOrDie(env, "android/view/KeyEvent");
131987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
1321f2451007c660091b7b090c1ea332f9044515d2dJeff Brown
133987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
1341f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            "obtain", "(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
135987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
1361f2451007c660091b7b090c1ea332f9044515d2dJeff Brown            "recycle", "()V");
13746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
138987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mDeviceId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDeviceId", "I");
139987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
140987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
141987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe                                                    "I");
142987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
143987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mKeyCode = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mKeyCode", "I");
144987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mScanCode = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mScanCode", "I");
145987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mRepeatCount = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mRepeatCount",
146987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe                                                      "I");
147987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mFlags = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mFlags", "I");
148987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mDownTime = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDownTime", "J");
149987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mEventTime = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mEventTime",
150987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe                                                    "J");
151987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gKeyEventClassInfo.mCharacters = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mCharacters",
152987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe                                                     "Ljava/lang/String;");
153987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
154987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    return RegisterMethodsOrDie(env, "android/view/KeyEvent", g_methods, NELEM(g_methods));
15546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
15646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
15746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android
158