Loading services/core/jni/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -211,7 +211,6 @@ cc_defaults { "android.system.suspend-V1-ndk", "server_configurable_flags", "service.incremental", "android.companion.virtualdevice.flags-aconfig-cc", ], static_libs: [ Loading services/core/jni/com_android_server_companion_virtual_InputController.cpp +2 −253 Original line number Diff line number Diff line Loading @@ -19,273 +19,22 @@ #include <android-base/unique_fd.h> #include <android/input.h> #include <android/keycodes.h> #include <android_companion_virtualdevice_flags.h> #include <errno.h> #include <fcntl.h> #include <input/Input.h> #include <input/VirtualInputDevice.h> #include <linux/uinput.h> #include <math.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> #include <utils/Log.h> #include <map> #include <set> #include <string> using android::base::unique_fd; namespace android { namespace vd_flags = android::companion::virtualdevice::flags; static constexpr jlong INVALID_PTR = 0; enum class DeviceType { KEYBOARD, MOUSE, TOUCHSCREEN, DPAD, STYLUS, ROTARY_ENCODER, }; static unique_fd invalidFd() { return unique_fd(-1); } /** Creates a new uinput device and assigns a file descriptor. */ static unique_fd openUinput(const char* readableName, jint vendorId, jint productId, const char* phys, DeviceType deviceType, jint screenHeight, jint screenWidth) { unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK))); if (fd < 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } ioctl(fd, UI_SET_PHYS, phys); ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_EVBIT, EV_SYN); switch (deviceType) { case DeviceType::DPAD: for (const auto& [_, keyCode] : VirtualDpad::DPAD_KEY_CODE_MAPPING) { ioctl(fd, UI_SET_KEYBIT, keyCode); } break; case DeviceType::KEYBOARD: for (const auto& [_, keyCode] : VirtualKeyboard::KEY_CODE_MAPPING) { ioctl(fd, UI_SET_KEYBIT, keyCode); } break; case DeviceType::MOUSE: ioctl(fd, UI_SET_EVBIT, EV_REL); ioctl(fd, UI_SET_KEYBIT, BTN_LEFT); ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT); ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE); ioctl(fd, UI_SET_KEYBIT, BTN_BACK); ioctl(fd, UI_SET_KEYBIT, BTN_FORWARD); ioctl(fd, UI_SET_RELBIT, REL_X); ioctl(fd, UI_SET_RELBIT, REL_Y); ioctl(fd, UI_SET_RELBIT, REL_WHEEL); ioctl(fd, UI_SET_RELBIT, REL_HWHEEL); if (vd_flags::high_resolution_scroll()) { ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES); ioctl(fd, UI_SET_RELBIT, REL_HWHEEL_HI_RES); } break; case DeviceType::TOUCHSCREEN: ioctl(fd, UI_SET_EVBIT, EV_ABS); ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH); ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT); ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X); ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y); ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID); ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE); ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR); ioctl(fd, UI_SET_ABSBIT, ABS_MT_PRESSURE); ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT); break; case DeviceType::STYLUS: ioctl(fd, UI_SET_EVBIT, EV_ABS); ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH); ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS); ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2); ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PEN); ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_RUBBER); ioctl(fd, UI_SET_ABSBIT, ABS_X); ioctl(fd, UI_SET_ABSBIT, ABS_Y); ioctl(fd, UI_SET_ABSBIT, ABS_TILT_X); ioctl(fd, UI_SET_ABSBIT, ABS_TILT_Y); ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE); ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT); break; case DeviceType::ROTARY_ENCODER: ioctl(fd, UI_SET_EVBIT, EV_REL); ioctl(fd, UI_SET_RELBIT, REL_WHEEL); if (vd_flags::high_resolution_scroll()) { ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES); } break; default: ALOGE("Invalid input device type %d", static_cast<int32_t>(deviceType)); return invalidFd(); } int version; if (ioctl(fd, UI_GET_VERSION, &version) == 0 && version >= 5) { uinput_setup setup; memset(&setup, 0, sizeof(setup)); strlcpy(setup.name, readableName, UINPUT_MAX_NAME_SIZE); setup.id.version = 1; setup.id.bustype = BUS_VIRTUAL; setup.id.vendor = vendorId; setup.id.product = productId; if (deviceType == DeviceType::TOUCHSCREEN) { uinput_abs_setup xAbsSetup; xAbsSetup.code = ABS_MT_POSITION_X; xAbsSetup.absinfo.maximum = screenWidth - 1; xAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput x axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup yAbsSetup; yAbsSetup.code = ABS_MT_POSITION_Y; yAbsSetup.absinfo.maximum = screenHeight - 1; yAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput y axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup majorAbsSetup; majorAbsSetup.code = ABS_MT_TOUCH_MAJOR; majorAbsSetup.absinfo.maximum = screenWidth - 1; majorAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &majorAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput major axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup pressureAbsSetup; pressureAbsSetup.code = ABS_MT_PRESSURE; pressureAbsSetup.absinfo.maximum = 255; pressureAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup slotAbsSetup; slotAbsSetup.code = ABS_MT_SLOT; slotAbsSetup.absinfo.maximum = MAX_POINTERS - 1; slotAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &slotAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput slots: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup trackingIdAbsSetup; trackingIdAbsSetup.code = ABS_MT_TRACKING_ID; trackingIdAbsSetup.absinfo.maximum = MAX_POINTERS - 1; trackingIdAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &trackingIdAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput tracking ids: %s", strerror(errno)); return invalidFd(); } } else if (deviceType == DeviceType::STYLUS) { uinput_abs_setup xAbsSetup; xAbsSetup.code = ABS_X; xAbsSetup.absinfo.maximum = screenWidth - 1; xAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) { ALOGE("Error creating stylus uinput x axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup yAbsSetup; yAbsSetup.code = ABS_Y; yAbsSetup.absinfo.maximum = screenHeight - 1; yAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) { ALOGE("Error creating stylus uinput y axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup tiltXAbsSetup; tiltXAbsSetup.code = ABS_TILT_X; tiltXAbsSetup.absinfo.maximum = 90; tiltXAbsSetup.absinfo.minimum = -90; if (ioctl(fd, UI_ABS_SETUP, &tiltXAbsSetup) != 0) { ALOGE("Error creating stylus uinput tilt x axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup tiltYAbsSetup; tiltYAbsSetup.code = ABS_TILT_Y; tiltYAbsSetup.absinfo.maximum = 90; tiltYAbsSetup.absinfo.minimum = -90; if (ioctl(fd, UI_ABS_SETUP, &tiltYAbsSetup) != 0) { ALOGE("Error creating stylus uinput tilt y axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup pressureAbsSetup; pressureAbsSetup.code = ABS_PRESSURE; pressureAbsSetup.absinfo.maximum = 255; pressureAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno)); return invalidFd(); } } if (ioctl(fd, UI_DEV_SETUP, &setup) != 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } } else { // UI_DEV_SETUP was not introduced until version 5. Try setting up manually. ALOGI("Falling back to version %d manual setup", version); uinput_user_dev fallback; memset(&fallback, 0, sizeof(fallback)); strlcpy(fallback.name, readableName, UINPUT_MAX_NAME_SIZE); fallback.id.version = 1; fallback.id.bustype = BUS_VIRTUAL; fallback.id.vendor = vendorId; fallback.id.product = productId; if (deviceType == DeviceType::TOUCHSCREEN) { fallback.absmin[ABS_MT_POSITION_X] = 0; fallback.absmax[ABS_MT_POSITION_X] = screenWidth - 1; fallback.absmin[ABS_MT_POSITION_Y] = 0; fallback.absmax[ABS_MT_POSITION_Y] = screenHeight - 1; fallback.absmin[ABS_MT_TOUCH_MAJOR] = 0; fallback.absmax[ABS_MT_TOUCH_MAJOR] = screenWidth - 1; fallback.absmin[ABS_MT_PRESSURE] = 0; fallback.absmax[ABS_MT_PRESSURE] = 255; } else if (deviceType == DeviceType::STYLUS) { fallback.absmin[ABS_X] = 0; fallback.absmax[ABS_X] = screenWidth - 1; fallback.absmin[ABS_Y] = 0; fallback.absmax[ABS_Y] = screenHeight - 1; fallback.absmin[ABS_TILT_X] = -90; fallback.absmax[ABS_TILT_X] = 90; fallback.absmin[ABS_TILT_Y] = -90; fallback.absmax[ABS_TILT_Y] = 90; fallback.absmin[ABS_PRESSURE] = 0; fallback.absmax[ABS_PRESSURE] = 255; } if (TEMP_FAILURE_RETRY(write(fd, &fallback, sizeof(fallback))) != sizeof(fallback)) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } } if (ioctl(fd, UI_DEV_CREATE) != 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } return fd; } static unique_fd openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId, jstring phys, DeviceType deviceType, int screenHeight, int screenWidth) { jstring phys, DeviceType deviceType, jint screenHeight, jint screenWidth) { ScopedUtfChars readableName(env, name); ScopedUtfChars readablePhys(env, phys); return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType, Loading Loading
services/core/jni/Android.bp +0 −1 Original line number Diff line number Diff line Loading @@ -211,7 +211,6 @@ cc_defaults { "android.system.suspend-V1-ndk", "server_configurable_flags", "service.incremental", "android.companion.virtualdevice.flags-aconfig-cc", ], static_libs: [ Loading
services/core/jni/com_android_server_companion_virtual_InputController.cpp +2 −253 Original line number Diff line number Diff line Loading @@ -19,273 +19,22 @@ #include <android-base/unique_fd.h> #include <android/input.h> #include <android/keycodes.h> #include <android_companion_virtualdevice_flags.h> #include <errno.h> #include <fcntl.h> #include <input/Input.h> #include <input/VirtualInputDevice.h> #include <linux/uinput.h> #include <math.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedUtfChars.h> #include <utils/Log.h> #include <map> #include <set> #include <string> using android::base::unique_fd; namespace android { namespace vd_flags = android::companion::virtualdevice::flags; static constexpr jlong INVALID_PTR = 0; enum class DeviceType { KEYBOARD, MOUSE, TOUCHSCREEN, DPAD, STYLUS, ROTARY_ENCODER, }; static unique_fd invalidFd() { return unique_fd(-1); } /** Creates a new uinput device and assigns a file descriptor. */ static unique_fd openUinput(const char* readableName, jint vendorId, jint productId, const char* phys, DeviceType deviceType, jint screenHeight, jint screenWidth) { unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK))); if (fd < 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } ioctl(fd, UI_SET_PHYS, phys); ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_EVBIT, EV_SYN); switch (deviceType) { case DeviceType::DPAD: for (const auto& [_, keyCode] : VirtualDpad::DPAD_KEY_CODE_MAPPING) { ioctl(fd, UI_SET_KEYBIT, keyCode); } break; case DeviceType::KEYBOARD: for (const auto& [_, keyCode] : VirtualKeyboard::KEY_CODE_MAPPING) { ioctl(fd, UI_SET_KEYBIT, keyCode); } break; case DeviceType::MOUSE: ioctl(fd, UI_SET_EVBIT, EV_REL); ioctl(fd, UI_SET_KEYBIT, BTN_LEFT); ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT); ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE); ioctl(fd, UI_SET_KEYBIT, BTN_BACK); ioctl(fd, UI_SET_KEYBIT, BTN_FORWARD); ioctl(fd, UI_SET_RELBIT, REL_X); ioctl(fd, UI_SET_RELBIT, REL_Y); ioctl(fd, UI_SET_RELBIT, REL_WHEEL); ioctl(fd, UI_SET_RELBIT, REL_HWHEEL); if (vd_flags::high_resolution_scroll()) { ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES); ioctl(fd, UI_SET_RELBIT, REL_HWHEEL_HI_RES); } break; case DeviceType::TOUCHSCREEN: ioctl(fd, UI_SET_EVBIT, EV_ABS); ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH); ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT); ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X); ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y); ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID); ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE); ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR); ioctl(fd, UI_SET_ABSBIT, ABS_MT_PRESSURE); ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT); break; case DeviceType::STYLUS: ioctl(fd, UI_SET_EVBIT, EV_ABS); ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH); ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS); ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2); ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PEN); ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_RUBBER); ioctl(fd, UI_SET_ABSBIT, ABS_X); ioctl(fd, UI_SET_ABSBIT, ABS_Y); ioctl(fd, UI_SET_ABSBIT, ABS_TILT_X); ioctl(fd, UI_SET_ABSBIT, ABS_TILT_Y); ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE); ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT); break; case DeviceType::ROTARY_ENCODER: ioctl(fd, UI_SET_EVBIT, EV_REL); ioctl(fd, UI_SET_RELBIT, REL_WHEEL); if (vd_flags::high_resolution_scroll()) { ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES); } break; default: ALOGE("Invalid input device type %d", static_cast<int32_t>(deviceType)); return invalidFd(); } int version; if (ioctl(fd, UI_GET_VERSION, &version) == 0 && version >= 5) { uinput_setup setup; memset(&setup, 0, sizeof(setup)); strlcpy(setup.name, readableName, UINPUT_MAX_NAME_SIZE); setup.id.version = 1; setup.id.bustype = BUS_VIRTUAL; setup.id.vendor = vendorId; setup.id.product = productId; if (deviceType == DeviceType::TOUCHSCREEN) { uinput_abs_setup xAbsSetup; xAbsSetup.code = ABS_MT_POSITION_X; xAbsSetup.absinfo.maximum = screenWidth - 1; xAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput x axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup yAbsSetup; yAbsSetup.code = ABS_MT_POSITION_Y; yAbsSetup.absinfo.maximum = screenHeight - 1; yAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput y axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup majorAbsSetup; majorAbsSetup.code = ABS_MT_TOUCH_MAJOR; majorAbsSetup.absinfo.maximum = screenWidth - 1; majorAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &majorAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput major axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup pressureAbsSetup; pressureAbsSetup.code = ABS_MT_PRESSURE; pressureAbsSetup.absinfo.maximum = 255; pressureAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup slotAbsSetup; slotAbsSetup.code = ABS_MT_SLOT; slotAbsSetup.absinfo.maximum = MAX_POINTERS - 1; slotAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &slotAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput slots: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup trackingIdAbsSetup; trackingIdAbsSetup.code = ABS_MT_TRACKING_ID; trackingIdAbsSetup.absinfo.maximum = MAX_POINTERS - 1; trackingIdAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &trackingIdAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput tracking ids: %s", strerror(errno)); return invalidFd(); } } else if (deviceType == DeviceType::STYLUS) { uinput_abs_setup xAbsSetup; xAbsSetup.code = ABS_X; xAbsSetup.absinfo.maximum = screenWidth - 1; xAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) { ALOGE("Error creating stylus uinput x axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup yAbsSetup; yAbsSetup.code = ABS_Y; yAbsSetup.absinfo.maximum = screenHeight - 1; yAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) { ALOGE("Error creating stylus uinput y axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup tiltXAbsSetup; tiltXAbsSetup.code = ABS_TILT_X; tiltXAbsSetup.absinfo.maximum = 90; tiltXAbsSetup.absinfo.minimum = -90; if (ioctl(fd, UI_ABS_SETUP, &tiltXAbsSetup) != 0) { ALOGE("Error creating stylus uinput tilt x axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup tiltYAbsSetup; tiltYAbsSetup.code = ABS_TILT_Y; tiltYAbsSetup.absinfo.maximum = 90; tiltYAbsSetup.absinfo.minimum = -90; if (ioctl(fd, UI_ABS_SETUP, &tiltYAbsSetup) != 0) { ALOGE("Error creating stylus uinput tilt y axis: %s", strerror(errno)); return invalidFd(); } uinput_abs_setup pressureAbsSetup; pressureAbsSetup.code = ABS_PRESSURE; pressureAbsSetup.absinfo.maximum = 255; pressureAbsSetup.absinfo.minimum = 0; if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) { ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno)); return invalidFd(); } } if (ioctl(fd, UI_DEV_SETUP, &setup) != 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } } else { // UI_DEV_SETUP was not introduced until version 5. Try setting up manually. ALOGI("Falling back to version %d manual setup", version); uinput_user_dev fallback; memset(&fallback, 0, sizeof(fallback)); strlcpy(fallback.name, readableName, UINPUT_MAX_NAME_SIZE); fallback.id.version = 1; fallback.id.bustype = BUS_VIRTUAL; fallback.id.vendor = vendorId; fallback.id.product = productId; if (deviceType == DeviceType::TOUCHSCREEN) { fallback.absmin[ABS_MT_POSITION_X] = 0; fallback.absmax[ABS_MT_POSITION_X] = screenWidth - 1; fallback.absmin[ABS_MT_POSITION_Y] = 0; fallback.absmax[ABS_MT_POSITION_Y] = screenHeight - 1; fallback.absmin[ABS_MT_TOUCH_MAJOR] = 0; fallback.absmax[ABS_MT_TOUCH_MAJOR] = screenWidth - 1; fallback.absmin[ABS_MT_PRESSURE] = 0; fallback.absmax[ABS_MT_PRESSURE] = 255; } else if (deviceType == DeviceType::STYLUS) { fallback.absmin[ABS_X] = 0; fallback.absmax[ABS_X] = screenWidth - 1; fallback.absmin[ABS_Y] = 0; fallback.absmax[ABS_Y] = screenHeight - 1; fallback.absmin[ABS_TILT_X] = -90; fallback.absmax[ABS_TILT_X] = 90; fallback.absmin[ABS_TILT_Y] = -90; fallback.absmax[ABS_TILT_Y] = 90; fallback.absmin[ABS_PRESSURE] = 0; fallback.absmax[ABS_PRESSURE] = 255; } if (TEMP_FAILURE_RETRY(write(fd, &fallback, sizeof(fallback))) != sizeof(fallback)) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } } if (ioctl(fd, UI_DEV_CREATE) != 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); return invalidFd(); } return fd; } static unique_fd openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId, jstring phys, DeviceType deviceType, int screenHeight, int screenWidth) { jstring phys, DeviceType deviceType, jint screenHeight, jint screenWidth) { ScopedUtfChars readableName(env, name); ScopedUtfChars readablePhys(env, phys); return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType, Loading