• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <input/Input.h>
23 #include <input/VirtualInputDevice.h>
24 #include <nativehelper/JNIHelp.h>
25 #include <nativehelper/ScopedUtfChars.h>
26 
27 #include <string>
28 
29 using android::base::unique_fd;
30 
31 namespace android {
32 
33 static constexpr jlong INVALID_PTR = 0;
34 
openUinputJni(JNIEnv * env,jstring name,jint vendorId,jint productId,jstring phys,DeviceType deviceType,jint screenHeight,jint screenWidth)35 static unique_fd openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId,
36                                jstring phys, DeviceType deviceType, jint screenHeight,
37                                jint screenWidth) {
38     ScopedUtfChars readableName(env, name);
39     ScopedUtfChars readablePhys(env, phys);
40     return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType,
41                       screenHeight, screenWidth);
42 }
43 
nativeOpenUinputDpad(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys)44 static jlong nativeOpenUinputDpad(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
45                                   jint productId, jstring phys) {
46     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::DPAD,
47                             /* screenHeight= */ 0, /* screenWidth= */ 0);
48     return fd.ok() ? reinterpret_cast<jlong>(new VirtualDpad(std::move(fd))) : INVALID_PTR;
49 }
50 
nativeOpenUinputKeyboard(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys)51 static jlong nativeOpenUinputKeyboard(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
52                                       jint productId, jstring phys) {
53     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::KEYBOARD,
54                             /* screenHeight= */ 0, /* screenWidth= */ 0);
55     return fd.ok() ? reinterpret_cast<jlong>(new VirtualKeyboard(std::move(fd))) : INVALID_PTR;
56 }
57 
nativeOpenUinputMouse(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys)58 static jlong nativeOpenUinputMouse(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
59                                    jint productId, jstring phys) {
60     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::MOUSE,
61                             /* screenHeight= */ 0, /* screenWidth= */ 0);
62     return fd.ok() ? reinterpret_cast<jlong>(new VirtualMouse(std::move(fd))) : INVALID_PTR;
63 }
64 
nativeOpenUinputTouchscreen(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys,jint height,jint width)65 static jlong nativeOpenUinputTouchscreen(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
66                                          jint productId, jstring phys, jint height, jint width) {
67     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::TOUCHSCREEN, height,
68                             width);
69     return fd.ok() ? reinterpret_cast<jlong>(new VirtualTouchscreen(std::move(fd))) : INVALID_PTR;
70 }
71 
nativeOpenUinputStylus(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys,jint height,jint width)72 static jlong nativeOpenUinputStylus(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
73                                     jint productId, jstring phys, jint height, jint width) {
74     auto fd =
75             openUinputJni(env, name, vendorId, productId, phys, DeviceType::STYLUS, height, width);
76     return fd.ok() ? reinterpret_cast<jlong>(new VirtualStylus(std::move(fd))) : INVALID_PTR;
77 }
78 
nativeOpenUinputRotaryEncoder(JNIEnv * env,jobject thiz,jstring name,jint vendorId,jint productId,jstring phys,jint height,jint width)79 static jlong nativeOpenUinputRotaryEncoder(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
80                                            jint productId, jstring phys, jint height, jint width) {
81     auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::ROTARY_ENCODER,
82                             /* screenHeight= */ 0, /* screenWidth= */ 0);
83     return fd.ok() ? reinterpret_cast<jlong>(new VirtualRotaryEncoder(std::move(fd))) : INVALID_PTR;
84 }
85 
nativeCloseUinput(JNIEnv * env,jobject thiz,jlong ptr)86 static void nativeCloseUinput(JNIEnv* env, jobject thiz, jlong ptr) {
87     VirtualInputDevice* virtualInputDevice = reinterpret_cast<VirtualInputDevice*>(ptr);
88     delete virtualInputDevice;
89 }
90 
91 // Native methods for VirtualDpad
nativeWriteDpadKeyEvent(JNIEnv * env,jobject thiz,jlong ptr,jint androidKeyCode,jint action,jlong eventTimeNanos)92 static bool nativeWriteDpadKeyEvent(JNIEnv* env, jobject thiz, jlong ptr, jint androidKeyCode,
93                                     jint action, jlong eventTimeNanos) {
94     VirtualDpad* virtualDpad = reinterpret_cast<VirtualDpad*>(ptr);
95     return virtualDpad->writeDpadKeyEvent(androidKeyCode, action,
96                                           std::chrono::nanoseconds(eventTimeNanos));
97 }
98 
99 // Native methods for VirtualKeyboard
nativeWriteKeyEvent(JNIEnv * env,jobject thiz,jlong ptr,jint androidKeyCode,jint action,jlong eventTimeNanos)100 static bool nativeWriteKeyEvent(JNIEnv* env, jobject thiz, jlong ptr, jint androidKeyCode,
101                                 jint action, jlong eventTimeNanos) {
102     VirtualKeyboard* virtualKeyboard = reinterpret_cast<VirtualKeyboard*>(ptr);
103     return virtualKeyboard->writeKeyEvent(androidKeyCode, action,
104                                           std::chrono::nanoseconds(eventTimeNanos));
105 }
106 
107 // 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)108 static bool nativeWriteTouchEvent(JNIEnv* env, jobject thiz, jlong ptr, jint pointerId,
109                                   jint toolType, jint action, jfloat locationX, jfloat locationY,
110                                   jfloat pressure, jfloat majorAxisSize, jlong eventTimeNanos) {
111     VirtualTouchscreen* virtualTouchscreen = reinterpret_cast<VirtualTouchscreen*>(ptr);
112     return virtualTouchscreen->writeTouchEvent(pointerId, toolType, action, locationX, locationY,
113                                                pressure, majorAxisSize,
114                                                std::chrono::nanoseconds(eventTimeNanos));
115 }
116 
117 // Native methods for VirtualMouse
nativeWriteButtonEvent(JNIEnv * env,jobject thiz,jlong ptr,jint buttonCode,jint action,jlong eventTimeNanos)118 static bool nativeWriteButtonEvent(JNIEnv* env, jobject thiz, jlong ptr, jint buttonCode,
119                                    jint action, jlong eventTimeNanos) {
120     VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
121     return virtualMouse->writeButtonEvent(buttonCode, action,
122                                           std::chrono::nanoseconds(eventTimeNanos));
123 }
124 
nativeWriteRelativeEvent(JNIEnv * env,jobject thiz,jlong ptr,jfloat relativeX,jfloat relativeY,jlong eventTimeNanos)125 static bool nativeWriteRelativeEvent(JNIEnv* env, jobject thiz, jlong ptr, jfloat relativeX,
126                                      jfloat relativeY, jlong eventTimeNanos) {
127     VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
128     return virtualMouse->writeRelativeEvent(relativeX, relativeY,
129                                             std::chrono::nanoseconds(eventTimeNanos));
130 }
131 
nativeWriteScrollEvent(JNIEnv * env,jobject thiz,jlong ptr,jfloat xAxisMovement,jfloat yAxisMovement,jlong eventTimeNanos)132 static bool nativeWriteScrollEvent(JNIEnv* env, jobject thiz, jlong ptr, jfloat xAxisMovement,
133                                    jfloat yAxisMovement, jlong eventTimeNanos) {
134     VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
135     return virtualMouse->writeScrollEvent(xAxisMovement, yAxisMovement,
136                                           std::chrono::nanoseconds(eventTimeNanos));
137 }
138 
139 // 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)140 static bool nativeWriteStylusMotionEvent(JNIEnv* env, jobject thiz, jlong ptr, jint toolType,
141                                          jint action, jint locationX, jint locationY, jint pressure,
142                                          jint tiltX, jint tiltY, jlong eventTimeNanos) {
143     VirtualStylus* virtualStylus = reinterpret_cast<VirtualStylus*>(ptr);
144     return virtualStylus->writeMotionEvent(toolType, action, locationX, locationY, pressure, tiltX,
145                                            tiltY, std::chrono::nanoseconds(eventTimeNanos));
146 }
147 
nativeWriteStylusButtonEvent(JNIEnv * env,jobject thiz,jlong ptr,jint buttonCode,jint action,jlong eventTimeNanos)148 static bool nativeWriteStylusButtonEvent(JNIEnv* env, jobject thiz, jlong ptr, jint buttonCode,
149                                          jint action, jlong eventTimeNanos) {
150     VirtualStylus* virtualStylus = reinterpret_cast<VirtualStylus*>(ptr);
151     return virtualStylus->writeButtonEvent(buttonCode, action,
152                                            std::chrono::nanoseconds(eventTimeNanos));
153 }
154 
nativeWriteRotaryEncoderScrollEvent(JNIEnv * env,jobject thiz,jlong ptr,jfloat scrollAmount,jlong eventTimeNanos)155 static bool nativeWriteRotaryEncoderScrollEvent(JNIEnv* env, jobject thiz, jlong ptr,
156                                                 jfloat scrollAmount, jlong eventTimeNanos) {
157     VirtualRotaryEncoder* virtualRotaryEncoder = reinterpret_cast<VirtualRotaryEncoder*>(ptr);
158     return virtualRotaryEncoder->writeScrollEvent(scrollAmount,
159                                                   std::chrono::nanoseconds(eventTimeNanos));
160 }
161 
162 static JNINativeMethod methods[] = {
nativeOpenUinputDpad(Ljava/lang/String;IILjava/lang/String;)163         {"nativeOpenUinputDpad", "(Ljava/lang/String;IILjava/lang/String;)J",
164          (void*)nativeOpenUinputDpad},
nativeOpenUinputKeyboard(Ljava/lang/String;IILjava/lang/String;)165         {"nativeOpenUinputKeyboard", "(Ljava/lang/String;IILjava/lang/String;)J",
166          (void*)nativeOpenUinputKeyboard},
nativeOpenUinputMouse(Ljava/lang/String;IILjava/lang/String;)167         {"nativeOpenUinputMouse", "(Ljava/lang/String;IILjava/lang/String;)J",
168          (void*)nativeOpenUinputMouse},
nativeOpenUinputTouchscreen(Ljava/lang/String;IILjava/lang/String;II)169         {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IILjava/lang/String;II)J",
170          (void*)nativeOpenUinputTouchscreen},
nativeOpenUinputStylus(Ljava/lang/String;IILjava/lang/String;II)171         {"nativeOpenUinputStylus", "(Ljava/lang/String;IILjava/lang/String;II)J",
172          (void*)nativeOpenUinputStylus},
nativeOpenUinputRotaryEncoder(Ljava/lang/String;IILjava/lang/String;)173         {"nativeOpenUinputRotaryEncoder", "(Ljava/lang/String;IILjava/lang/String;)J",
174          (void*)nativeOpenUinputRotaryEncoder},
nativeCloseUinput(J)175         {"nativeCloseUinput", "(J)V", (void*)nativeCloseUinput},
nativeWriteDpadKeyEvent(JIIJ)176         {"nativeWriteDpadKeyEvent", "(JIIJ)Z", (void*)nativeWriteDpadKeyEvent},
nativeWriteKeyEvent(JIIJ)177         {"nativeWriteKeyEvent", "(JIIJ)Z", (void*)nativeWriteKeyEvent},
nativeWriteButtonEvent(JIIJ)178         {"nativeWriteButtonEvent", "(JIIJ)Z", (void*)nativeWriteButtonEvent},
nativeWriteTouchEvent(JIIIFFFFJ)179         {"nativeWriteTouchEvent", "(JIIIFFFFJ)Z", (void*)nativeWriteTouchEvent},
nativeWriteRelativeEvent(JFFJ)180         {"nativeWriteRelativeEvent", "(JFFJ)Z", (void*)nativeWriteRelativeEvent},
nativeWriteScrollEvent(JFFJ)181         {"nativeWriteScrollEvent", "(JFFJ)Z", (void*)nativeWriteScrollEvent},
nativeWriteStylusMotionEvent(JIIIIIIIJ)182         {"nativeWriteStylusMotionEvent", "(JIIIIIIIJ)Z", (void*)nativeWriteStylusMotionEvent},
nativeWriteStylusButtonEvent(JIIJ)183         {"nativeWriteStylusButtonEvent", "(JIIJ)Z", (void*)nativeWriteStylusButtonEvent},
nativeWriteRotaryEncoderScrollEvent(JFJ)184         {"nativeWriteRotaryEncoderScrollEvent", "(JFJ)Z",
185          (void*)nativeWriteRotaryEncoderScrollEvent},
186 };
187 
register_android_server_companion_virtual_InputController(JNIEnv * env)188 int register_android_server_companion_virtual_InputController(JNIEnv* env) {
189     return jniRegisterNativeMethods(env, "com/android/server/companion/virtual/InputController",
190                                     methods, NELEM(methods));
191 }
192 
193 } // namespace android
194