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