• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 "Input"
18 
19 #include "jni.h"
20 #include "JNIHelp.h"
21 #include <utils/misc.h>
22 #include <utils/Log.h>
23 
24 #include <ui/EventHub.h>
25 #include <utils/threads.h>
26 
27 #include <stdio.h>
28 
29 namespace android {
30 
31 // ----------------------------------------------------------------------------
32 
33 static struct input_offsets_t
34 {
35     jfieldID mMinValue;
36     jfieldID mMaxValue;
37     jfieldID mFlat;
38     jfieldID mFuzz;
39 
40     jfieldID mDeviceId;
41     jfieldID mType;
42     jfieldID mScancode;
43     jfieldID mKeycode;
44     jfieldID mFlags;
45     jfieldID mValue;
46     jfieldID mWhen;
47 } gInputOffsets;
48 
49 // ----------------------------------------------------------------------------
50 
51 static Mutex gLock;
52 static sp<EventHub> gHub;
53 
54 static jboolean
android_server_KeyInputQueue_readEvent(JNIEnv * env,jobject clazz,jobject event)55 android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz,
56                                           jobject event)
57 {
58     gLock.lock();
59     sp<EventHub> hub = gHub;
60     if (hub == NULL) {
61         hub = new EventHub;
62         gHub = hub;
63     }
64     gLock.unlock();
65 
66     int32_t deviceId;
67     int32_t type;
68     int32_t scancode, keycode;
69     uint32_t flags;
70     int32_t value;
71     nsecs_t when;
72     bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode,
73             &flags, &value, &when);
74 
75     env->SetIntField(event, gInputOffsets.mDeviceId, (jint)deviceId);
76     env->SetIntField(event, gInputOffsets.mType, (jint)type);
77     env->SetIntField(event, gInputOffsets.mScancode, (jint)scancode);
78     env->SetIntField(event, gInputOffsets.mKeycode, (jint)keycode);
79     env->SetIntField(event, gInputOffsets.mFlags, (jint)flags);
80     env->SetIntField(event, gInputOffsets.mValue, value);
81     env->SetLongField(event, gInputOffsets.mWhen,
82                         (jlong)(nanoseconds_to_milliseconds(when)));
83 
84     return res;
85 }
86 
87 static jint
android_server_KeyInputQueue_getDeviceClasses(JNIEnv * env,jobject clazz,jint deviceId)88 android_server_KeyInputQueue_getDeviceClasses(JNIEnv* env, jobject clazz,
89                                               jint deviceId)
90 {
91     jint classes = 0;
92     gLock.lock();
93     if (gHub != NULL) classes = gHub->getDeviceClasses(deviceId);
94     gLock.unlock();
95     return classes;
96 }
97 
98 static jstring
android_server_KeyInputQueue_getDeviceName(JNIEnv * env,jobject clazz,jint deviceId)99 android_server_KeyInputQueue_getDeviceName(JNIEnv* env, jobject clazz,
100                                               jint deviceId)
101 {
102     String8 name;
103     gLock.lock();
104     if (gHub != NULL) name = gHub->getDeviceName(deviceId);
105     gLock.unlock();
106 
107     if (name.size() > 0) {
108         return env->NewStringUTF(name.string());
109     }
110     return NULL;
111 }
112 
113 static void
android_server_KeyInputQueue_addExcludedDevice(JNIEnv * env,jobject clazz,jstring deviceName)114 android_server_KeyInputQueue_addExcludedDevice(JNIEnv* env, jobject clazz,
115                                               jstring deviceName)
116 {
117     gLock.lock();
118     sp<EventHub> hub = gHub;
119     if (hub == NULL) {
120         hub = new EventHub;
121         gHub = hub;
122     }
123     gLock.unlock();
124 
125     const char* nameStr = env->GetStringUTFChars(deviceName, NULL);
126     gHub->addExcludedDevice(nameStr);
127     env->ReleaseStringUTFChars(deviceName, nameStr);
128 }
129 
130 static jboolean
android_server_KeyInputQueue_getAbsoluteInfo(JNIEnv * env,jobject clazz,jint deviceId,jint axis,jobject info)131 android_server_KeyInputQueue_getAbsoluteInfo(JNIEnv* env, jobject clazz,
132                                              jint deviceId, jint axis,
133                                              jobject info)
134 {
135     int32_t minValue, maxValue, flat, fuzz;
136     int res = -1;
137     gLock.lock();
138     if (gHub != NULL) {
139         res = gHub->getAbsoluteInfo(deviceId, axis,
140                 &minValue, &maxValue, &flat, &fuzz);
141     }
142     gLock.unlock();
143 
144     if (res < 0) return JNI_FALSE;
145 
146     env->SetIntField(info, gInputOffsets.mMinValue, (jint)minValue);
147     env->SetIntField(info, gInputOffsets.mMaxValue, (jint)maxValue);
148     env->SetIntField(info, gInputOffsets.mFlat, (jint)flat);
149     env->SetIntField(info, gInputOffsets.mFuzz, (jint)fuzz);
150     return JNI_TRUE;
151 }
152 
153 static jint
android_server_KeyInputQueue_getSwitchState(JNIEnv * env,jobject clazz,jint sw)154 android_server_KeyInputQueue_getSwitchState(JNIEnv* env, jobject clazz,
155                                            jint sw)
156 {
157     jint st = -1;
158     gLock.lock();
159     if (gHub != NULL) st = gHub->getSwitchState(sw);
160     gLock.unlock();
161 
162     return st;
163 }
164 
165 static jint
android_server_KeyInputQueue_getSwitchStateDevice(JNIEnv * env,jobject clazz,jint deviceId,jint sw)166 android_server_KeyInputQueue_getSwitchStateDevice(JNIEnv* env, jobject clazz,
167                                             jint deviceId, jint sw)
168 {
169     jint st = -1;
170     gLock.lock();
171     if (gHub != NULL) st = gHub->getSwitchState(deviceId, sw);
172     gLock.unlock();
173 
174     return st;
175 }
176 
177 static jint
android_server_KeyInputQueue_getScancodeState(JNIEnv * env,jobject clazz,jint sw)178 android_server_KeyInputQueue_getScancodeState(JNIEnv* env, jobject clazz,
179                                            jint sw)
180 {
181     jint st = -1;
182     gLock.lock();
183     if (gHub != NULL) st = gHub->getScancodeState(sw);
184     gLock.unlock();
185 
186     return st;
187 }
188 
189 static jint
android_server_KeyInputQueue_getScancodeStateDevice(JNIEnv * env,jobject clazz,jint deviceId,jint sw)190 android_server_KeyInputQueue_getScancodeStateDevice(JNIEnv* env, jobject clazz,
191                                             jint deviceId, jint sw)
192 {
193     jint st = -1;
194     gLock.lock();
195     if (gHub != NULL) st = gHub->getScancodeState(deviceId, sw);
196     gLock.unlock();
197 
198     return st;
199 }
200 
201 static jint
android_server_KeyInputQueue_getKeycodeState(JNIEnv * env,jobject clazz,jint sw)202 android_server_KeyInputQueue_getKeycodeState(JNIEnv* env, jobject clazz,
203                                            jint sw)
204 {
205     jint st = -1;
206     gLock.lock();
207     if (gHub != NULL) st = gHub->getKeycodeState(sw);
208     gLock.unlock();
209 
210     return st;
211 }
212 
213 static jint
android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv * env,jobject clazz,jint deviceId,jint sw)214 android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv* env, jobject clazz,
215                                             jint deviceId, jint sw)
216 {
217     jint st = -1;
218     gLock.lock();
219     if (gHub != NULL) st = gHub->getKeycodeState(deviceId, sw);
220     gLock.unlock();
221 
222     return st;
223 }
224 
225 static jint
android_server_KeyInputQueue_scancodeToKeycode(JNIEnv * env,jobject clazz,jint deviceId,jint scancode)226 android_server_KeyInputQueue_scancodeToKeycode(JNIEnv* env, jobject clazz,
227                                             jint deviceId, jint scancode)
228 {
229     jint res = 0;
230     gLock.lock();
231     if (gHub != NULL) {
232         int32_t keycode;
233         uint32_t flags;
234         gHub->scancodeToKeycode(deviceId, scancode, &keycode, &flags);
235         res = keycode;
236     }
237     gLock.unlock();
238 
239     return res;
240 }
241 
242 static jboolean
android_server_KeyInputQueue_hasKeys(JNIEnv * env,jobject clazz,jintArray keyCodes,jbooleanArray outFlags)243 android_server_KeyInputQueue_hasKeys(JNIEnv* env, jobject clazz,
244                                      jintArray keyCodes, jbooleanArray outFlags)
245 {
246     jboolean ret = JNI_FALSE;
247 
248     int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
249     uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
250     size_t numCodes = env->GetArrayLength(keyCodes);
251     if (numCodes == env->GetArrayLength(outFlags)) {
252         gLock.lock();
253         if (gHub != NULL) ret = gHub->hasKeys(numCodes, codes, flags);
254         gLock.unlock();
255     }
256 
257     env->ReleaseBooleanArrayElements(outFlags, flags, 0);
258     env->ReleaseIntArrayElements(keyCodes, codes, 0);
259     return ret;
260 }
261 
262 // ----------------------------------------------------------------------------
263 
264 /*
265  * JNI registration.
266  */
267 static JNINativeMethod gInputMethods[] = {
268     /* name, signature, funcPtr */
269     { "readEvent",       "(Landroid/view/RawInputEvent;)Z",
270             (void*) android_server_KeyInputQueue_readEvent },
271     { "getDeviceClasses", "(I)I",
272         (void*) android_server_KeyInputQueue_getDeviceClasses },
273     { "getDeviceName", "(I)Ljava/lang/String;",
274         (void*) android_server_KeyInputQueue_getDeviceName },
275     { "addExcludedDevice", "(Ljava/lang/String;)V",
276         (void*) android_server_KeyInputQueue_addExcludedDevice },
277     { "getAbsoluteInfo", "(IILcom/android/server/InputDevice$AbsoluteInfo;)Z",
278         (void*) android_server_KeyInputQueue_getAbsoluteInfo },
279     { "getSwitchState", "(I)I",
280         (void*) android_server_KeyInputQueue_getSwitchState },
281     { "getSwitchState", "(II)I",
282         (void*) android_server_KeyInputQueue_getSwitchStateDevice },
283     { "nativeGetScancodeState", "(I)I",
284         (void*) android_server_KeyInputQueue_getScancodeState },
285     { "nativeGetScancodeState", "(II)I",
286         (void*) android_server_KeyInputQueue_getScancodeStateDevice },
287     { "nativeGetKeycodeState", "(I)I",
288         (void*) android_server_KeyInputQueue_getKeycodeState },
289     { "nativeGetKeycodeState", "(II)I",
290         (void*) android_server_KeyInputQueue_getKeycodeStateDevice },
291     { "hasKeys", "([I[Z)Z",
292         (void*) android_server_KeyInputQueue_hasKeys },
293     { "scancodeToKeycode", "(II)I",
294         (void*) android_server_KeyInputQueue_scancodeToKeycode },
295 };
296 
register_android_server_KeyInputQueue(JNIEnv * env)297 int register_android_server_KeyInputQueue(JNIEnv* env)
298 {
299     jclass input = env->FindClass("com/android/server/KeyInputQueue");
300     LOG_FATAL_IF(input == NULL, "Unable to find class com/android/server/KeyInputQueue");
301     int res = jniRegisterNativeMethods(env, "com/android/server/KeyInputQueue",
302                                         gInputMethods, NELEM(gInputMethods));
303 
304     jclass absoluteInfo = env->FindClass("com/android/server/InputDevice$AbsoluteInfo");
305     LOG_FATAL_IF(absoluteInfo == NULL, "Unable to find class com/android/server/InputDevice$AbsoluteInfo");
306 
307     gInputOffsets.mMinValue
308         = env->GetFieldID(absoluteInfo, "minValue", "I");
309     LOG_FATAL_IF(gInputOffsets.mMinValue == NULL, "Unable to find InputDevice.AbsoluteInfo.minValue");
310 
311     gInputOffsets.mMaxValue
312         = env->GetFieldID(absoluteInfo, "maxValue", "I");
313     LOG_FATAL_IF(gInputOffsets.mMaxValue == NULL, "Unable to find InputDevice.AbsoluteInfo.maxValue");
314 
315     gInputOffsets.mFlat
316         = env->GetFieldID(absoluteInfo, "flat", "I");
317     LOG_FATAL_IF(gInputOffsets.mFlat == NULL, "Unable to find InputDevice.AbsoluteInfo.flat");
318 
319     gInputOffsets.mFuzz
320         = env->GetFieldID(absoluteInfo, "fuzz", "I");
321     LOG_FATAL_IF(gInputOffsets.mFuzz == NULL, "Unable to find InputDevice.AbsoluteInfo.fuzz");
322 
323     jclass inputEvent = env->FindClass("android/view/RawInputEvent");
324     LOG_FATAL_IF(inputEvent == NULL, "Unable to find class android/view/RawInputEvent");
325 
326     gInputOffsets.mDeviceId
327         = env->GetFieldID(inputEvent, "deviceId", "I");
328     LOG_FATAL_IF(gInputOffsets.mDeviceId == NULL, "Unable to find RawInputEvent.deviceId");
329 
330     gInputOffsets.mType
331         = env->GetFieldID(inputEvent, "type", "I");
332     LOG_FATAL_IF(gInputOffsets.mType == NULL, "Unable to find RawInputEvent.type");
333 
334     gInputOffsets.mScancode
335         = env->GetFieldID(inputEvent, "scancode", "I");
336     LOG_FATAL_IF(gInputOffsets.mScancode == NULL, "Unable to find RawInputEvent.scancode");
337 
338     gInputOffsets.mKeycode
339         = env->GetFieldID(inputEvent, "keycode", "I");
340     LOG_FATAL_IF(gInputOffsets.mKeycode == NULL, "Unable to find RawInputEvent.keycode");
341 
342     gInputOffsets.mFlags
343         = env->GetFieldID(inputEvent, "flags", "I");
344     LOG_FATAL_IF(gInputOffsets.mFlags == NULL, "Unable to find RawInputEvent.flags");
345 
346     gInputOffsets.mValue
347         = env->GetFieldID(inputEvent, "value", "I");
348     LOG_FATAL_IF(gInputOffsets.mValue == NULL, "Unable to find RawInputEvent.value");
349 
350     gInputOffsets.mWhen
351         = env->GetFieldID(inputEvent, "when", "J");
352     LOG_FATAL_IF(gInputOffsets.mWhen == NULL, "Unable to find RawInputEvent.when");
353 
354     return res;
355 }
356 
357 }; // namespace android
358 
359