19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright 2006, The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/KeyCharacterMap.h> 186b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <ui/Input.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 216b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include <nativehelper/jni.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <nativehelper/JNIHelp.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 246b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#include "android_view_KeyEvent.h" 256b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 286b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic struct { 296b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jclass clazz; 306b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown} gKeyEventClassInfo; 316b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 3249ed71db425c5054e3ad9526496a7e116c89556bJeff Brownstatic struct { 3349ed71db425c5054e3ad9526496a7e116c89556bJeff Brown jfieldID keyCode; 3449ed71db425c5054e3ad9526496a7e116c89556bJeff Brown jfieldID metaState; 3549ed71db425c5054e3ad9526496a7e116c89556bJeff Brown} gFallbackActionClassInfo; 3649ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 3749ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 381e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brownstatic jint nativeLoad(JNIEnv *env, jobject clazz, jstring fileStr) { 391e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown const char* file = env->GetStringUTFChars(fileStr, NULL); 401e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown 416b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map; 421e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown status_t status = KeyCharacterMap::load(String8(file), &map); 431e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown jint result; 446b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (status) { 456b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown String8 msg; 461e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown msg.appendFormat("Could not load key character map '%s' due to error %d. " 471e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown "Refer to the log for details.", file, status); 486b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jniThrowException(env, "android/view/KeyCharacterMap$KeyCharacterMapUnavailableException", 496b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown msg.string()); 501e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown result = 0; 511e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown } else { 521e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown result = reinterpret_cast<jint>(map); 536b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 541e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown 551e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown env->ReleaseStringUTFChars(fileStr, file); 561e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown return result; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 596b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic void nativeDispose(JNIEnv *env, jobject clazz, jint ptr) { 606b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 616b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown delete map; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 646b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic jchar nativeGetCharacter(JNIEnv *env, jobject clazz, jint ptr, 656b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jint keyCode, jint metaState) { 666b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 676b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return map->getCharacter(keyCode, metaState); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7049ed71db425c5054e3ad9526496a7e116c89556bJeff Brownstatic jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, 7149ed71db425c5054e3ad9526496a7e116c89556bJeff Brown jint metaState, jobject fallbackActionObj) { 7249ed71db425c5054e3ad9526496a7e116c89556bJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 7349ed71db425c5054e3ad9526496a7e116c89556bJeff Brown KeyCharacterMap::FallbackAction fallbackAction; 7449ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 7549ed71db425c5054e3ad9526496a7e116c89556bJeff Brown bool result = map->getFallbackAction(keyCode, metaState, &fallbackAction); 7649ed71db425c5054e3ad9526496a7e116c89556bJeff Brown if (result) { 7749ed71db425c5054e3ad9526496a7e116c89556bJeff Brown env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode, 7849ed71db425c5054e3ad9526496a7e116c89556bJeff Brown fallbackAction.keyCode); 7949ed71db425c5054e3ad9526496a7e116c89556bJeff Brown env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState, 8049ed71db425c5054e3ad9526496a7e116c89556bJeff Brown fallbackAction.metaState); 8149ed71db425c5054e3ad9526496a7e116c89556bJeff Brown } 8249ed71db425c5054e3ad9526496a7e116c89556bJeff Brown return result; 8349ed71db425c5054e3ad9526496a7e116c89556bJeff Brown} 8449ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 856b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic jchar nativeGetNumber(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { 866b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 876b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return map->getNumber(keyCode); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 906b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic jchar nativeGetMatch(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, 916b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jcharArray charsArray, jint metaState) { 926b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 946b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jsize numChars = env->GetArrayLength(charsArray); 956b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jchar* chars = static_cast<jchar*>(env->GetPrimitiveArrayCritical(charsArray, NULL)); 966b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (!chars) { 976b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return 0; 986b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1006b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown char16_t result = map->getMatch(keyCode, chars, size_t(numChars), metaState); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1026b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown env->ReleasePrimitiveArrayCritical(charsArray, chars, JNI_ABORT); 1036b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return result; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1066b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic jchar nativeGetDisplayLabel(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { 1076b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 1086b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return map->getDisplayLabel(keyCode); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1116b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic jint nativeGetKeyboardType(JNIEnv *env, jobject clazz, jint ptr) { 1126b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 1136b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return map->getKeyboardType(); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1166b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brownstatic jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jint ptr, jint deviceId, 1176b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jcharArray charsArray) { 1186b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1206b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jchar* chars = env->GetCharArrayElements(charsArray, NULL); 1216b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (!chars) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1246b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jsize numChars = env->GetArrayLength(charsArray); 1256b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 1266b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown Vector<KeyEvent> events; 1276b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jobjectArray result = NULL; 1286b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (map->getEvents(deviceId, chars, size_t(numChars), events)) { 1296b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL); 1306b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (result) { 1316b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown for (size_t i = 0; i < events.size(); i++) { 1326b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown jobject keyEventObj = android_view_KeyEvent_fromNative(env, &events.itemAt(i)); 1336b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown if (!keyEventObj) break; // threw OOM exception 1346b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown env->SetObjectArrayElement(result, jsize(i), keyEventObj); 1356b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown env->DeleteLocalRef(keyEventObj); 1366b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 1376b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 1386b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown } 1396b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 1406b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown env->ReleaseCharArrayElements(charsArray, chars, JNI_ABORT); 1416b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown return result; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1446b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration. 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod g_methods[] = { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 1511e08fe90df18930691b0c2ec22e5db25d7fcb4cfJeff Brown { "nativeLoad", "(Ljava/lang/String;)I", 1526b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeLoad }, 1536b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeDispose", "(I)V", 1546b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeDispose }, 1556b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeGetCharacter", "(III)C", 1566b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeGetCharacter }, 15749ed71db425c5054e3ad9526496a7e116c89556bJeff Brown { "nativeGetFallbackAction", "(IIILandroid/view/KeyCharacterMap$FallbackAction;)Z", 15849ed71db425c5054e3ad9526496a7e116c89556bJeff Brown (void*)nativeGetFallbackAction }, 1596b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeGetNumber", "(II)C", 1606b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeGetNumber }, 1616b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeGetMatch", "(II[CI)C", 1626b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeGetMatch }, 1636b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeGetDisplayLabel", "(II)C", 1646b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeGetDisplayLabel }, 1656b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeGetKeyboardType", "(I)I", 1666b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeGetKeyboardType }, 1676b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown { "nativeGetEvents", "(II[C)[Landroid/view/KeyEvent;", 1686b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown (void*)nativeGetEvents }, 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1716b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown#define FIND_CLASS(var, className) \ 1726b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown var = env->FindClass(className); \ 17317cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro LOG_FATAL_IF(! var, "Unable to find class " className); 1746b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown 17549ed71db425c5054e3ad9526496a7e116c89556bJeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 17649ed71db425c5054e3ad9526496a7e116c89556bJeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 17749ed71db425c5054e3ad9526496a7e116c89556bJeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 17849ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_text_KeyCharacterMap(JNIEnv* env) 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1816b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); 18217cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz)); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18417cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro jclass clazz; 18517cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro FIND_CLASS(clazz, "android/view/KeyCharacterMap$FallbackAction"); 18649ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 18717cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro GET_FIELD_ID(gFallbackActionClassInfo.keyCode, clazz, 18849ed71db425c5054e3ad9526496a7e116c89556bJeff Brown "keyCode", "I"); 18949ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 19017cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro GET_FIELD_ID(gFallbackActionClassInfo.metaState, clazz, 19149ed71db425c5054e3ad9526496a7e116c89556bJeff Brown "metaState", "I"); 19249ed71db425c5054e3ad9526496a7e116c89556bJeff Brown 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/view/KeyCharacterMap", g_methods, NELEM(g_methods)); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android 198