/* * Copyright 2006, 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. */ #include #include #include #include #include #include #include "android_os_Parcel.h" #include "android_view_KeyEvent.h" #include "core_jni_helpers.h" namespace android { static struct { jclass clazz; jmethodID ctor; } gKeyCharacterMapClassInfo; static struct { jclass clazz; } gKeyEventClassInfo; static struct { jfieldID keyCode; jfieldID metaState; } gFallbackActionClassInfo; class NativeKeyCharacterMap { public: NativeKeyCharacterMap(int32_t deviceId, const sp& map) : mDeviceId(deviceId), mMap(map) { } ~NativeKeyCharacterMap() { } inline int32_t getDeviceId() const { return mDeviceId; } inline const sp& getMap() const { return mMap; } private: int32_t mDeviceId; sp mMap; }; jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId, const sp& kcm) { NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, kcm.get() ? kcm : KeyCharacterMap::empty()); if (!map) { return NULL; } return env->NewObject(gKeyCharacterMapClassInfo.clazz, gKeyCharacterMapClassInfo.ctor, reinterpret_cast(map)); } static jlong nativeReadFromParcel(JNIEnv *env, jobject clazz, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); if (!parcel) { return 0; } int32_t deviceId = parcel->readInt32(); if (parcel->errorCheck()) { return 0; } sp kcm = KeyCharacterMap::readFromParcel(parcel); if (!kcm.get()) { return 0; } NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, kcm); return reinterpret_cast(map); } static void nativeWriteToParcel(JNIEnv* env, jobject clazz, jlong ptr, jobject parcelObj) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); Parcel* parcel = parcelForJavaObject(env, parcelObj); if (parcel) { parcel->writeInt32(map->getDeviceId()); map->getMap()->writeToParcel(parcel); } } static void nativeDispose(JNIEnv *env, jobject clazz, jlong ptr) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); delete map; } static jchar nativeGetCharacter(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode, jint metaState) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); return map->getMap()->getCharacter(keyCode, metaState); } static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode, jint metaState, jobject fallbackActionObj) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); KeyCharacterMap::FallbackAction fallbackAction; bool result = map->getMap()->getFallbackAction(keyCode, metaState, &fallbackAction); if (result) { env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode, fallbackAction.keyCode); env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState, fallbackAction.metaState); } return result; } static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); return map->getMap()->getNumber(keyCode); } static jchar nativeGetMatch(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode, jcharArray charsArray, jint metaState) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); jsize numChars = env->GetArrayLength(charsArray); jchar* chars = static_cast(env->GetPrimitiveArrayCritical(charsArray, NULL)); if (!chars) { return 0; } char16_t result = map->getMap()->getMatch( keyCode, reinterpret_cast(chars), size_t(numChars), metaState); env->ReleasePrimitiveArrayCritical(charsArray, chars, JNI_ABORT); return result; } static jchar nativeGetDisplayLabel(JNIEnv *env, jobject clazz, jlong ptr, jint keyCode) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); return map->getMap()->getDisplayLabel(keyCode); } static jint nativeGetKeyboardType(JNIEnv *env, jobject clazz, jlong ptr) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); return map->getMap()->getKeyboardType(); } static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jlong ptr, jcharArray charsArray) { NativeKeyCharacterMap* map = reinterpret_cast(ptr); jchar* chars = env->GetCharArrayElements(charsArray, NULL); if (!chars) { return NULL; } jsize numChars = env->GetArrayLength(charsArray); Vector events; jobjectArray result = NULL; if (map->getMap()->getEvents(map->getDeviceId(), reinterpret_cast(chars), size_t(numChars), events)) { result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL); if (result) { for (size_t i = 0; i < events.size(); i++) { jobject keyEventObj = android_view_KeyEvent_fromNative(env, &events.itemAt(i)); if (!keyEventObj) break; // threw OOM exception env->SetObjectArrayElement(result, jsize(i), keyEventObj); env->DeleteLocalRef(keyEventObj); } } } env->ReleaseCharArrayElements(charsArray, chars, JNI_ABORT); return result; } /* * JNI registration. */ static JNINativeMethod g_methods[] = { /* name, signature, funcPtr */ { "nativeReadFromParcel", "(Landroid/os/Parcel;)J", (void*)nativeReadFromParcel }, { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel }, { "nativeDispose", "(J)V", (void*)nativeDispose }, { "nativeGetCharacter", "(JII)C", (void*)nativeGetCharacter }, { "nativeGetFallbackAction", "(JIILandroid/view/KeyCharacterMap$FallbackAction;)Z", (void*)nativeGetFallbackAction }, { "nativeGetNumber", "(JI)C", (void*)nativeGetNumber }, { "nativeGetMatch", "(JI[CI)C", (void*)nativeGetMatch }, { "nativeGetDisplayLabel", "(JI)C", (void*)nativeGetDisplayLabel }, { "nativeGetKeyboardType", "(J)I", (void*)nativeGetKeyboardType }, { "nativeGetEvents", "(J[C)[Landroid/view/KeyEvent;", (void*)nativeGetEvents }, }; int register_android_view_KeyCharacterMap(JNIEnv* env) { gKeyCharacterMapClassInfo.clazz = FindClassOrDie(env, "android/view/KeyCharacterMap"); gKeyCharacterMapClassInfo.clazz = MakeGlobalRefOrDie(env, gKeyCharacterMapClassInfo.clazz); gKeyCharacterMapClassInfo.ctor = GetMethodIDOrDie(env, gKeyCharacterMapClassInfo.clazz, "", "(J)V"); gKeyEventClassInfo.clazz = FindClassOrDie(env, "android/view/KeyEvent"); gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, gKeyEventClassInfo.clazz); jclass clazz = FindClassOrDie(env, "android/view/KeyCharacterMap$FallbackAction"); gFallbackActionClassInfo.keyCode = GetFieldIDOrDie(env, clazz, "keyCode", "I"); gFallbackActionClassInfo.metaState = GetFieldIDOrDie(env, clazz, "metaState", "I"); return RegisterMethodsOrDie(env, "android/view/KeyCharacterMap", g_methods, NELEM(g_methods)); } }; // namespace android