Home | History | Annotate | Download | only in jni
      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