| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "Input" |
| |
| #include "jni.h" |
| #include "JNIHelp.h" |
| #include <utils/misc.h> |
| #include <utils/Log.h> |
| |
| #include <ui/EventHub.h> |
| #include <utils/threads.h> |
| |
| #include <stdio.h> |
| |
| namespace android { |
| |
| // ---------------------------------------------------------------------------- |
| |
| static struct input_offsets_t |
| { |
| jfieldID mMinValue; |
| jfieldID mMaxValue; |
| jfieldID mFlat; |
| jfieldID mFuzz; |
| |
| jfieldID mDeviceId; |
| jfieldID mType; |
| jfieldID mScancode; |
| jfieldID mKeycode; |
| jfieldID mFlags; |
| jfieldID mValue; |
| jfieldID mWhen; |
| } gInputOffsets; |
| |
| // ---------------------------------------------------------------------------- |
| |
| static Mutex gLock; |
| static sp<EventHub> gHub; |
| |
| static jboolean |
| android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz, |
| jobject event) |
| { |
| gLock.lock(); |
| sp<EventHub> hub = gHub; |
| if (hub == NULL) { |
| hub = new EventHub; |
| gHub = hub; |
| } |
| gLock.unlock(); |
| |
| int32_t deviceId; |
| int32_t type; |
| int32_t scancode, keycode; |
| uint32_t flags; |
| int32_t value; |
| nsecs_t when; |
| bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode, |
| &flags, &value, &when); |
| |
| env->SetIntField(event, gInputOffsets.mDeviceId, (jint)deviceId); |
| env->SetIntField(event, gInputOffsets.mType, (jint)type); |
| env->SetIntField(event, gInputOffsets.mScancode, (jint)scancode); |
| env->SetIntField(event, gInputOffsets.mKeycode, (jint)keycode); |
| env->SetIntField(event, gInputOffsets.mFlags, (jint)flags); |
| env->SetIntField(event, gInputOffsets.mValue, value); |
| env->SetLongField(event, gInputOffsets.mWhen, |
| (jlong)(nanoseconds_to_milliseconds(when))); |
| |
| return res; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getDeviceClasses(JNIEnv* env, jobject clazz, |
| jint deviceId) |
| { |
| jint classes = 0; |
| gLock.lock(); |
| if (gHub != NULL) classes = gHub->getDeviceClasses(deviceId); |
| gLock.unlock(); |
| return classes; |
| } |
| |
| static jstring |
| android_server_KeyInputQueue_getDeviceName(JNIEnv* env, jobject clazz, |
| jint deviceId) |
| { |
| String8 name; |
| gLock.lock(); |
| if (gHub != NULL) name = gHub->getDeviceName(deviceId); |
| gLock.unlock(); |
| |
| if (name.size() > 0) { |
| return env->NewStringUTF(name.string()); |
| } |
| return NULL; |
| } |
| |
| static void |
| android_server_KeyInputQueue_addExcludedDevice(JNIEnv* env, jobject clazz, |
| jstring deviceName) |
| { |
| gLock.lock(); |
| sp<EventHub> hub = gHub; |
| if (hub == NULL) { |
| hub = new EventHub; |
| gHub = hub; |
| } |
| gLock.unlock(); |
| |
| const char* nameStr = env->GetStringUTFChars(deviceName, NULL); |
| gHub->addExcludedDevice(nameStr); |
| env->ReleaseStringUTFChars(deviceName, nameStr); |
| } |
| |
| static jboolean |
| android_server_KeyInputQueue_getAbsoluteInfo(JNIEnv* env, jobject clazz, |
| jint deviceId, jint axis, |
| jobject info) |
| { |
| int32_t minValue, maxValue, flat, fuzz; |
| int res = -1; |
| gLock.lock(); |
| if (gHub != NULL) { |
| res = gHub->getAbsoluteInfo(deviceId, axis, |
| &minValue, &maxValue, &flat, &fuzz); |
| } |
| gLock.unlock(); |
| |
| if (res < 0) return JNI_FALSE; |
| |
| env->SetIntField(info, gInputOffsets.mMinValue, (jint)minValue); |
| env->SetIntField(info, gInputOffsets.mMaxValue, (jint)maxValue); |
| env->SetIntField(info, gInputOffsets.mFlat, (jint)flat); |
| env->SetIntField(info, gInputOffsets.mFuzz, (jint)fuzz); |
| return JNI_TRUE; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getSwitchState(JNIEnv* env, jobject clazz, |
| jint sw) |
| { |
| jint st = -1; |
| gLock.lock(); |
| if (gHub != NULL) st = gHub->getSwitchState(sw); |
| gLock.unlock(); |
| |
| return st; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getSwitchStateDevice(JNIEnv* env, jobject clazz, |
| jint deviceId, jint sw) |
| { |
| jint st = -1; |
| gLock.lock(); |
| if (gHub != NULL) st = gHub->getSwitchState(deviceId, sw); |
| gLock.unlock(); |
| |
| return st; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getScancodeState(JNIEnv* env, jobject clazz, |
| jint sw) |
| { |
| jint st = -1; |
| gLock.lock(); |
| if (gHub != NULL) st = gHub->getScancodeState(sw); |
| gLock.unlock(); |
| |
| return st; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getScancodeStateDevice(JNIEnv* env, jobject clazz, |
| jint deviceId, jint sw) |
| { |
| jint st = -1; |
| gLock.lock(); |
| if (gHub != NULL) st = gHub->getScancodeState(deviceId, sw); |
| gLock.unlock(); |
| |
| return st; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getKeycodeState(JNIEnv* env, jobject clazz, |
| jint sw) |
| { |
| jint st = -1; |
| gLock.lock(); |
| if (gHub != NULL) st = gHub->getKeycodeState(sw); |
| gLock.unlock(); |
| |
| return st; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv* env, jobject clazz, |
| jint deviceId, jint sw) |
| { |
| jint st = -1; |
| gLock.lock(); |
| if (gHub != NULL) st = gHub->getKeycodeState(deviceId, sw); |
| gLock.unlock(); |
| |
| return st; |
| } |
| |
| static jint |
| android_server_KeyInputQueue_scancodeToKeycode(JNIEnv* env, jobject clazz, |
| jint deviceId, jint scancode) |
| { |
| jint res = 0; |
| gLock.lock(); |
| if (gHub != NULL) { |
| int32_t keycode; |
| uint32_t flags; |
| gHub->scancodeToKeycode(deviceId, scancode, &keycode, &flags); |
| res = keycode; |
| } |
| gLock.unlock(); |
| |
| return res; |
| } |
| |
| static jboolean |
| android_server_KeyInputQueue_hasKeys(JNIEnv* env, jobject clazz, |
| jintArray keyCodes, jbooleanArray outFlags) |
| { |
| jboolean ret = JNI_FALSE; |
| |
| int32_t* codes = env->GetIntArrayElements(keyCodes, NULL); |
| uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL); |
| size_t numCodes = env->GetArrayLength(keyCodes); |
| if (numCodes == env->GetArrayLength(outFlags)) { |
| gLock.lock(); |
| if (gHub != NULL) ret = gHub->hasKeys(numCodes, codes, flags); |
| gLock.unlock(); |
| } |
| |
| env->ReleaseBooleanArrayElements(outFlags, flags, 0); |
| env->ReleaseIntArrayElements(keyCodes, codes, 0); |
| return ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| /* |
| * JNI registration. |
| */ |
| static JNINativeMethod gInputMethods[] = { |
| /* name, signature, funcPtr */ |
| { "readEvent", "(Landroid/view/RawInputEvent;)Z", |
| (void*) android_server_KeyInputQueue_readEvent }, |
| { "getDeviceClasses", "(I)I", |
| (void*) android_server_KeyInputQueue_getDeviceClasses }, |
| { "getDeviceName", "(I)Ljava/lang/String;", |
| (void*) android_server_KeyInputQueue_getDeviceName }, |
| { "addExcludedDevice", "(Ljava/lang/String;)V", |
| (void*) android_server_KeyInputQueue_addExcludedDevice }, |
| { "getAbsoluteInfo", "(IILcom/android/server/InputDevice$AbsoluteInfo;)Z", |
| (void*) android_server_KeyInputQueue_getAbsoluteInfo }, |
| { "getSwitchState", "(I)I", |
| (void*) android_server_KeyInputQueue_getSwitchState }, |
| { "getSwitchState", "(II)I", |
| (void*) android_server_KeyInputQueue_getSwitchStateDevice }, |
| { "getScancodeState", "(I)I", |
| (void*) android_server_KeyInputQueue_getScancodeState }, |
| { "getScancodeState", "(II)I", |
| (void*) android_server_KeyInputQueue_getScancodeStateDevice }, |
| { "getKeycodeState", "(I)I", |
| (void*) android_server_KeyInputQueue_getKeycodeState }, |
| { "getKeycodeState", "(II)I", |
| (void*) android_server_KeyInputQueue_getKeycodeStateDevice }, |
| { "hasKeys", "([I[Z)Z", |
| (void*) android_server_KeyInputQueue_hasKeys }, |
| { "scancodeToKeycode", "(II)I", |
| (void*) android_server_KeyInputQueue_scancodeToKeycode }, |
| }; |
| |
| int register_android_server_KeyInputQueue(JNIEnv* env) |
| { |
| jclass input = env->FindClass("com/android/server/KeyInputQueue"); |
| LOG_FATAL_IF(input == NULL, "Unable to find class com/android/server/KeyInputQueue"); |
| int res = jniRegisterNativeMethods(env, "com/android/server/KeyInputQueue", |
| gInputMethods, NELEM(gInputMethods)); |
| |
| jclass absoluteInfo = env->FindClass("com/android/server/InputDevice$AbsoluteInfo"); |
| LOG_FATAL_IF(absoluteInfo == NULL, "Unable to find class com/android/server/InputDevice$AbsoluteInfo"); |
| |
| gInputOffsets.mMinValue |
| = env->GetFieldID(absoluteInfo, "minValue", "I"); |
| LOG_FATAL_IF(gInputOffsets.mMinValue == NULL, "Unable to find InputDevice.AbsoluteInfo.minValue"); |
| |
| gInputOffsets.mMaxValue |
| = env->GetFieldID(absoluteInfo, "maxValue", "I"); |
| LOG_FATAL_IF(gInputOffsets.mMaxValue == NULL, "Unable to find InputDevice.AbsoluteInfo.maxValue"); |
| |
| gInputOffsets.mFlat |
| = env->GetFieldID(absoluteInfo, "flat", "I"); |
| LOG_FATAL_IF(gInputOffsets.mFlat == NULL, "Unable to find InputDevice.AbsoluteInfo.flat"); |
| |
| gInputOffsets.mFuzz |
| = env->GetFieldID(absoluteInfo, "fuzz", "I"); |
| LOG_FATAL_IF(gInputOffsets.mFuzz == NULL, "Unable to find InputDevice.AbsoluteInfo.fuzz"); |
| |
| jclass inputEvent = env->FindClass("android/view/RawInputEvent"); |
| LOG_FATAL_IF(inputEvent == NULL, "Unable to find class android/view/RawInputEvent"); |
| |
| gInputOffsets.mDeviceId |
| = env->GetFieldID(inputEvent, "deviceId", "I"); |
| LOG_FATAL_IF(gInputOffsets.mDeviceId == NULL, "Unable to find RawInputEvent.deviceId"); |
| |
| gInputOffsets.mType |
| = env->GetFieldID(inputEvent, "type", "I"); |
| LOG_FATAL_IF(gInputOffsets.mType == NULL, "Unable to find RawInputEvent.type"); |
| |
| gInputOffsets.mScancode |
| = env->GetFieldID(inputEvent, "scancode", "I"); |
| LOG_FATAL_IF(gInputOffsets.mScancode == NULL, "Unable to find RawInputEvent.scancode"); |
| |
| gInputOffsets.mKeycode |
| = env->GetFieldID(inputEvent, "keycode", "I"); |
| LOG_FATAL_IF(gInputOffsets.mKeycode == NULL, "Unable to find RawInputEvent.keycode"); |
| |
| gInputOffsets.mFlags |
| = env->GetFieldID(inputEvent, "flags", "I"); |
| LOG_FATAL_IF(gInputOffsets.mFlags == NULL, "Unable to find RawInputEvent.flags"); |
| |
| gInputOffsets.mValue |
| = env->GetFieldID(inputEvent, "value", "I"); |
| LOG_FATAL_IF(gInputOffsets.mValue == NULL, "Unable to find RawInputEvent.value"); |
| |
| gInputOffsets.mWhen |
| = env->GetFieldID(inputEvent, "when", "J"); |
| LOG_FATAL_IF(gInputOffsets.mWhen == NULL, "Unable to find RawInputEvent.when"); |
| |
| return res; |
| } |
| |
| }; // namespace android |
| |