1 /*
2  * Copyright (C) 2021 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 #define LOG_TAG "InputController"
18 
19 #include <android-base/unique_fd.h>
20 #include <android/input.h>
21 #include <android/keycodes.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <input/Input.h>
25 #include <input/VirtualInputDevice.h>
26 #include <linux/uinput.h>
27 #include <math.h>
28 #include <nativehelper/JNIHelp.h>
29 #include <nativehelper/ScopedUtfChars.h>
30 #include <utils/Log.h>
31 
32 #include <map>
33 #include <set>
34 #include <string>
35 
36 using android::base::unique_fd;
37 
38 namespace android {
39 
40 static constexpr jlong INVALID_PTR = 0;
41 
42 enum class DeviceType {
43     KEYBOARD,
44     MOUSE,
45     TOUCHSCREEN,
46     DPAD,
47     STYLUS,
48 };
49 
invalidFd()50 static unique_fd invalidFd() {
51     return unique_fd(-1);
52 }
53 
54 /** Creates a new uinput device and assigns a file descriptor. */
openUinput(const char * readableName,jint vendorId,jint productId,const char * phys,DeviceType deviceType,jint screenHeight,jint screenWidth)55 static unique_fd openUinput(const char* readableName, jint vendorId, jint productId,
56                             const char* phys, DeviceType deviceType, jint screenHeight,
57                             jint screenWidth) {
58     unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK)));
59     if (fd < 0) {
60         ALOGE("Error creating uinput device: %s", strerror(errno));
61         return invalidFd();
62     }
63 
64     ioctl(fd, UI_SET_PHYS, phys);
65 
66     ioctl(fd, UI_SET_EVBIT, EV_KEY);
67     ioctl(fd, UI_SET_EVBIT, EV_SYN);
68     switch (deviceType) {
69         case DeviceType::DPAD:
70             for (const auto& [_, keyCode] : VirtualDpad::DPAD_KEY_CODE_MAPPING) {
71                 ioctl(fd, UI_SET_KEYBIT, keyCode);
72             }
73             break;
74         case DeviceType::KEYBOARD:
75             for (const auto& [_, keyCode] : VirtualKeyboard::KEY_CODE_MAPPING) {
76                 ioctl(fd, UI_SET_KEYBIT, keyCode);
77             }
78             break;
79         case DeviceType::MOUSE:
80             ioctl(fd, UI_SET_EVBIT, EV_REL);
81             ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
82             ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);
83             ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE);
84             ioctl(fd, UI_SET_KEYBIT, BTN_BACK);
85             ioctl(fd, UI_SET_KEYBIT, BTN_FORWARD);
86             ioctl(fd, UI_SET_RELBIT, REL_X);
87             ioctl(fd, UI_SET_RELBIT, REL_Y);
88             ioctl(fd, UI_SET_RELBIT, REL_WHEEL);
89             ioctl(fd, UI_SET_RELBIT, REL_HWHEEL);
90             break;
91         case DeviceType::TOUCHSCREEN:
92             ioctl(fd, UI_SET_EVBIT, EV_ABS);
93             ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);
94             ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT);
95             ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
96             ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
97             ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
98             ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE);
99             ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
100             ioctl(fd, UI_SET_ABSBIT, ABS_MT_PRESSURE);
101             ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
102             break;
103         case DeviceType::STYLUS:
104             ioctl(fd, UI_SET_EVBIT, EV_ABS);
105             ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);
106             ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS);
107             ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2);
108             ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PEN);
109             ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_RUBBER);
110             ioctl(fd, UI_SET_ABSBIT, ABS_X);
111             ioctl(fd, UI_SET_ABSBIT, ABS_Y);
112             ioctl(fd, UI_SET_ABSBIT, ABS_TILT_X);
113             ioctl(fd, UI_SET_ABSBIT, ABS_TILT_Y);
114             ioctl(fd, UI_SET_ABSBIT, ABS_PRESSURE);
115             ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
116             break;
117         default:
118             ALOGE("Invalid input device type %d", static_cast<int32_t>(deviceType));
119             return invalidFd();
120     }
121 
122     int version;
123     if (ioctl(fd, UI_GET_VERSION, &version) == 0 && version >= 5) {
124         uinput_setup setup;
125         memset(&setup, 0, sizeof(setup));
126         strlcpy(setup.name, readableName, UINPUT_MAX_NAME_SIZE);
127         setup.id.version = 1;
128         setup.id.bustype = BUS_VIRTUAL;
129         setup.id.vendor = vendorId;
130         setup.id.product = productId;
131         if (deviceType == DeviceType::TOUCHSCREEN) {
132             uinput_abs_setup xAbsSetup;
133             xAbsSetup.code = ABS_MT_POSITION_X;
134             xAbsSetup.absinfo.maximum = screenWidth - 1;
135             xAbsSetup.absinfo.minimum = 0;
136             if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) {
137                 ALOGE("Error creating touchscreen uinput x axis: %s", strerror(errno));
138                 return invalidFd();
139             }
140             uinput_abs_setup yAbsSetup;
141             yAbsSetup.code = ABS_MT_POSITION_Y;
142             yAbsSetup.absinfo.maximum = screenHeight - 1;
143             yAbsSetup.absinfo.minimum = 0;
144             if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) {
145                 ALOGE("Error creating touchscreen uinput y axis: %s", strerror(errno));
146                 return invalidFd();
147             }
148             uinput_abs_setup majorAbsSetup;
149             majorAbsSetup.code = ABS_MT_TOUCH_MAJOR;
150             majorAbsSetup.absinfo.maximum = screenWidth - 1;
151             majorAbsSetup.absinfo.minimum = 0;
152             if (ioctl(fd, UI_ABS_SETUP, &majorAbsSetup) != 0) {
153                 ALOGE("Error creating touchscreen uinput major axis: %s", strerror(errno));
154                 return invalidFd();
155             }
156             uinput_abs_setup pressureAbsSetup;
157             pressureAbsSetup.code = ABS_MT_PRESSURE;
158             pressureAbsSetup.absinfo.maximum = 255;
159             pressureAbsSetup.absinfo.minimum = 0;
160             if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) {
161                 ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno));
162                 return invalidFd();
163             }
164             uinput_abs_setup slotAbsSetup;
165             slotAbsSetup.code = ABS_MT_SLOT;
166             slotAbsSetup.absinfo.maximum = MAX_POINTERS - 1;
167             slotAbsSetup.absinfo.minimum = 0;
168             if (ioctl(fd, UI_ABS_SETUP, &slotAbsSetup) != 0) {
169                 ALOGE("Error creating touchscreen uinput slots: %s", strerror(errno));
170                 return invalidFd();
171             }
172             uinput_abs_setup trackingIdAbsSetup;
173             trackingIdAbsSetup.code = ABS_MT_TRACKING_ID;
174             trackingIdAbsSetup.absinfo.maximum = MAX_POINTERS - 1;
175             trackingIdAbsSetup.absinfo.minimum = 0;
176             if (ioctl(fd, UI_ABS_SETUP, &trackingIdAbsSetup) != 0) {
177                 ALOGE("Error creating touchscreen uinput tracking ids: %s", strerror(errno));
178                 return invalidFd();
179             }
180         } else if (deviceType == DeviceType::STYLUS) {
181             uinput_abs_setup xAbsSetup;
182             xAbsSetup.code = ABS_X;
183             xAbsSetup.absinfo.maximum = screenWidth - 1;
184             xAbsSetup.absinfo.minimum = 0;
185             if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) {
186                 ALOGE("Error creating stylus uinput x axis: %s", strerror(errno));
187                 return invalidFd();
188             }
189             uinput_abs_setup yAbsSetup;
190             yAbsSetup.code = ABS_Y;
191             yAbsSetup.absinfo.maximum = screenHeight - 1;
192             yAbsSetup.absinfo.minimum = 0;
193             if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) {
194                 ALOGE("Error creating stylus uinput y axis: %s", strerror(errno));
195                 return invalidFd();
196             }
197             uinput_abs_setup tiltXAbsSetup;
198             tiltXAbsSetup.code = ABS_TILT_X;
199             tiltXAbsSetup.absinfo.maximum = 90;
200             tiltXAbsSetup.absinfo.minimum = -90;
201             if (ioctl(fd, UI_ABS_SETUP, &tiltXAbsSetup) != 0) {
202                 ALOGE("Error creating stylus uinput tilt x axis: %s", strerror(errno));
203                 return invalidFd();
204             }
205             uinput_abs_setup tiltYAbsSetup;
206             tiltYAbsSetup.code = ABS_TILT_Y;
207             tiltYAbsSetup.absinfo.maximum = 90;
208             tiltYAbsSetup.absinfo.minimum = -90;
209             if (ioctl(fd, UI_ABS_SETUP, &tiltYAbsSetup) != 0) {
210                 ALOGE("Error creating stylus uinput tilt y axis: %s", strerror(errno));
211                 return invalidFd();
212             }
213             uinput_abs_setup pressureAbsSetup;
214             pressureAbsSetup.code = ABS_PRESSURE;
215             pressureAbsSetup.absinfo.maximum = 255;
216             pressureAbsSetup.absinfo.minimum = 0;
217             if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) {
218                 ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno));
219                 return invalidFd();
220             }
221         }
222         if (ioctl(fd, UI_DEV_SETUP, &setup) != 0) {
223             ALOGE("Error creating uinput device: %s", strerror(errno));
224             return invalidFd();
225         }
226     } else {
227         // UI_DEV_SETUP was not introduced until version 5. Try setting up manually.
228         ALOGI("Falling back to version %d manual setup", version);
229         uinput_user_dev fallback;
230         memset(&fallback, 0, sizeof(fallback));
231         strlcpy(fallback.name, readableName, UINPUT_MAX_NAME_SIZE);
232         fallback.id.version = 1;
233         fallback.id.bustype = BUS_VIRTUAL;
234         fallback.id.vendor = vendorId;
235         fallback.id.product = productId;
236         if (deviceType == DeviceType::TOUCHSCREEN) {
237             fallback.absmin[ABS_MT_POSITION_X] = 0;
238             fallback.absmax[ABS_MT_POSITION_X] = screenWidth - 1;
239             fallback.absmin[ABS_MT_POSITION_Y] = 0;
240             fallback.absmax[ABS_MT_POSITION_Y] = screenHeight - 1;
241             fallback.absmin[ABS_MT_TOUCH_MAJOR] = 0;
242             fallback.absmax[ABS_MT_TOUCH_MAJOR] = screenWidth - 1;
243             fallback.absmin[ABS_MT_PRESSURE] = 0;
244             fallback.absmax[ABS_MT_PRESSURE] = 255;
245         } else if (deviceType == DeviceType::STYLUS) {
246             fallback.absmin[ABS_X] = 0;
247             fallback.absmax[ABS_X] = screenWidth - 1;
248             fallback.absmin[ABS_Y] = 0;
249             fallback.absmax[ABS_Y] = screenHeight - 1;
250             fallback.absmin[ABS_TILT_X] = -90;
251             fallback.absmax[ABS_TILT_X] = 90;
252             fallback.absmin[ABS_TILT_Y] = -90;
253             fallback.absmax[ABS_TILT_Y] = 90;
254             fallback.absmin[ABS_PRESSURE] = 0;
255             fallback.absmax[ABS_PRESSURE] = 255;
256         }
257         if (TEMP_FAILURE_RETRY(write(fd, &fallback, sizeof(fallback))) != sizeof(fallback)) {
258             ALOGE("Error creating uinput device: %s", strerror(errno));
259             return invalidFd();
260         }
261     }
262 
263     if (ioctl(fd, UI_DEV_CREATE) != 0) {
264         ALOGE("Error creating uinput device: %s", strerror(errno));
265         return invalidFd();
266     }
267 
268     return fd;
269 }
270 
openUinputJni(JNIEnv * env,jstring name,jint vendorId,jint productId,jstring phys,DeviceType deviceType,int screenHeight,int screenWidth)271 static unique_fd openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId,
272                                jstring phys, DeviceType deviceType, int screenHeight,
273                                int screenWidth) {
274     ScopedUtfChars readableName(env, name);
275     ScopedUtfChars readablePhys(env, phys);
276     return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType,
277                       screenHeight, screenWidth);
278 }
279 
nativeOpenUinputDpad(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys)280 static jlong nativeOpenUinputDpad(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
281                                   jint productId, jstring phys) {
282     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::DPAD,
283                             /* screenHeight= */ 0, /* screenWidth= */ 0);
284     return fd.ok() ? reinterpret_cast<jlong>(new VirtualDpad(std::move(fd))) : INVALID_PTR;
285 }
286 
nativeOpenUinputKeyboard(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys)287 static jlong nativeOpenUinputKeyboard(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
288                                       jint productId, jstring phys) {
289     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::KEYBOARD,
290                             /* screenHeight= */ 0, /* screenWidth= */ 0);
291     return fd.ok() ? reinterpret_cast<jlong>(new VirtualKeyboard(std::move(fd))) : INVALID_PTR;
292 }
293 
nativeOpenUinputMouse(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys)294 static jlong nativeOpenUinputMouse(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
295                                    jint productId, jstring phys) {
296     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::MOUSE,
297                             /* screenHeight= */ 0, /* screenWidth= */ 0);
298     return fd.ok() ? reinterpret_cast<jlong>(new VirtualMouse(std::move(fd))) : INVALID_PTR;
299 }
300 
nativeOpenUinputTouchscreen(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys,jint height,jint width)301 static jlong nativeOpenUinputTouchscreen(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
302                                          jint productId, jstring phys, jint height, jint width) {
303     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::TOUCHSCREEN, height,
304                             width);
305     return fd.ok() ? reinterpret_cast<jlong>(new VirtualTouchscreen(std::move(fd))) : INVALID_PTR;
306 }
307 
nativeOpenUinputStylus(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys,jint height,jint width)308 static jlong nativeOpenUinputStylus(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
309                                     jint productId, jstring phys, jint height, jint width) {
310     auto fd =
311             openUinputJni(env, name, vendorId, productId, phys, DeviceType::STYLUS, height, width);
312     return fd.ok() ? reinterpret_cast<jlong>(new VirtualStylus(std::move(fd))) : INVALID_PTR;
313 }
314 
nativeCloseUinput(JNIEnv * env,jobject thiz,jlong ptr)315 static void nativeCloseUinput(JNIEnv* env, jobject thiz, jlong ptr) {
316     VirtualInputDevice* virtualInputDevice = reinterpret_cast<VirtualInputDevice*>(ptr);
317     delete virtualInputDevice;
318 }
319 
320 // Native methods for VirtualDpad
nativeWriteDpadKeyEvent(JNIEnv * env,jobject thiz,jlong ptr,jint androidKeyCode,jint action,jlong eventTimeNanos)321 static bool nativeWriteDpadKeyEvent(JNIEnv* env, jobject thiz, jlong ptr, jint androidKeyCode,
322                                     jint action, jlong eventTimeNanos) {
323     VirtualDpad* virtualDpad = reinterpret_cast<VirtualDpad*>(ptr);
324     return virtualDpad->writeDpadKeyEvent(androidKeyCode, action,
325                                           std::chrono::nanoseconds(eventTimeNanos));
326 }
327 
328 // Native methods for VirtualKeyboard
nativeWriteKeyEvent(JNIEnv * env,jobject thiz,jlong ptr,jint androidKeyCode,jint action,jlong eventTimeNanos)329 static bool nativeWriteKeyEvent(JNIEnv* env, jobject thiz, jlong ptr, jint androidKeyCode,
330                                 jint action, jlong eventTimeNanos) {
331     VirtualKeyboard* virtualKeyboard = reinterpret_cast<VirtualKeyboard*>(ptr);
332     return virtualKeyboard->writeKeyEvent(androidKeyCode, action,
333                                           std::chrono::nanoseconds(eventTimeNanos));
334 }
335 
336 // Native methods for VirtualTouchscreen
nativeWriteTouchEvent(JNIEnv * env,jobject thiz,jlong ptr,jint pointerId,jint toolType,jint action,jfloat locationX,jfloat locationY,jfloat pressure,jfloat majorAxisSize,jlong eventTimeNanos)337 static bool nativeWriteTouchEvent(JNIEnv* env, jobject thiz, jlong ptr, jint pointerId,
338                                   jint toolType, jint action, jfloat locationX, jfloat locationY,
339                                   jfloat pressure, jfloat majorAxisSize, jlong eventTimeNanos) {
340     VirtualTouchscreen* virtualTouchscreen = reinterpret_cast<VirtualTouchscreen*>(ptr);
341     return virtualTouchscreen->writeTouchEvent(pointerId, toolType, action, locationX, locationY,
342                                                pressure, majorAxisSize,
343                                                std::chrono::nanoseconds(eventTimeNanos));
344 }
345 
346 // Native methods for VirtualMouse
nativeWriteButtonEvent(JNIEnv * env,jobject thiz,jlong ptr,jint buttonCode,jint action,jlong eventTimeNanos)347 static bool nativeWriteButtonEvent(JNIEnv* env, jobject thiz, jlong ptr, jint buttonCode,
348                                    jint action, jlong eventTimeNanos) {
349     VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
350     return virtualMouse->writeButtonEvent(buttonCode, action,
351                                           std::chrono::nanoseconds(eventTimeNanos));
352 }
353 
nativeWriteRelativeEvent(JNIEnv * env,jobject thiz,jlong ptr,jfloat relativeX,jfloat relativeY,jlong eventTimeNanos)354 static bool nativeWriteRelativeEvent(JNIEnv* env, jobject thiz, jlong ptr, jfloat relativeX,
355                                      jfloat relativeY, jlong eventTimeNanos) {
356     VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
357     return virtualMouse->writeRelativeEvent(relativeX, relativeY,
358                                             std::chrono::nanoseconds(eventTimeNanos));
359 }
360 
nativeWriteScrollEvent(JNIEnv * env,jobject thiz,jlong ptr,jfloat xAxisMovement,jfloat yAxisMovement,jlong eventTimeNanos)361 static bool nativeWriteScrollEvent(JNIEnv* env, jobject thiz, jlong ptr, jfloat xAxisMovement,
362                                    jfloat yAxisMovement, jlong eventTimeNanos) {
363     VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
364     return virtualMouse->writeScrollEvent(xAxisMovement, yAxisMovement,
365                                           std::chrono::nanoseconds(eventTimeNanos));
366 }
367 
368 // Native methods for VirtualStylus
nativeWriteStylusMotionEvent(JNIEnv * env,jobject thiz,jlong ptr,jint toolType,jint action,jint locationX,jint locationY,jint pressure,jint tiltX,jint tiltY,jlong eventTimeNanos)369 static bool nativeWriteStylusMotionEvent(JNIEnv* env, jobject thiz, jlong ptr, jint toolType,
370                                          jint action, jint locationX, jint locationY, jint pressure,
371                                          jint tiltX, jint tiltY, jlong eventTimeNanos) {
372     VirtualStylus* virtualStylus = reinterpret_cast<VirtualStylus*>(ptr);
373     return virtualStylus->writeMotionEvent(toolType, action, locationX, locationY, pressure, tiltX,
374                                            tiltY, std::chrono::nanoseconds(eventTimeNanos));
375 }
376 
nativeWriteStylusButtonEvent(JNIEnv * env,jobject thiz,jlong ptr,jint buttonCode,jint action,jlong eventTimeNanos)377 static bool nativeWriteStylusButtonEvent(JNIEnv* env, jobject thiz, jlong ptr, jint buttonCode,
378                                          jint action, jlong eventTimeNanos) {
379     VirtualStylus* virtualStylus = reinterpret_cast<VirtualStylus*>(ptr);
380     return virtualStylus->writeButtonEvent(buttonCode, action,
381                                            std::chrono::nanoseconds(eventTimeNanos));
382 }
383 
384 static JNINativeMethod methods[] = {
385         {"nativeOpenUinputDpad", "(Ljava/lang/String;IILjava/lang/String;)J",
386          (void*)nativeOpenUinputDpad},
387         {"nativeOpenUinputKeyboard", "(Ljava/lang/String;IILjava/lang/String;)J",
388          (void*)nativeOpenUinputKeyboard},
389         {"nativeOpenUinputMouse", "(Ljava/lang/String;IILjava/lang/String;)J",
390          (void*)nativeOpenUinputMouse},
391         {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IILjava/lang/String;II)J",
392          (void*)nativeOpenUinputTouchscreen},
393         {"nativeOpenUinputStylus", "(Ljava/lang/String;IILjava/lang/String;II)J",
394          (void*)nativeOpenUinputStylus},
395         {"nativeCloseUinput", "(J)V", (void*)nativeCloseUinput},
396         {"nativeWriteDpadKeyEvent", "(JIIJ)Z", (void*)nativeWriteDpadKeyEvent},
397         {"nativeWriteKeyEvent", "(JIIJ)Z", (void*)nativeWriteKeyEvent},
398         {"nativeWriteButtonEvent", "(JIIJ)Z", (void*)nativeWriteButtonEvent},
399         {"nativeWriteTouchEvent", "(JIIIFFFFJ)Z", (void*)nativeWriteTouchEvent},
400         {"nativeWriteRelativeEvent", "(JFFJ)Z", (void*)nativeWriteRelativeEvent},
401         {"nativeWriteScrollEvent", "(JFFJ)Z", (void*)nativeWriteScrollEvent},
402         {"nativeWriteStylusMotionEvent", "(JIIIIIIIJ)Z", (void*)nativeWriteStylusMotionEvent},
403         {"nativeWriteStylusButtonEvent", "(JIIJ)Z", (void*)nativeWriteStylusButtonEvent},
404 };
405 
register_android_server_companion_virtual_InputController(JNIEnv * env)406 int register_android_server_companion_virtual_InputController(JNIEnv* env) {
407     return jniRegisterNativeMethods(env, "com/android/server/companion/virtual/InputController",
408                                     methods, NELEM(methods));
409 }
410 
411 } // namespace android
412