blob: c6eaf9f04809acbaed4b189ec8cc0ba696db5b1e [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
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800281class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800282public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800283 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
284 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800285 uint32_t consumeSeq;
286 InputEvent* event;
287 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
288 &consumeSeq, &event);
289
290 ASSERT_EQ(OK, status)
291 << mName.c_str() << ": consumer consume should return OK.";
292 ASSERT_TRUE(event != nullptr)
293 << mName.c_str() << ": consumer should have returned non-NULL event.";
294 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800295 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800296
297 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800298 << mName.c_str() << ": event displayId should be the same as expected.";
299
300 int32_t flags;
301 switch (expectedEventType) {
302 case AINPUT_EVENT_TYPE_KEY: {
303 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
304 flags = typedEvent->getFlags();
305 break;
306 }
307 case AINPUT_EVENT_TYPE_MOTION: {
308 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
309 flags = typedEvent->getFlags();
310 break;
311 }
312 default: {
313 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
314 }
315 }
316 ASSERT_EQ(expectedFlags, flags)
317 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800318
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800319 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800320 ASSERT_EQ(OK, status)
321 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
322 }
323
324 void assertNoEvents() {
325 uint32_t consumeSeq;
326 InputEvent* event;
327 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
328 &consumeSeq, &event);
329 ASSERT_NE(OK, status)
330 << mName.c_str()
331 << ": should not have received any events, so consume(..) should not return OK.";
332 }
333
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800334protected:
335 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
336 const std::string name, int32_t displayId) :
337 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
338 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
339 mConsumer = new InputConsumer(mClientChannel);
340 }
341
342 virtual ~FakeInputReceiver() {
343 }
344
345 // return true if the event has been handled.
346 virtual bool handled() {
347 return false;
348 }
349
Arthur Hungb92218b2018-08-14 12:00:21 +0800350 sp<InputDispatcher> mDispatcher;
351 sp<InputChannel> mServerChannel, mClientChannel;
352 InputConsumer *mConsumer;
353 PreallocatedInputEventFactory mEventFactory;
354
355 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800356 int32_t mDisplayId;
357};
358
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800359class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
360public:
361 static const int32_t WIDTH = 600;
362 static const int32_t HEIGHT = 800;
363
364 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
365 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
366 InputWindowHandle(inputApplicationHandle),
367 FakeInputReceiver(dispatcher, name, displayId),
368 mFocused(false) {
369 mDispatcher->registerInputChannel(mServerChannel, this, displayId);
370 }
371
372 virtual bool updateInfo() {
373 if (!mInfo) {
374 mInfo = new InputWindowInfo();
375 }
376 mInfo->inputChannel = mServerChannel;
377 mInfo->name = mName;
378 mInfo->layoutParamsFlags = 0;
379 mInfo->layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
380 mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
381 mInfo->frameLeft = 0;
382 mInfo->frameTop = 0;
383 mInfo->frameRight = WIDTH;
384 mInfo->frameBottom = HEIGHT;
385 mInfo->scaleFactor = 1.0;
386 mInfo->addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
387 mInfo->visible = true;
388 mInfo->canReceiveKeys = true;
389 mInfo->hasFocus = mFocused;
390 mInfo->hasWallpaper = false;
391 mInfo->paused = false;
392 mInfo->layer = 0;
393 mInfo->ownerPid = INJECTOR_PID;
394 mInfo->ownerUid = INJECTOR_UID;
395 mInfo->inputFeatures = 0;
396 mInfo->displayId = mDisplayId;
397
398 return true;
399 }
400
401 void setFocus() {
402 mFocused = true;
403 }
404
405 void assertNoEvents() {
406 uint32_t consumeSeq;
407 InputEvent* event;
408 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
409 &consumeSeq, &event);
410 ASSERT_NE(OK, status)
411 << mName.c_str()
412 << ": should not have received any events, so consume(..) should not return OK.";
413 }
414protected:
415 virtual bool handled() {
416 return true;
417 }
418
419 bool mFocused;
420};
421
Tiger Huang721e26f2018-07-24 22:26:19 +0800422static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
423 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800424 KeyEvent event;
425 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
426
427 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800428 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800429 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
430 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
431
432 // Inject event until dispatch out.
433 return dispatcher->injectInputEvent(
434 &event,
435 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
436 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
437}
438
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800439static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
440 int32_t displayId) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800441 MotionEvent event;
442 PointerProperties pointerProperties[1];
443 PointerCoords pointerCoords[1];
444
445 pointerProperties[0].clear();
446 pointerProperties[0].id = 0;
447 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
448
449 pointerCoords[0].clear();
450 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
451 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
452
453 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
454 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800455 event.initialize(DEVICE_ID, source, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800456 AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
457 AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
458 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
459 pointerCoords);
460
461 // Inject event until dispatch out.
462 return dispatcher->injectInputEvent(
463 &event,
464 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
465 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
466}
467
468TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
469 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800470 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
471 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800472
473 Vector<sp<InputWindowHandle>> inputWindowHandles;
474 inputWindowHandles.add(window);
475
476 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800477 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
478 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800479 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
480
481 // Window should receive motion event.
482 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
483}
484
485// The foreground window should receive the first touch down event.
486TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
487 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800488 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
489 ADISPLAY_ID_DEFAULT);
490 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
491 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800492
493 Vector<sp<InputWindowHandle>> inputWindowHandles;
494 inputWindowHandles.add(windowTop);
495 inputWindowHandles.add(windowSecond);
496
497 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800498 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
499 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800500 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
501
502 // Top window should receive the touch down event. Second window should not receive anything.
503 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
504 windowSecond->assertNoEvents();
505}
506
507TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
508 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800509 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
510 ADISPLAY_ID_DEFAULT);
511 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
512 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800513
514 // Set focus application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800515 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800516
517 // Expect one focus window exist in display.
518 windowSecond->setFocus();
519 Vector<sp<InputWindowHandle>> inputWindowHandles;
520 inputWindowHandles.add(windowTop);
521 inputWindowHandles.add(windowSecond);
522
523 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
524 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
525 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
526
527 // Focused window should receive event.
528 windowTop->assertNoEvents();
529 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
530}
531
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800532/* Test InputDispatcher for MultiDisplay */
533class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
534public:
535 static constexpr int32_t SECOND_DISPLAY_ID = 1;
536 virtual void SetUp() {
537 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800538
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800539 application1 = new FakeApplicationHandle();
540 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
541 ADISPLAY_ID_DEFAULT);
542 Vector<sp<InputWindowHandle>> inputWindowHandles;
543 inputWindowHandles.push(windowInPrimary);
544 // Set focus window for primary display, but focused display would be second one.
545 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
546 windowInPrimary->setFocus();
547 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800548
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800549 application2 = new FakeApplicationHandle();
550 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
551 SECOND_DISPLAY_ID);
552 // Set focus to second display window.
553 Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
554 inputWindowHandles_Second.push(windowInSecondary);
555 // Set focus display to second one.
556 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
557 // Set focus window for second display.
558 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
559 windowInSecondary->setFocus();
560 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
561 }
562
563 virtual void TearDown() {
564 InputDispatcherTest::TearDown();
565
566 application1.clear();
567 windowInPrimary.clear();
568 application2.clear();
569 windowInSecondary.clear();
570 }
571
572protected:
573 sp<FakeApplicationHandle> application1;
574 sp<FakeWindowHandle> windowInPrimary;
575 sp<FakeApplicationHandle> application2;
576 sp<FakeWindowHandle> windowInSecondary;
577};
578
579TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
580 // Test touch down on primary display.
581 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
582 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800583 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
584 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
585 windowInSecondary->assertNoEvents();
586
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800587 // Test touch down on second display.
588 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
589 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800590 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
591 windowInPrimary->assertNoEvents();
592 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
593}
594
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800595TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800596 // Test inject a key down with display id specified.
597 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
598 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
599 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
600 windowInSecondary->assertNoEvents();
601
602 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800603 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
604 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
605 windowInPrimary->assertNoEvents();
606 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
607
608 // Remove secondary display.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800609 Vector<sp<InputWindowHandle>> noWindows;
610 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800611
612 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800613 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
614 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800615
616 // Test inject a key down, should timeout because of no target window.
617 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
618 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
619 windowInPrimary->assertNoEvents();
620 windowInSecondary->assertNoEvents();
621}
622
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800623class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
624public:
625 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
626 int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
627 mDispatcher->registerInputChannel(mServerChannel, nullptr, displayId);
628 }
629};
630
631// Test per-display input monitors for motion event.
632TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
633 sp<FakeMonitorReceiver> monitorInPrimary =
634 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
635 sp<FakeMonitorReceiver> monitorInSecondary =
636 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
637
638 // Test touch down on primary display.
639 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
640 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
641 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
642 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
643 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
644 windowInSecondary->assertNoEvents();
645 monitorInSecondary->assertNoEvents();
646
647 // Test touch down on second display.
648 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
649 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
650 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
651 windowInPrimary->assertNoEvents();
652 monitorInPrimary->assertNoEvents();
653 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
654 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
655
656 // Test inject a non-pointer motion event.
657 // If specific a display, it will dispatch to the focused window of particular display,
658 // or it will dispatch to the focused window of focused display.
659 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
660 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
661 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
662 windowInPrimary->assertNoEvents();
663 monitorInPrimary->assertNoEvents();
664 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
665 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
666}
667
668// Test per-display input monitors for key event.
669TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
670 //Input monitor per display.
671 sp<FakeMonitorReceiver> monitorInPrimary =
672 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
673 sp<FakeMonitorReceiver> monitorInSecondary =
674 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
675
676 // Test inject a key down.
677 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
678 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
679 windowInPrimary->assertNoEvents();
680 monitorInPrimary->assertNoEvents();
681 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
682 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
683}
684
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685} // namespace android