1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "KeyEvent-JNI"
18 
19 #include "JNIHelp.h"
20 
21 #include <android_runtime/AndroidRuntime.h>
22 #include <android_runtime/Log.h>
23 #include <utils/Log.h>
24 #include <input/Input.h>
25 #include <ScopedUtfChars.h>
26 #include "android_view_KeyEvent.h"
27 
28 #include "core_jni_helpers.h"
29 
30 namespace android {
31 
32 // ----------------------------------------------------------------------------
33 
34 static struct {
35     jclass clazz;
36 
37     jmethodID obtain;
38     jmethodID recycle;
39 
40     jfieldID mDeviceId;
41     jfieldID mSource;
42     jfieldID mMetaState;
43     jfieldID mAction;
44     jfieldID mKeyCode;
45     jfieldID mScanCode;
46     jfieldID mRepeatCount;
47     jfieldID mFlags;
48     jfieldID mDownTime;
49     jfieldID mEventTime;
50     jfieldID mCharacters;
51 } gKeyEventClassInfo;
52 
53 // ----------------------------------------------------------------------------
54 
android_view_KeyEvent_fromNative(JNIEnv * env,const KeyEvent * event)55 jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
56     jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
57             gKeyEventClassInfo.obtain,
58             nanoseconds_to_milliseconds(event->getDownTime()),
59             nanoseconds_to_milliseconds(event->getEventTime()),
60             event->getAction(),
61             event->getKeyCode(),
62             event->getRepeatCount(),
63             event->getMetaState(),
64             event->getDeviceId(),
65             event->getScanCode(),
66             event->getFlags(),
67             event->getSource(),
68             NULL);
69     if (env->ExceptionCheck()) {
70         ALOGE("An exception occurred while obtaining a key event.");
71         LOGE_EX(env);
72         env->ExceptionClear();
73         return NULL;
74     }
75     return eventObj;
76 }
77 
android_view_KeyEvent_toNative(JNIEnv * env,jobject eventObj,KeyEvent * event)78 status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
79         KeyEvent* event) {
80     jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
81     jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
82     jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
83     jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
84     jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
85     jint scanCode = env->GetIntField(eventObj, gKeyEventClassInfo.mScanCode);
86     jint repeatCount = env->GetIntField(eventObj, gKeyEventClassInfo.mRepeatCount);
87     jint flags = env->GetIntField(eventObj, gKeyEventClassInfo.mFlags);
88     jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
89     jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
90 
91     event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
92             milliseconds_to_nanoseconds(downTime),
93             milliseconds_to_nanoseconds(eventTime));
94     return OK;
95 }
96 
android_view_KeyEvent_recycle(JNIEnv * env,jobject eventObj)97 status_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj) {
98     env->CallVoidMethod(eventObj, gKeyEventClassInfo.recycle);
99     if (env->ExceptionCheck()) {
100         ALOGW("An exception occurred while recycling a key event.");
101         LOGW_EX(env);
102         env->ExceptionClear();
103         return UNKNOWN_ERROR;
104     }
105     return OK;
106 }
107 
android_view_KeyEvent_nativeKeyCodeToString(JNIEnv * env,jobject clazz,jint keyCode)108 static jstring android_view_KeyEvent_nativeKeyCodeToString(JNIEnv* env, jobject clazz,
109         jint keyCode) {
110     return env->NewStringUTF(KeyEvent::getLabel(keyCode));
111 }
112 
android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv * env,jobject clazz,jstring label)113 static jint android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv* env, jobject clazz,
114         jstring label) {
115     ScopedUtfChars keyLabel(env, label);
116     return KeyEvent::getKeyCodeFromLabel(keyLabel.c_str());
117 }
118 
119 
120 // ----------------------------------------------------------------------------
121 
122 static const JNINativeMethod g_methods[] = {
123     { "nativeKeyCodeToString", "(I)Ljava/lang/String;",
124         (void*)android_view_KeyEvent_nativeKeyCodeToString},
125     { "nativeKeyCodeFromString", "(Ljava/lang/String;)I",
126         (void*)android_view_KeyEvent_nativeKeyCodeFromString},
127 };
128 
register_android_view_KeyEvent(JNIEnv * env)129 int register_android_view_KeyEvent(JNIEnv* env) {
130     jclass clazz = FindClassOrDie(env, "android/view/KeyEvent");
131     gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
132 
133     gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
134             "obtain", "(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
135     gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
136             "recycle", "()V");
137 
138     gKeyEventClassInfo.mDeviceId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDeviceId", "I");
139     gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
140     gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
141                                                     "I");
142     gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
143     gKeyEventClassInfo.mKeyCode = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mKeyCode", "I");
144     gKeyEventClassInfo.mScanCode = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mScanCode", "I");
145     gKeyEventClassInfo.mRepeatCount = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mRepeatCount",
146                                                       "I");
147     gKeyEventClassInfo.mFlags = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mFlags", "I");
148     gKeyEventClassInfo.mDownTime = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDownTime", "J");
149     gKeyEventClassInfo.mEventTime = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mEventTime",
150                                                     "J");
151     gKeyEventClassInfo.mCharacters = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mCharacters",
152                                                      "Ljava/lang/String;");
153 
154     return RegisterMethodsOrDie(env, "android/view/KeyEvent", g_methods, NELEM(g_methods));
155 }
156 
157 } // namespace android
158