blob: 2bbfb1b9b7dafb7cec3fed15ff6b529770914bda [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
Jeff Brownf086ddb2014-02-11 14:28:48 -080030// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080031static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080032
Michael Wrightd02c5b62014-02-10 15:10:22 -080033// An arbitrary injector pid / uid pair that has permission to inject events.
34static const int32_t INJECTOR_PID = 999;
35static const int32_t INJECTOR_UID = 1001;
36
37
38// --- FakeInputDispatcherPolicy ---
39
40class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
41 InputDispatcherConfiguration mConfig;
42
43protected:
44 virtual ~FakeInputDispatcherPolicy() {
45 }
46
47public:
48 FakeInputDispatcherPolicy() {
49 }
50
51private:
Narayan Kamath39efe3e2014-10-17 10:37:08 +010052 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080053 }
54
Narayan Kamath39efe3e2014-10-17 10:37:08 +010055 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
56 const sp<InputWindowHandle>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080057 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080058 return 0;
59 }
60
Narayan Kamath39efe3e2014-10-17 10:37:08 +010061 virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080062 }
63
64 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
65 *outConfig = mConfig;
66 }
67
Narayan Kamath39efe3e2014-10-17 10:37:08 +010068 virtual bool filterInputEvent(const InputEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080069 return true;
70 }
71
Narayan Kamath39efe3e2014-10-17 10:37:08 +010072 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080073 }
74
Narayan Kamath39efe3e2014-10-17 10:37:08 +010075 virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080076 }
77
Narayan Kamath39efe3e2014-10-17 10:37:08 +010078 virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&,
79 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080080 return 0;
81 }
82
Narayan Kamath39efe3e2014-10-17 10:37:08 +010083 virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&,
84 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080085 return false;
86 }
87
Narayan Kamath39efe3e2014-10-17 10:37:08 +010088 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080089 }
90
Narayan Kamath39efe3e2014-10-17 10:37:08 +010091 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080092 }
93
Narayan Kamath39efe3e2014-10-17 10:37:08 +010094 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080095 return false;
96 }
97};
98
99
100// --- InputDispatcherTest ---
101
102class InputDispatcherTest : public testing::Test {
103protected:
104 sp<FakeInputDispatcherPolicy> mFakePolicy;
105 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800106 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800107
108 virtual void SetUp() {
109 mFakePolicy = new FakeInputDispatcherPolicy();
110 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800111 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
112 //Start InputDispatcher thread
113 mDispatcherThread = new InputDispatcherThread(mDispatcher);
114 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800115 }
116
117 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800118 mDispatcherThread->requestExit();
119 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120 mFakePolicy.clear();
121 mDispatcher.clear();
122 }
123};
124
125
126TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
127 KeyEvent event;
128
129 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100130 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800131 /*action*/ -1, 0,
132 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800133 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800134 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800135 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
136 << "Should reject key events with undefined action.";
137
138 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100139 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800140 AKEY_EVENT_ACTION_MULTIPLE, 0,
141 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800142 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800143 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800144 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
145 << "Should reject key events with ACTION_MULTIPLE.";
146}
147
148TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
149 MotionEvent event;
150 PointerProperties pointerProperties[MAX_POINTERS + 1];
151 PointerCoords pointerCoords[MAX_POINTERS + 1];
152 for (int i = 0; i <= MAX_POINTERS; i++) {
153 pointerProperties[i].clear();
154 pointerProperties[i].id = i;
155 pointerCoords[i].clear();
156 }
157
158 // Rejects undefined motion actions.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800159 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100160 /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161 ARBITRARY_TIME, ARBITRARY_TIME,
162 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800163 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800164 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800165 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
166 << "Should reject motion events with undefined action.";
167
168 // Rejects pointer down with invalid index.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800169 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800170 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100171 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172 ARBITRARY_TIME, ARBITRARY_TIME,
173 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800174 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800175 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
177 << "Should reject motion events with pointer down index too large.";
178
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800179 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800180 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100181 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800182 ARBITRARY_TIME, ARBITRARY_TIME,
183 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800184 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800185 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
187 << "Should reject motion events with pointer down index too small.";
188
189 // Rejects pointer up with invalid index.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800190 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100192 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193 ARBITRARY_TIME, ARBITRARY_TIME,
194 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800195 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800196 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800197 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
198 << "Should reject motion events with pointer up index too large.";
199
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800200 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800201 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100202 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800203 ARBITRARY_TIME, ARBITRARY_TIME,
204 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800205 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800206 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800207 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
208 << "Should reject motion events with pointer up index too small.";
209
210 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800211 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100212 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213 ARBITRARY_TIME, ARBITRARY_TIME,
214 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800215 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800216 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
218 << "Should reject motion events with 0 pointers.";
219
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800220 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100221 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800222 ARBITRARY_TIME, ARBITRARY_TIME,
223 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800224 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800225 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800226 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
227 << "Should reject motion events with more than MAX_POINTERS pointers.";
228
229 // Rejects motion events with invalid pointer ids.
230 pointerProperties[0].id = -1;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800231 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100232 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800233 ARBITRARY_TIME, ARBITRARY_TIME,
234 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800235 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800236 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800237 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
238 << "Should reject motion events with pointer ids less than 0.";
239
240 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800241 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100242 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800243 ARBITRARY_TIME, ARBITRARY_TIME,
244 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800245 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800246 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
248 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
249
250 // Rejects motion events with duplicate pointer ids.
251 pointerProperties[0].id = 1;
252 pointerProperties[1].id = 1;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800253 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100254 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800255 ARBITRARY_TIME, ARBITRARY_TIME,
256 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800257 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800258 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800259 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
260 << "Should reject motion events with duplicate pointer ids.";
261}
262
Arthur Hungb92218b2018-08-14 12:00:21 +0800263// --- InputDispatcherTest SetInputWindowTest ---
264static const int32_t INJECT_EVENT_TIMEOUT = 500;
265static const int32_t DISPATCHING_TIMEOUT = 100;
266
267class FakeApplicationHandle : public InputApplicationHandle {
268public:
269 FakeApplicationHandle() {}
270 virtual ~FakeApplicationHandle() {}
271
272 virtual bool updateInfo() {
273 if (!mInfo) {
274 mInfo = new InputApplicationInfo();
275 }
276 mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
277 return true;
278 }
279};
280
281class FakeWindowHandle : public InputWindowHandle {
282public:
283 static const int32_t WIDTH = 600;
284 static const int32_t HEIGHT = 800;
285
286 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
287 const sp<InputDispatcher>& dispatcher, const std::string name) :
288 InputWindowHandle(inputApplicationHandle), mDispatcher(dispatcher),
289 mName(name), mFocused(false), mDisplayId(ADISPLAY_ID_DEFAULT) {
290 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
291 mConsumer = new InputConsumer(mClientChannel);
292 mDispatcher->registerInputChannel(mServerChannel, this, false);
293 }
294
295 virtual ~FakeWindowHandle() {
296 mDispatcher->unregisterInputChannel(mServerChannel);
297 mServerChannel.clear();
298 mClientChannel.clear();
299 mDispatcher.clear();
300
301 if (mConsumer != nullptr) {
302 delete mConsumer;
303 }
304 }
305
306 virtual bool updateInfo() {
307 if (!mInfo) {
308 mInfo = new InputWindowInfo();
309 }
310 mInfo->inputChannel = mServerChannel;
311 mInfo->name = mName;
312 mInfo->layoutParamsFlags = 0;
313 mInfo->layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
314 mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
315 mInfo->frameLeft = 0;
316 mInfo->frameTop = 0;
317 mInfo->frameRight = WIDTH;
318 mInfo->frameBottom = HEIGHT;
319 mInfo->scaleFactor = 1.0;
320 mInfo->addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
321 mInfo->visible = true;
322 mInfo->canReceiveKeys = true;
323 mInfo->hasFocus = mFocused;
324 mInfo->hasWallpaper = false;
325 mInfo->paused = false;
326 mInfo->layer = 0;
327 mInfo->ownerPid = INJECTOR_PID;
328 mInfo->ownerUid = INJECTOR_UID;
329 mInfo->inputFeatures = 0;
330 mInfo->displayId = mDisplayId;
331
332 return true;
333 }
334
335 void setFocus() {
336 mFocused = true;
337 }
338
339 void setDisplayId(int32_t displayId) {
340 mDisplayId = displayId;
341 }
342
343 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId) {
344 uint32_t consumeSeq;
345 InputEvent* event;
346 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
347 &consumeSeq, &event);
348
349 ASSERT_EQ(OK, status)
350 << mName.c_str() << ": consumer consume should return OK.";
351 ASSERT_TRUE(event != nullptr)
352 << mName.c_str() << ": consumer should have returned non-NULL event.";
353 ASSERT_EQ(expectedEventType, event->getType())
354 << mName.c_str() << ": consumer type should same as expected one.";
355
356 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
357 << mName.c_str() << ": consumer displayId should same as expected one.";
358
359 status = mConsumer->sendFinishedSignal(consumeSeq, true /*handled*/);
360 ASSERT_EQ(OK, status)
361 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
362 }
363
364 void assertNoEvents() {
365 uint32_t consumeSeq;
366 InputEvent* event;
367 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
368 &consumeSeq, &event);
369 ASSERT_NE(OK, status)
370 << mName.c_str()
371 << ": should not have received any events, so consume(..) should not return OK.";
372 }
373
374 private:
375 sp<InputDispatcher> mDispatcher;
376 sp<InputChannel> mServerChannel, mClientChannel;
377 InputConsumer *mConsumer;
378 PreallocatedInputEventFactory mEventFactory;
379
380 std::string mName;
381 bool mFocused;
382 int32_t mDisplayId;
383};
384
Tiger Huang721e26f2018-07-24 22:26:19 +0800385static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
386 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800387 KeyEvent event;
388 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
389
390 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800391 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800392 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
393 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
394
395 // Inject event until dispatch out.
396 return dispatcher->injectInputEvent(
397 &event,
398 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
399 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
400}
401
402static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t displayId) {
403 MotionEvent event;
404 PointerProperties pointerProperties[1];
405 PointerCoords pointerCoords[1];
406
407 pointerProperties[0].clear();
408 pointerProperties[0].id = 0;
409 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
410
411 pointerCoords[0].clear();
412 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
413 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
414
415 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
416 // Define a valid motion down event.
417 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, displayId,
418 AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
419 AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
420 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
421 pointerCoords);
422
423 // Inject event until dispatch out.
424 return dispatcher->injectInputEvent(
425 &event,
426 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
427 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
428}
429
430TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
431 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
432 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window");
433
434 Vector<sp<InputWindowHandle>> inputWindowHandles;
435 inputWindowHandles.add(window);
436
437 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
438 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
439 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
440
441 // Window should receive motion event.
442 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
443}
444
445// The foreground window should receive the first touch down event.
446TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
447 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
448 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top");
449 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
450
451 Vector<sp<InputWindowHandle>> inputWindowHandles;
452 inputWindowHandles.add(windowTop);
453 inputWindowHandles.add(windowSecond);
454
455 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
456 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
457 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
458
459 // Top window should receive the touch down event. Second window should not receive anything.
460 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
461 windowSecond->assertNoEvents();
462}
463
464TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
465 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
466 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top");
467 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");
468
469 // Set focus application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800470 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800471
472 // Expect one focus window exist in display.
473 windowSecond->setFocus();
474 Vector<sp<InputWindowHandle>> inputWindowHandles;
475 inputWindowHandles.add(windowTop);
476 inputWindowHandles.add(windowSecond);
477
478 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
479 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
480 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
481
482 // Focused window should receive event.
483 windowTop->assertNoEvents();
484 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
485}
486
487TEST_F(InputDispatcherTest, SetInputWindow_MultiDisplayTouch) {
488 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
489 sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
490 sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application, mDispatcher, "D_2");
491
492 // Test the primary display touch down.
493 Vector<sp<InputWindowHandle>> inputWindowHandles;
494 inputWindowHandles.push(windowInPrimary);
495
496 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
497 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ADISPLAY_ID_DEFAULT))
498 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
499 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
500 windowInSecondary->assertNoEvents();
501
502 // Test the second display touch down.
503 constexpr int32_t SECOND_DISPLAY_ID = 1;
504 windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
505 Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
506 inputWindowHandles_Second.push(windowInSecondary);
507
508 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
509 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, SECOND_DISPLAY_ID))
510 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
511 windowInPrimary->assertNoEvents();
512 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
513}
514
Arthur Hungb92218b2018-08-14 12:00:21 +0800515TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {
516 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
517 sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
518 sp<FakeApplicationHandle> application2 = new FakeApplicationHandle();
519 sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2");
520
Tiger Huang721e26f2018-07-24 22:26:19 +0800521 constexpr int32_t SECOND_DISPLAY_ID = 1;
522
523 // Set focus to primary display window.
524 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
525 windowInPrimary->setFocus();
526
Arthur Hungb92218b2018-08-14 12:00:21 +0800527 // Set focus to second display window.
Tiger Huang721e26f2018-07-24 22:26:19 +0800528 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
529 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Arthur Hungb92218b2018-08-14 12:00:21 +0800530 windowInSecondary->setFocus();
531
532 // Update all windows per displays.
533 Vector<sp<InputWindowHandle>> inputWindowHandles;
534 inputWindowHandles.push(windowInPrimary);
535 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
536
Arthur Hungb92218b2018-08-14 12:00:21 +0800537 windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
538 Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
539 inputWindowHandles_Second.push(windowInSecondary);
540 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
541
Tiger Huang721e26f2018-07-24 22:26:19 +0800542 // Test inject a key down with display id specified.
543 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
544 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
545 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
546 windowInSecondary->assertNoEvents();
547
548 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800549 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
550 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
551 windowInPrimary->assertNoEvents();
552 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
553
554 // Remove secondary display.
555 inputWindowHandles_Second.clear();
556 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
557
558 // Expect old focus should receive a cancel event.
559 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Tiger Huang721e26f2018-07-24 22:26:19 +0800560 // TODO(b/111361570): Validate that the event here was marked as canceled.
Arthur Hungb92218b2018-08-14 12:00:21 +0800561
562 // Test inject a key down, should timeout because of no target window.
563 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
564 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
565 windowInPrimary->assertNoEvents();
566 windowInSecondary->assertNoEvents();
567}
568
Michael Wrightd02c5b62014-02-10 15:10:22 -0800569} // namespace android