/* * Copyright (C) 2012 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 "android_view_InputDevice.h" #include #include #include #include #include #include #include "android_view_KeyCharacterMap.h" #include "core_jni_helpers.h" namespace android { static struct { jclass clazz; jmethodID ctor; jmethodID addMotionRange; jmethodID setShouldSmoothScroll; } gInputDeviceClassInfo; jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo) { ScopedLocalRef nameObj(env, env->NewStringUTF(deviceInfo.getDisplayName().c_str())); if (!nameObj.get()) { return NULL; } ScopedLocalRef descriptorObj(env, env->NewStringUTF(deviceInfo.getIdentifier().descriptor.c_str())); if (!descriptorObj.get()) { return NULL; } std::optional layoutInfo = deviceInfo.getKeyboardLayoutInfo(); ScopedLocalRef keyboardLanguageTagObj(env, env->NewStringUTF( layoutInfo ? layoutInfo->languageTag.c_str() : NULL)); ScopedLocalRef keyboardLayoutTypeObj(env, env->NewStringUTF( layoutInfo ? layoutInfo->layoutType.c_str() : NULL)); std::shared_ptr map = deviceInfo.getKeyCharacterMap(); std::unique_ptr mapCopy; if (map != nullptr) { mapCopy = std::make_unique(*map); } ScopedLocalRef kcmObj(env, android_view_KeyCharacterMap_create(env, deviceInfo.getId(), std::move(mapCopy))); if (!kcmObj.get()) { return NULL; } const InputDeviceIdentifier& ident = deviceInfo.getIdentifier(); const auto usiVersion = deviceInfo.getUsiVersion().value_or(InputDeviceUsiVersion{-1, -1}); ScopedLocalRef inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(), deviceInfo.getControllerNumber(), nameObj.get(), static_cast(ident.vendor), static_cast(ident.product), static_cast(ident.bus), descriptorObj.get(), deviceInfo.isExternal(), deviceInfo.getSources(), deviceInfo.getKeyboardType(), kcmObj.get(), keyboardLanguageTagObj.get(), keyboardLayoutTypeObj.get(), deviceInfo.hasVibrator(), deviceInfo.hasMic(), deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(), deviceInfo.hasBattery(), usiVersion.majorVersion, usiVersion.minorVersion, deviceInfo.getAssociatedDisplayId(), deviceInfo.isEnabled())); // Note: We do not populate the Bluetooth address into the InputDevice object to avoid leaking // it to apps that do not have the Bluetooth permission. const std::vector& ranges = deviceInfo.getMotionRanges(); for (const InputDeviceInfo::MotionRange& range: ranges) { env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.addMotionRange, range.axis, range.source, range.min, range.max, range.flat, range.fuzz, range.resolution); if (env->ExceptionCheck()) { return NULL; } } if (com::android::input::flags::input_device_view_behavior_api()) { const InputDeviceViewBehavior& viewBehavior = deviceInfo.getViewBehavior(); std::optional defaultSmoothScroll = viewBehavior.shouldSmoothScroll; if (defaultSmoothScroll.has_value()) { env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.setShouldSmoothScroll, *defaultSmoothScroll); if (env->ExceptionCheck()) { return NULL; } } } return env->NewLocalRef(inputDeviceObj.get()); } int register_android_view_InputDevice(JNIEnv* env) { gInputDeviceClassInfo.clazz = FindClassOrDie(env, "android/view/InputDevice"); gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz); gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "", "(IIILjava/lang/String;IIILjava/lang/" "String;ZIILandroid/view/KeyCharacterMap;Ljava/" "lang/String;Ljava/lang/String;ZZZZZIIIZ)V"); gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "addMotionRange", "(IIFFFFF)V"); gInputDeviceClassInfo.setShouldSmoothScroll = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "setShouldSmoothScroll", "(Z)V"); return 0; } }; // namespace android