1 /*
2 * Copyright (C) 2010 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 #include "../InputDispatcher.h"
18
19 #include <gtest/gtest.h>
20 #include <linux/input.h>
21
22 namespace android {
23
24 // An arbitrary time value.
25 static const nsecs_t ARBITRARY_TIME = 1234;
26
27 // An arbitrary device id.
28 static const int32_t DEVICE_ID = 1;
29
30 // An arbitrary display id.
31 static const int32_t DISPLAY_ID = 0;
32
33 // An arbitrary injector pid / uid pair that has permission to inject events.
34 static const int32_t INJECTOR_PID = 999;
35 static const int32_t INJECTOR_UID = 1001;
36
37
38 // --- FakeInputDispatcherPolicy ---
39
40 class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
41 InputDispatcherConfiguration mConfig;
42
43 protected:
~FakeInputDispatcherPolicy()44 virtual ~FakeInputDispatcherPolicy() {
45 }
46
47 public:
FakeInputDispatcherPolicy()48 FakeInputDispatcherPolicy() {
49 }
50
51 private:
notifyConfigurationChanged(nsecs_t)52 virtual void notifyConfigurationChanged(nsecs_t) {
53 }
54
notifyANR(const sp<InputApplicationHandle> &,const sp<InputWindowHandle> &,const String8 &)55 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
56 const sp<InputWindowHandle>&,
57 const String8&) {
58 return 0;
59 }
60
notifyInputChannelBroken(const sp<InputWindowHandle> &)61 virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) {
62 }
63
getDispatcherConfiguration(InputDispatcherConfiguration * outConfig)64 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
65 *outConfig = mConfig;
66 }
67
filterInputEvent(const InputEvent *,uint32_t)68 virtual bool filterInputEvent(const InputEvent*, uint32_t) {
69 return true;
70 }
71
interceptKeyBeforeQueueing(const KeyEvent *,uint32_t &)72 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
73 }
74
interceptMotionBeforeQueueing(nsecs_t,uint32_t &)75 virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
76 }
77
interceptKeyBeforeDispatching(const sp<InputWindowHandle> &,const KeyEvent *,uint32_t)78 virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&,
79 const KeyEvent*, uint32_t) {
80 return 0;
81 }
82
dispatchUnhandledKey(const sp<InputWindowHandle> &,const KeyEvent *,uint32_t,KeyEvent *)83 virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&,
84 const KeyEvent*, uint32_t, KeyEvent*) {
85 return false;
86 }
87
notifySwitch(nsecs_t,uint32_t,uint32_t,uint32_t)88 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
89 }
90
pokeUserActivity(nsecs_t,int32_t)91 virtual void pokeUserActivity(nsecs_t, int32_t) {
92 }
93
checkInjectEventsPermissionNonReentrant(int32_t,int32_t)94 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
95 return false;
96 }
97 };
98
99
100 // --- InputDispatcherTest ---
101
102 class InputDispatcherTest : public testing::Test {
103 protected:
104 sp<FakeInputDispatcherPolicy> mFakePolicy;
105 sp<InputDispatcher> mDispatcher;
106
SetUp()107 virtual void SetUp() {
108 mFakePolicy = new FakeInputDispatcherPolicy();
109 mDispatcher = new InputDispatcher(mFakePolicy);
110 }
111
TearDown()112 virtual void TearDown() {
113 mFakePolicy.clear();
114 mDispatcher.clear();
115 }
116 };
117
118
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesKeyEvents)119 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
120 KeyEvent event;
121
122 // Rejects undefined key actions.
123 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
124 /*action*/ -1, 0,
125 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
126 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
127 &event, DISPLAY_ID,
128 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
129 << "Should reject key events with undefined action.";
130
131 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
132 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
133 AKEY_EVENT_ACTION_MULTIPLE, 0,
134 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
135 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
136 &event, DISPLAY_ID,
137 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
138 << "Should reject key events with ACTION_MULTIPLE.";
139 }
140
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesMotionEvents)141 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
142 MotionEvent event;
143 PointerProperties pointerProperties[MAX_POINTERS + 1];
144 PointerCoords pointerCoords[MAX_POINTERS + 1];
145 for (int i = 0; i <= MAX_POINTERS; i++) {
146 pointerProperties[i].clear();
147 pointerProperties[i].id = i;
148 pointerCoords[i].clear();
149 }
150
151 // Rejects undefined motion actions.
152 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
153 /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
154 ARBITRARY_TIME, ARBITRARY_TIME,
155 /*pointerCount*/ 1, pointerProperties, pointerCoords);
156 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
157 &event, DISPLAY_ID,
158 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
159 << "Should reject motion events with undefined action.";
160
161 // Rejects pointer down with invalid index.
162 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
163 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
164 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
165 ARBITRARY_TIME, ARBITRARY_TIME,
166 /*pointerCount*/ 1, pointerProperties, pointerCoords);
167 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
168 &event, DISPLAY_ID,
169 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
170 << "Should reject motion events with pointer down index too large.";
171
172 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
173 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
174 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
175 ARBITRARY_TIME, ARBITRARY_TIME,
176 /*pointerCount*/ 1, pointerProperties, pointerCoords);
177 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
178 &event, DISPLAY_ID,
179 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
180 << "Should reject motion events with pointer down index too small.";
181
182 // Rejects pointer up with invalid index.
183 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
184 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
185 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
186 ARBITRARY_TIME, ARBITRARY_TIME,
187 /*pointerCount*/ 1, pointerProperties, pointerCoords);
188 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
189 &event, DISPLAY_ID,
190 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
191 << "Should reject motion events with pointer up index too large.";
192
193 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
194 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
195 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
196 ARBITRARY_TIME, ARBITRARY_TIME,
197 /*pointerCount*/ 1, pointerProperties, pointerCoords);
198 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
199 &event, DISPLAY_ID,
200 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
201 << "Should reject motion events with pointer up index too small.";
202
203 // Rejects motion events with invalid number of pointers.
204 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
205 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
206 ARBITRARY_TIME, ARBITRARY_TIME,
207 /*pointerCount*/ 0, pointerProperties, pointerCoords);
208 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
209 &event, DISPLAY_ID,
210 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
211 << "Should reject motion events with 0 pointers.";
212
213 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
214 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
215 ARBITRARY_TIME, ARBITRARY_TIME,
216 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
217 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
218 &event, DISPLAY_ID,
219 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
220 << "Should reject motion events with more than MAX_POINTERS pointers.";
221
222 // Rejects motion events with invalid pointer ids.
223 pointerProperties[0].id = -1;
224 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
225 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
226 ARBITRARY_TIME, ARBITRARY_TIME,
227 /*pointerCount*/ 1, pointerProperties, pointerCoords);
228 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
229 &event, DISPLAY_ID,
230 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
231 << "Should reject motion events with pointer ids less than 0.";
232
233 pointerProperties[0].id = MAX_POINTER_ID + 1;
234 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
235 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
236 ARBITRARY_TIME, ARBITRARY_TIME,
237 /*pointerCount*/ 1, pointerProperties, pointerCoords);
238 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
239 &event, DISPLAY_ID,
240 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
241 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
242
243 // Rejects motion events with duplicate pointer ids.
244 pointerProperties[0].id = 1;
245 pointerProperties[1].id = 1;
246 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
247 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
248 ARBITRARY_TIME, ARBITRARY_TIME,
249 /*pointerCount*/ 2, pointerProperties, pointerCoords);
250 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
251 &event, DISPLAY_ID,
252 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
253 << "Should reject motion events with duplicate pointer ids.";
254 }
255
256 } // namespace android
257