/* * 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 }, { "nativeGetScancodeState", "(I)I", (void*) android_server_KeyInputQueue_getScancodeState }, { "nativeGetScancodeState", "(II)I", (void*) android_server_KeyInputQueue_getScancodeStateDevice }, { "nativeGetKeycodeState", "(I)I", (void*) android_server_KeyInputQueue_getKeycodeState }, { "nativeGetKeycodeState", "(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