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