Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2006, 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 #include <android_runtime/AndroidRuntime.h>
     18 
     19 #include <input/KeyCharacterMap.h>
     20 #include <input/Input.h>
     21 #include <binder/Parcel.h>
     22 
     23 #include <nativehelper/jni.h>
     24 #include <nativehelper/JNIHelp.h>
     25 
     26 #include "android_os_Parcel.h"
     27 #include "android_view_KeyEvent.h"
     28 
     29 #include "core_jni_helpers.h"
     30 
     31 namespace android {
     32 
     33 static struct {
     34     jclass clazz;
     35     jmethodID ctor;
     36 } gKeyCharacterMapClassInfo;
     37 
     38 static struct {
     39     jclass clazz;
     40 } gKeyEventClassInfo;
     41 
     42 static struct {
     43     jfieldID keyCode;
     44     jfieldID metaState;
     45 } gFallbackActionClassInfo;
     46 
     47 
     48 class NativeKeyCharacterMap {
     49 public:
     50     NativeKeyCharacterMap(int32_t deviceId, const sp<KeyCharacterMap>& map) :
     51         mDeviceId(deviceId), mMap(map) {
     52     }
     53 
     54     ~NativeKeyCharacterMap() {
     55     }
     56 
     57     inline int32_t getDeviceId() const {
     58         return mDeviceId;
     59     }
     60 
     61     inline const sp<KeyCharacterMap>& getMap() const {
     62         return mMap;
     63     }
     64 
     65 private:
     66     int32_t mDeviceId;
     67     sp<KeyCharacterMap> mMap;
     68 };
     69 
     70 
     71 jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId,
     72         const sp<KeyCharacterMap>& kcm) {
     73     NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId,
     74             kcm.get() ? kcm : KeyCharacterMap::empty());
     75     if (!map) {
     76         return NULL;
     77     }
     78 
     79     return env->NewObject(gKeyCharacterMapClassInfo.clazz, gKeyCharacterMapClassInfo.ctor,
     80             reinterpret_cast<jlong>(map));
     81 }
     82 
     83 static jlong nativeReadFromParcel(JNIEnv *env, jobject clazz, jobject parcelObj) {
     84     Parcel* parcel = parcelForJavaObject(env, parcelObj);
     85     if (!parcel) {
     86         return 0;
     87     }
     88 
     89     int32_t deviceId = parcel->readInt32();
     90     if (parcel->errorCheck()) {
     91         return 0;
     92     }
     93 
     94     sp<KeyCharacterMap> kcm = KeyCharacterMap::readFromParcel(parcel);
     95     if (!kcm.get()) {
     96         return 0;
     97     }
     98 
     99     NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, kcm);
    100     return reinterpret_cast<jlong>(map);
    101 }
    102 
    103 static void nativeWriteToParcel(JNIEnv* env, jobject clazz, jlong ptr, jobject parcelObj) {
    104     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    105     Parcel* parcel = parcelForJavaObject(env, parcelObj);
    106     if (parcel) {
    107         parcel->writeInt32(map->getDeviceId());
    108         map->getMap()->writeToParcel(parcel);
    109     }
    110 }
    111 
    112 static void nativeDispose(JNIEnv *env, jobject clazz, jlong ptr) {
    113     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    114     delete map;
    115 }
    116 
    117 static jchar nativeGetCharacter(JNIEnv *env, jobject clazz, jlong ptr,
    118         jint keyCode, jint metaState) {
    119     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    120     return map->getMap()->getCharacter(keyCode, metaState);
    121 }
    122 
    123 static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode,
    124         jint metaState, jobject fallbackActionObj) {
    125     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    126     KeyCharacterMap::FallbackAction fallbackAction;
    127 
    128     bool result = map->getMap()->getFallbackAction(keyCode, metaState, &fallbackAction);
    129     if (result) {
    130         env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode,
    131                 fallbackAction.keyCode);
    132         env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState,
    133                 fallbackAction.metaState);
    134     }
    135     return result;
    136 }
    137 
    138 static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode) {
    139     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    140     return map->getMap()->getNumber(keyCode);
    141 }
    142 
    143 static jchar nativeGetMatch(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode,
    144         jcharArray charsArray, jint metaState) {
    145     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    146 
    147     jsize numChars = env->GetArrayLength(charsArray);
    148     jchar* chars = static_cast<jchar*>(env->GetPrimitiveArrayCritical(charsArray, NULL));
    149     if (!chars) {
    150         return 0;
    151     }
    152 
    153     char16_t result = map->getMap()->getMatch(
    154         keyCode, reinterpret_cast<char16_t*>(chars), size_t(numChars),
    155         metaState);
    156 
    157     env->ReleasePrimitiveArrayCritical(charsArray, chars, JNI_ABORT);
    158     return result;
    159 }
    160 
    161 static jchar nativeGetDisplayLabel(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode) {
    162     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    163     return map->getMap()->getDisplayLabel(keyCode);
    164 }
    165 
    166 static jint nativeGetKeyboardType(JNIEnv *env, jobject clazz, jlong ptr) {
    167     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    168     return map->getMap()->getKeyboardType();
    169 }
    170 
    171 static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jlong ptr,
    172         jcharArray charsArray) {
    173     NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr);
    174 
    175     jchar* chars = env->GetCharArrayElements(charsArray, NULL);
    176     if (!chars) {
    177         return NULL;
    178     }
    179     jsize numChars = env->GetArrayLength(charsArray);
    180 
    181     Vector<KeyEvent> events;
    182     jobjectArray result = NULL;
    183     if (map->getMap()->getEvents(map->getDeviceId(),
    184                                  reinterpret_cast<char16_t*>(chars),
    185                                  size_t(numChars), events)) {
    186         result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL);
    187         if (result) {
    188             for (size_t i = 0; i < events.size(); i++) {
    189                 jobject keyEventObj = android_view_KeyEvent_fromNative(env, &events.itemAt(i));
    190                 if (!keyEventObj) break; // threw OOM exception
    191                 env->SetObjectArrayElement(result, jsize(i), keyEventObj);
    192                 env->DeleteLocalRef(keyEventObj);
    193             }
    194         }
    195     }
    196 
    197     env->ReleaseCharArrayElements(charsArray, chars, JNI_ABORT);
    198     return result;
    199 }
    200 
    201 
    202 /*
    203  * JNI registration.
    204  */
    205 
    206 static JNINativeMethod g_methods[] = {
    207     /* name, signature, funcPtr */
    208     { "nativeReadFromParcel", "(Landroid/os/Parcel;)J",
    209             (void*)nativeReadFromParcel },
    210     { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
    211             (void*)nativeWriteToParcel },
    212     { "nativeDispose", "(J)V",
    213             (void*)nativeDispose },
    214     { "nativeGetCharacter", "(JII)C",
    215             (void*)nativeGetCharacter },
    216     { "nativeGetFallbackAction", "(JIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
    217             (void*)nativeGetFallbackAction },
    218     { "nativeGetNumber", "(JI)C",
    219             (void*)nativeGetNumber },
    220     { "nativeGetMatch", "(JI[CI)C",
    221             (void*)nativeGetMatch },
    222     { "nativeGetDisplayLabel", "(JI)C",
    223             (void*)nativeGetDisplayLabel },
    224     { "nativeGetKeyboardType", "(J)I",
    225             (void*)nativeGetKeyboardType },
    226     { "nativeGetEvents", "(J[C)[Landroid/view/KeyEvent;",
    227             (void*)nativeGetEvents },
    228 };
    229 
    230 int register_android_view_KeyCharacterMap(JNIEnv* env)
    231 {
    232     gKeyCharacterMapClassInfo.clazz = FindClassOrDie(env, "android/view/KeyCharacterMap");
    233     gKeyCharacterMapClassInfo.clazz = MakeGlobalRefOrDie(env, gKeyCharacterMapClassInfo.clazz);
    234 
    235     gKeyCharacterMapClassInfo.ctor = GetMethodIDOrDie(env, gKeyCharacterMapClassInfo.clazz,
    236             "<init>", "(J)V");
    237 
    238     gKeyEventClassInfo.clazz = FindClassOrDie(env, "android/view/KeyEvent");
    239     gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, gKeyEventClassInfo.clazz);
    240 
    241     jclass clazz = FindClassOrDie(env, "android/view/KeyCharacterMap$FallbackAction");
    242 
    243     gFallbackActionClassInfo.keyCode = GetFieldIDOrDie(env, clazz, "keyCode", "I");
    244     gFallbackActionClassInfo.metaState = GetFieldIDOrDie(env, clazz, "metaState", "I");
    245 
    246     return RegisterMethodsOrDie(env, "android/view/KeyCharacterMap", g_methods, NELEM(g_methods));
    247 }
    248 
    249 }; // namespace android
    250