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 #ifndef _UI_TEST_INPUT_UINPUT_INJECTOR_H
18 #define _UI_TEST_INPUT_UINPUT_INJECTOR_H
19 
20 #include <android-base/unique_fd.h>
21 #include <gtest/gtest.h>
22 #include <inttypes.h>
23 #include <linux/uinput.h>
24 #include <log/log.h>
25 #include <ui/Point.h>
26 #include <ui/Rect.h>
27 
28 #include <memory>
29 
30 namespace android {
31 
32 // This is the factory method that must be used to create a UinputDevice.
33 template <class D, class... Ts>
createUinputDevice(Ts...args)34 std::unique_ptr<D> createUinputDevice(Ts... args) {
35     // Using `new` to access non-public constructors.
36     std::unique_ptr<D> dev(new D(&args...));
37     EXPECT_NO_FATAL_FAILURE(dev->init());
38     return dev;
39 }
40 
41 // --- UinputDevice ---
42 
43 class UinputDevice {
44 public:
45     virtual ~UinputDevice();
46 
getName()47     inline const char* getName() const { return mName; }
48 
49     // Subclasses must either provide a public constructor or must be-friend the factory method.
50     template <class D, class... Ts>
51     friend std::unique_ptr<D> createUinputDevice(Ts... args);
52 
53 protected:
54     const char* mName;
55 
56     UinputDevice(const char* name);
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 Keyboard Device";
76 
77     // Injects key press and sync.
78     void pressKey(int key);
79     // Injects key release and sync.
80     void releaseKey(int key);
81     // Injects 4 events: key press, sync, key release, and sync.
82     void pressAndReleaseKey(int key);
83 
84     template <class D, class... Ts>
85     friend std::unique_ptr<D> createUinputDevice(Ts... args);
86 
87 protected:
88     UinputKeyboard(std::initializer_list<int> keys = {});
89 
90 private:
91     void configureDevice(int fd, uinput_user_dev* device) override;
92 
93     std::set<int> mKeys;
94 };
95 
96 // --- UinputHomeKey---
97 
98 // A keyboard device that has a single HOME key.
99 class UinputHomeKey : public UinputKeyboard {
100 public:
101     // Injects 4 events: key press, sync, key release, and sync.
102     void pressAndReleaseHomeKey();
103 
104     template <class D, class... Ts>
105     friend std::unique_ptr<D> createUinputDevice(Ts... args);
106 
107 private:
108     UinputHomeKey();
109 };
110 
111 // A joystick device that sends a BTN_GEAR_DOWN / BTN_WHEEL key.
112 class UinputSteamController : public UinputKeyboard {
113 public:
114     template <class D, class... Ts>
115     friend std::unique_ptr<D> createUinputDevice(Ts... args);
116 
117 private:
118     UinputSteamController();
119 };
120 
121 // --- UinputTouchScreen ---
122 // A touch screen device with specific size.
123 class UinputTouchScreen : public UinputDevice {
124 public:
125     static constexpr const char* DEVICE_NAME = "Test Touch Screen";
126     static const int32_t RAW_TOUCH_MIN = 0;
127     static const int32_t RAW_TOUCH_MAX = 31;
128     static const int32_t RAW_ID_MIN = 0;
129     static const int32_t RAW_ID_MAX = 9;
130     static const int32_t RAW_SLOT_MIN = 0;
131     static const int32_t RAW_SLOT_MAX = 9;
132     static const int32_t RAW_PRESSURE_MIN = 0;
133     static const int32_t RAW_PRESSURE_MAX = 255;
134 
135     template <class D, class... Ts>
136     friend std::unique_ptr<D> createUinputDevice(Ts... args);
137 
138     void sendSlot(int32_t slot);
139     void sendTrackingId(int32_t trackingId);
140     void sendDown(const Point& point);
141     void sendMove(const Point& point);
142     void sendUp();
143     void sendToolType(int32_t toolType);
144 
145     const Point getCenterPoint();
146 
147 protected:
148     UinputTouchScreen(const Rect* size);
149 
150 private:
151     void configureDevice(int fd, uinput_user_dev* device) override;
152     const Rect mSize;
153 };
154 
155 } // namespace android
156 
157 #endif // _UI_TEST_INPUT_UINPUT_INJECTOR_H
158