1 //
2 // Copyright 2010 The Android Open Source Project
3 //
4
5 #include <ui/InputDispatcher.h>
6 #include <gtest/gtest.h>
7 #include <linux/input.h>
8
9 namespace android {
10
11 // An arbitrary time value.
12 static const nsecs_t ARBITRARY_TIME = 1234;
13
14 // An arbitrary device id.
15 static const int32_t DEVICE_ID = 1;
16
17 // An arbitrary injector pid / uid pair that has permission to inject events.
18 static const int32_t INJECTOR_PID = 999;
19 static const int32_t INJECTOR_UID = 1001;
20
21
22 // --- FakeInputDispatcherPolicy ---
23
24 class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
25 protected:
~FakeInputDispatcherPolicy()26 virtual ~FakeInputDispatcherPolicy() {
27 }
28
29 public:
FakeInputDispatcherPolicy()30 FakeInputDispatcherPolicy() {
31 }
32
33 private:
notifyConfigurationChanged(nsecs_t when)34 virtual void notifyConfigurationChanged(nsecs_t when) {
35 }
36
notifyANR(const sp<InputApplicationHandle> & inputApplicationHandle,const sp<InputChannel> & inputChannel)37 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
38 const sp<InputChannel>& inputChannel) {
39 return 0;
40 }
41
notifyInputChannelBroken(const sp<InputChannel> & inputChannel)42 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
43 }
44
getKeyRepeatTimeout()45 virtual nsecs_t getKeyRepeatTimeout() {
46 return 500 * 1000000LL;
47 }
48
getKeyRepeatDelay()49 virtual nsecs_t getKeyRepeatDelay() {
50 return 50 * 1000000LL;
51 }
52
getMaxEventsPerSecond()53 virtual int32_t getMaxEventsPerSecond() {
54 return 60;
55 }
56
interceptKeyBeforeQueueing(nsecs_t when,int32_t deviceId,int32_t action,int32_t & flags,int32_t keyCode,int32_t scanCode,uint32_t & policyFlags)57 virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId,
58 int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode,
59 uint32_t& policyFlags) {
60 }
61
interceptGenericBeforeQueueing(nsecs_t when,uint32_t & policyFlags)62 virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
63 }
64
interceptKeyBeforeDispatching(const sp<InputChannel> & inputChannel,const KeyEvent * keyEvent,uint32_t policyFlags)65 virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
66 const KeyEvent* keyEvent, uint32_t policyFlags) {
67 return false;
68 }
69
notifySwitch(nsecs_t when,int32_t switchCode,int32_t switchValue,uint32_t policyFlags)70 virtual void notifySwitch(nsecs_t when,
71 int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
72 }
73
pokeUserActivity(nsecs_t eventTime,int32_t eventType)74 virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
75 }
76
checkInjectEventsPermissionNonReentrant(int32_t injectorPid,int32_t injectorUid)77 virtual bool checkInjectEventsPermissionNonReentrant(
78 int32_t injectorPid, int32_t injectorUid) {
79 return false;
80 }
81 };
82
83
84 // --- InputDispatcherTest ---
85
86 class InputDispatcherTest : public testing::Test {
87 protected:
88 sp<FakeInputDispatcherPolicy> mFakePolicy;
89 sp<InputDispatcher> mDispatcher;
90
SetUp()91 virtual void SetUp() {
92 mFakePolicy = new FakeInputDispatcherPolicy();
93 mDispatcher = new InputDispatcher(mFakePolicy);
94 }
95
TearDown()96 virtual void TearDown() {
97 mFakePolicy.clear();
98 mDispatcher.clear();
99 }
100 };
101
102
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesKeyEvents)103 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
104 KeyEvent event;
105
106 // Rejects undefined key actions.
107 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
108 /*action*/ -1, 0,
109 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
110 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
111 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
112 << "Should reject key events with undefined action.";
113
114 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
115 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
116 AKEY_EVENT_ACTION_MULTIPLE, 0,
117 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
118 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
119 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
120 << "Should reject key events with ACTION_MULTIPLE.";
121 }
122
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesMotionEvents)123 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
124 MotionEvent event;
125 int32_t pointerIds[MAX_POINTERS + 1];
126 PointerCoords pointerCoords[MAX_POINTERS + 1];
127 for (int i = 0; i <= MAX_POINTERS; i++) {
128 pointerIds[i] = i;
129 }
130
131 // Rejects undefined motion actions.
132 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
133 /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
134 ARBITRARY_TIME, ARBITRARY_TIME,
135 /*pointerCount*/ 1, pointerIds, pointerCoords);
136 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
137 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
138 << "Should reject motion events with undefined action.";
139
140 // Rejects pointer down with invalid index.
141 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
142 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
143 0, 0, AMETA_NONE, 0, 0, 0, 0,
144 ARBITRARY_TIME, ARBITRARY_TIME,
145 /*pointerCount*/ 1, pointerIds, pointerCoords);
146 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
147 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
148 << "Should reject motion events with pointer down index too large.";
149
150 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
151 AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
152 0, 0, AMETA_NONE, 0, 0, 0, 0,
153 ARBITRARY_TIME, ARBITRARY_TIME,
154 /*pointerCount*/ 1, pointerIds, pointerCoords);
155 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
156 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
157 << "Should reject motion events with pointer down index too small.";
158
159 // Rejects pointer up with invalid index.
160 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
161 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
162 0, 0, AMETA_NONE, 0, 0, 0, 0,
163 ARBITRARY_TIME, ARBITRARY_TIME,
164 /*pointerCount*/ 1, pointerIds, pointerCoords);
165 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
166 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
167 << "Should reject motion events with pointer up index too large.";
168
169 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
170 AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
171 0, 0, AMETA_NONE, 0, 0, 0, 0,
172 ARBITRARY_TIME, ARBITRARY_TIME,
173 /*pointerCount*/ 1, pointerIds, pointerCoords);
174 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
175 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
176 << "Should reject motion events with pointer up index too small.";
177
178 // Rejects motion events with invalid number of pointers.
179 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
180 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
181 ARBITRARY_TIME, ARBITRARY_TIME,
182 /*pointerCount*/ 0, pointerIds, pointerCoords);
183 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
184 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
185 << "Should reject motion events with 0 pointers.";
186
187 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
188 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
189 ARBITRARY_TIME, ARBITRARY_TIME,
190 /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
191 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
192 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
193 << "Should reject motion events with more than MAX_POINTERS pointers.";
194
195 // Rejects motion events with invalid pointer ids.
196 pointerIds[0] = -1;
197 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
198 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
199 ARBITRARY_TIME, ARBITRARY_TIME,
200 /*pointerCount*/ 1, pointerIds, pointerCoords);
201 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
202 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
203 << "Should reject motion events with pointer ids less than 0.";
204
205 pointerIds[0] = MAX_POINTER_ID + 1;
206 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
207 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
208 ARBITRARY_TIME, ARBITRARY_TIME,
209 /*pointerCount*/ 1, pointerIds, pointerCoords);
210 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
211 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
212 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
213
214 // Rejects motion events with duplicate pointer ids.
215 pointerIds[0] = 1;
216 pointerIds[1] = 1;
217 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
218 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
219 ARBITRARY_TIME, ARBITRARY_TIME,
220 /*pointerCount*/ 2, pointerIds, pointerCoords);
221 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
222 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
223 << "Should reject motion events with duplicate pointer ids.";
224 }
225
226 } // namespace android
227