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 <nativehelper/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 <nativehelper/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 mDisplayId;
43     jfieldID mMetaState;
44     jfieldID mAction;
45     jfieldID mKeyCode;
46     jfieldID mScanCode;
47     jfieldID mRepeatCount;
48     jfieldID mFlags;
49     jfieldID mDownTime;
50     jfieldID mEventTime;
51     jfieldID mCharacters;
52 } gKeyEventClassInfo;
53 
54 // ----------------------------------------------------------------------------
55 
android_view_KeyEvent_fromNative(JNIEnv * env,const KeyEvent * event)56 jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
57     jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
58             gKeyEventClassInfo.obtain,
59             nanoseconds_to_milliseconds(event->getDownTime()),
60             nanoseconds_to_milliseconds(event->getEventTime()),
61             event->getAction(),
62             event->getKeyCode(),
63             event->getRepeatCount(),
64             event->getMetaState(),
65             event->getDeviceId(),
66             event->getScanCode(),
67             event->getFlags(),
68             event->getSource(),
69             event->getDisplayId(),
70             NULL);
71     if (env->ExceptionCheck()) {
72         ALOGE("An exception occurred while obtaining a key event.");
73         LOGE_EX(env);
74         env->ExceptionClear();
75         return NULL;
76     }
77     return eventObj;
78 }
79 
android_view_KeyEvent_toNative(JNIEnv * env,jobject eventObj,KeyEvent * event)80 status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
81         KeyEvent* event) {
82     jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
83     jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
84     jint displayId = env->GetIntField(eventObj, gKeyEventClassInfo.mDisplayId);
85     jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
86     jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
87     jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
88     jint scanCode = env->GetIntField(eventObj, gKeyEventClassInfo.mScanCode);
89     jint repeatCount = env->GetIntField(eventObj, gKeyEventClassInfo.mRepeatCount);
90     jint flags = env->GetIntField(eventObj, gKeyEventClassInfo.mFlags);
91     jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
92     jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
93 
94     event->initialize(deviceId, source, displayId, action, flags, keyCode, scanCode, metaState,
95             repeatCount,
96             milliseconds_to_nanoseconds(downTime),
97             milliseconds_to_nanoseconds(eventTime));
98     return OK;
99 }
100 
android_view_KeyEvent_recycle(JNIEnv * env,jobject eventObj)101 status_t android_view_KeyEvent_recycle(JNIEnv* env, jobject eventObj) {
102     env->CallVoidMethod(eventObj, gKeyEventClassInfo.recycle);
103     if (env->ExceptionCheck()) {
104         ALOGW("An exception occurred while recycling a key event.");
105         LOGW_EX(env);
106         env->ExceptionClear();
107         return UNKNOWN_ERROR;
108     }
109     return OK;
110 }
111 
android_view_KeyEvent_nativeKeyCodeToString(JNIEnv * env,jobject clazz,jint keyCode)112 static jstring android_view_KeyEvent_nativeKeyCodeToString(JNIEnv* env, jobject clazz,
113         jint keyCode) {
114     return env->NewStringUTF(KeyEvent::getLabel(keyCode));
115 }
116 
android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv * env,jobject clazz,jstring label)117 static jint android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv* env, jobject clazz,
118         jstring label) {
119     ScopedUtfChars keyLabel(env, label);
120     return KeyEvent::getKeyCodeFromLabel(keyLabel.c_str());
121 }
122 
123 
124 // ----------------------------------------------------------------------------
125 
126 static const JNINativeMethod g_methods[] = {
127     { "nativeKeyCodeToString", "(I)Ljava/lang/String;",
128         (void*)android_view_KeyEvent_nativeKeyCodeToString},
129     { "nativeKeyCodeFromString", "(Ljava/lang/String;)I",
130         (void*)android_view_KeyEvent_nativeKeyCodeFromString},
131 };
132 
register_android_view_KeyEvent(JNIEnv * env)133 int register_android_view_KeyEvent(JNIEnv* env) {
134     jclass clazz = FindClassOrDie(env, "android/view/KeyEvent");
135     gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
136 
137     gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
138             "obtain", "(JJIIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
139     gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
140             "recycle", "()V");
141 
142     gKeyEventClassInfo.mDeviceId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDeviceId", "I");
143     gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
144     gKeyEventClassInfo.mDisplayId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDisplayId",
145                                                     "I");
146     gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
147                                                     "I");
148     gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
149     gKeyEventClassInfo.mKeyCode = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mKeyCode", "I");
150     gKeyEventClassInfo.mScanCode = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mScanCode", "I");
151     gKeyEventClassInfo.mRepeatCount = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mRepeatCount",
152                                                       "I");
153     gKeyEventClassInfo.mFlags = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mFlags", "I");
154     gKeyEventClassInfo.mDownTime = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDownTime", "J");
155     gKeyEventClassInfo.mEventTime = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mEventTime",
156                                                     "J");
157     gKeyEventClassInfo.mCharacters = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mCharacters",
158                                                      "Ljava/lang/String;");
159 
160     return RegisterMethodsOrDie(env, "android/view/KeyEvent", g_methods, NELEM(g_methods));
161 }
162 
163 } // namespace android
164