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 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 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 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 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 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 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 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 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 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 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 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 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 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 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