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