1 /*
2 * Copyright (C) 2020 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 #pragma once
18
19 #include <android-base/unique_fd.h>
20 #include <gtest/gtest.h>
21 #include <inttypes.h>
22 #include <linux/uinput.h>
23 #include <log/log.h>
24 #include <ui/Point.h>
25 #include <ui/Rect.h>
26
27 #include <memory>
28
29 namespace android {
30
31 // This is the factory method that must be used to create a UinputDevice.
32 template <class D, class... Ts>
createUinputDevice(Ts...args)33 std::unique_ptr<D> createUinputDevice(Ts... args) {
34 // Using `new` to access non-public constructors.
35 std::unique_ptr<D> dev(new D(args...));
36 EXPECT_NO_FATAL_FAILURE(dev->init());
37 return dev;
38 }
39
40 // --- UinputDevice ---
41
42 class UinputDevice {
43 public:
44 virtual ~UinputDevice();
45
getName()46 inline const char* getName() const { return mName; }
47
48 // Subclasses must either provide a public constructor or must be-friend the factory method.
49 template <class D, class... Ts>
50 friend std::unique_ptr<D> createUinputDevice(Ts... args);
51
52 protected:
53 const char* mName;
54 const int16_t mProductId;
55
56 explicit UinputDevice(const char* name, int16_t productId);
57
58 // Signals which types of events this device supports before it is created.
59 // This must be overridden by subclasses.
60 virtual void configureDevice(int fd, uinput_user_dev* device) = 0;
61
62 void injectEvent(uint16_t type, uint16_t code, int32_t value);
63
64 private:
65 base::unique_fd mDeviceFd;
66
67 // This is called once by the factory method createUinputDevice().
68 void init();
69 };
70
71 // --- UinputKeyboard ---
72
73 class UinputKeyboard : public UinputDevice {
74 public:
75 static constexpr const char* KEYBOARD_NAME = "Test Uinput Keyboard Device";
76 static constexpr int16_t PRODUCT_ID = 42;
77
78 // Injects key press and sync.
79 void pressKey(int key);
80 // Injects key release and sync.
81 void releaseKey(int key);
82 // Injects 4 events: key press, sync, key release, and sync.
83 void pressAndReleaseKey(int key);
84
85 template <class D, class... Ts>
86 friend std::unique_ptr<D> createUinputDevice(Ts... args);
87
88 protected:
89 explicit UinputKeyboard(const char* name, int16_t productId = PRODUCT_ID,
90 std::initializer_list<int> keys = {});
91
92 void configureDevice(int fd, uinput_user_dev* device) override;
93
94 private:
95 std::set<int> mKeys;
96 };
97
98 // --- UinputHomeKey---
99
100 // A keyboard device that has a single HOME key.
101 class UinputHomeKey : public UinputKeyboard {
102 public:
103 static constexpr const char* DEVICE_NAME = "Test Uinput Home Key";
104 static constexpr int16_t PRODUCT_ID = 43;
105
106 // Injects 4 events: key press, sync, key release, and sync.
107 void pressAndReleaseHomeKey();
108
109 template <class D, class... Ts>
110 friend std::unique_ptr<D> createUinputDevice(Ts... args);
111
112 private:
113 explicit UinputHomeKey();
114 };
115
116 // --- UinputSteamController ---
117
118 // A joystick device that sends a BTN_GEAR_DOWN / BTN_WHEEL key.
119 class UinputSteamController : public UinputKeyboard {
120 public:
121 static constexpr const char* DEVICE_NAME = "Test Uinput Steam Controller";
122 static constexpr int16_t PRODUCT_ID = 44;
123
124 template <class D, class... Ts>
125 friend std::unique_ptr<D> createUinputDevice(Ts... args);
126
127 private:
128 explicit UinputSteamController();
129 };
130
131 // --- UinputExternalStylus ---
132
133 // A stylus that reports button presses.
134 class UinputExternalStylus : public UinputKeyboard {
135 public:
136 static constexpr const char* DEVICE_NAME = "Test Uinput External Stylus";
137 static constexpr int16_t PRODUCT_ID = 45;
138
139 template <class D, class... Ts>
140 friend std::unique_ptr<D> createUinputDevice(Ts... args);
141
142 private:
143 explicit UinputExternalStylus();
144 };
145
146 // --- UinputExternalStylusWithPressure ---
147
148 // A stylus that reports button presses and pressure values.
149 class UinputExternalStylusWithPressure : public UinputKeyboard {
150 public:
151 static constexpr const char* DEVICE_NAME = "Test Uinput External Stylus With Pressure";
152 static constexpr int16_t PRODUCT_ID = 46;
153
154 static constexpr int32_t RAW_PRESSURE_MIN = 0;
155 static constexpr int32_t RAW_PRESSURE_MAX = 255;
156
157 void setPressure(int32_t pressure);
158
159 template <class D, class... Ts>
160 friend std::unique_ptr<D> createUinputDevice(Ts... args);
161
162 private:
163 void configureDevice(int fd, uinput_user_dev* device) override;
164
165 explicit UinputExternalStylusWithPressure();
166 };
167
168 // --- UinputKeyboardWithUsage ---
169 // A keyboard that supports EV_MSC MSC_SCAN through which it can report HID usage codes.
170
171 class UinputKeyboardWithHidUsage : public UinputKeyboard {
172 public:
173 static constexpr const char* DEVICE_NAME = "Test Uinput Keyboard With Usage";
174 static constexpr int16_t PRODUCT_ID = 47;
175
176 template <class D, class... Ts>
177 friend std::unique_ptr<D> createUinputDevice(Ts... args);
178
179 protected:
180 explicit UinputKeyboardWithHidUsage(std::initializer_list<int> keys);
181
182 void configureDevice(int fd, uinput_user_dev* device) override;
183 };
184
185 // --- UinputTouchScreen ---
186
187 // A multi-touch touchscreen device with specific size that also supports styluses.
188 class UinputTouchScreen : public UinputKeyboard {
189 public:
190 static constexpr const char* DEVICE_NAME = "Test Uinput Touch Screen";
191 static constexpr int16_t PRODUCT_ID = 48;
192
193 static const int32_t RAW_TOUCH_MIN = 0;
194 static const int32_t RAW_TOUCH_MAX = 31;
195 static const int32_t RAW_ID_MIN = 0;
196 static const int32_t RAW_ID_MAX = 9;
197 static const int32_t RAW_SLOT_MIN = 0;
198 static const int32_t RAW_SLOT_MAX = 9;
199 static const int32_t RAW_PRESSURE_MIN = 0;
200 static const int32_t RAW_PRESSURE_MAX = 255;
201
202 template <class D, class... Ts>
203 friend std::unique_ptr<D> createUinputDevice(Ts... args);
204
205 void sendSlot(int32_t slot);
206 void sendTrackingId(int32_t trackingId);
207 void sendDown(const Point& point);
208 void sendMove(const Point& point);
209 void sendPressure(int32_t pressure);
210 void sendPointerUp();
211 void sendUp();
212 void sendToolType(int32_t toolType);
213 void sendSync();
214
215 const Point getCenterPoint();
216
217 protected:
218 explicit UinputTouchScreen(const Rect& size, const std::string& physicalPort = "");
219
220 private:
221 void configureDevice(int fd, uinput_user_dev* device) override;
222 const Rect mSize;
223 const std::string mPhysicalPort;
224 };
225
226 } // namespace android
227