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