blob: 066c143d51163923043e5fc317dd857eeb359a6e [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() {
Arthur Hung3b413f22018-10-26 18:05:34 +0800373 mInfo.inputChannel = mServerChannel;
374 mInfo.name = mName;
375 mInfo.layoutParamsFlags = 0;
376 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
377 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
378 mInfo.frameLeft = 0;
379 mInfo.frameTop = 0;
380 mInfo.frameRight = WIDTH;
381 mInfo.frameBottom = HEIGHT;
382 mInfo.scaleFactor = 1.0;
383 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
384 mInfo.visible = true;
385 mInfo.canReceiveKeys = true;
386 mInfo.hasFocus = mFocused;
387 mInfo.hasWallpaper = false;
388 mInfo.paused = false;
389 mInfo.layer = 0;
390 mInfo.ownerPid = INJECTOR_PID;
391 mInfo.ownerUid = INJECTOR_UID;
392 mInfo.inputFeatures = 0;
393 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800394
395 return true;
396 }
397
398 void setFocus() {
399 mFocused = true;
400 }
401
402 void assertNoEvents() {
403 uint32_t consumeSeq;
404 InputEvent* event;
405 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
406 &consumeSeq, &event);
407 ASSERT_NE(OK, status)
408 << mName.c_str()
409 << ": should not have received any events, so consume(..) should not return OK.";
410 }
411protected:
412 virtual bool handled() {
413 return true;
414 }
415
416 bool mFocused;
417};
418
Tiger Huang721e26f2018-07-24 22:26:19 +0800419static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
420 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800421 KeyEvent event;
422 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
423
424 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800425 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800426 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
427 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
428
429 // Inject event until dispatch out.
430 return dispatcher->injectInputEvent(
431 &event,
432 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
433 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
434}
435
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800436static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
437 int32_t displayId) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800438 MotionEvent event;
439 PointerProperties pointerProperties[1];
440 PointerCoords pointerCoords[1];
441
442 pointerProperties[0].clear();
443 pointerProperties[0].id = 0;
444 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
445
446 pointerCoords[0].clear();
447 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
448 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
449
450 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
451 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800452 event.initialize(DEVICE_ID, source, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800453 AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
454 AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
455 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
456 pointerCoords);
457
458 // Inject event until dispatch out.
459 return dispatcher->injectInputEvent(
460 &event,
461 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
462 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
463}
464
465TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
466 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800467 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
468 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800469
470 Vector<sp<InputWindowHandle>> inputWindowHandles;
471 inputWindowHandles.add(window);
472
473 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800474 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
475 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800476 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
477
478 // Window should receive motion event.
479 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
480}
481
482// The foreground window should receive the first touch down event.
483TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
484 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800485 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
486 ADISPLAY_ID_DEFAULT);
487 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
488 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800489
490 Vector<sp<InputWindowHandle>> inputWindowHandles;
491 inputWindowHandles.add(windowTop);
492 inputWindowHandles.add(windowSecond);
493
494 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800495 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
496 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800497 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
498
499 // Top window should receive the touch down event. Second window should not receive anything.
500 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
501 windowSecond->assertNoEvents();
502}
503
504TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
505 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800506 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
507 ADISPLAY_ID_DEFAULT);
508 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
509 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800510
511 // Set focus application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800512 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800513
514 // Expect one focus window exist in display.
515 windowSecond->setFocus();
516 Vector<sp<InputWindowHandle>> inputWindowHandles;
517 inputWindowHandles.add(windowTop);
518 inputWindowHandles.add(windowSecond);
519
520 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
521 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
522 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
523
524 // Focused window should receive event.
525 windowTop->assertNoEvents();
526 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
527}
528
Arthur Hung3b413f22018-10-26 18:05:34 +0800529TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
530 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
531
532 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
533 ADISPLAY_ID_DEFAULT);
534 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
535 ADISPLAY_ID_DEFAULT);
536
537 windowTop->setFocus();
538
539 Vector<sp<InputWindowHandle>> inputWindowHandles;
540 inputWindowHandles.add(windowTop);
541 inputWindowHandles.add(windowSecond);
542
543 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
544
545 // Release channel for window is no longer valid.
546 windowTop->releaseChannel();
547
548 // Test inject a motion down, should timeout because of no target channel.
549 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
550 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
551
552 // Top window is invalid, so it should not receive any input event.
553 windowTop->assertNoEvents();
554 windowSecond->assertNoEvents();
555}
556
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800557/* Test InputDispatcher for MultiDisplay */
558class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
559public:
560 static constexpr int32_t SECOND_DISPLAY_ID = 1;
561 virtual void SetUp() {
562 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800563
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800564 application1 = new FakeApplicationHandle();
565 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
566 ADISPLAY_ID_DEFAULT);
567 Vector<sp<InputWindowHandle>> inputWindowHandles;
568 inputWindowHandles.push(windowInPrimary);
569 // Set focus window for primary display, but focused display would be second one.
570 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
571 windowInPrimary->setFocus();
572 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800573
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800574 application2 = new FakeApplicationHandle();
575 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
576 SECOND_DISPLAY_ID);
577 // Set focus to second display window.
578 Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
579 inputWindowHandles_Second.push(windowInSecondary);
580 // Set focus display to second one.
581 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
582 // Set focus window for second display.
583 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
584 windowInSecondary->setFocus();
585 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
586 }
587
588 virtual void TearDown() {
589 InputDispatcherTest::TearDown();
590
591 application1.clear();
592 windowInPrimary.clear();
593 application2.clear();
594 windowInSecondary.clear();
595 }
596
597protected:
598 sp<FakeApplicationHandle> application1;
599 sp<FakeWindowHandle> windowInPrimary;
600 sp<FakeApplicationHandle> application2;
601 sp<FakeWindowHandle> windowInSecondary;
602};
603
604TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
605 // Test touch down on primary display.
606 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
607 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800608 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
609 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
610 windowInSecondary->assertNoEvents();
611
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800612 // Test touch down on second display.
613 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
614 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800615 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
616 windowInPrimary->assertNoEvents();
617 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
618}
619
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800620TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800621 // Test inject a key down with display id specified.
622 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
623 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
624 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
625 windowInSecondary->assertNoEvents();
626
627 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800628 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
629 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
630 windowInPrimary->assertNoEvents();
631 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
632
633 // Remove secondary display.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800634 Vector<sp<InputWindowHandle>> noWindows;
635 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800636
637 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800638 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
639 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800640
641 // Test inject a key down, should timeout because of no target window.
642 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
643 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
644 windowInPrimary->assertNoEvents();
645 windowInSecondary->assertNoEvents();
646}
647
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800648class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
649public:
650 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
651 int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
652 mDispatcher->registerInputChannel(mServerChannel, nullptr, displayId);
653 }
654};
655
656// Test per-display input monitors for motion event.
657TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
658 sp<FakeMonitorReceiver> monitorInPrimary =
659 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
660 sp<FakeMonitorReceiver> monitorInSecondary =
661 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
662
663 // Test touch down on primary display.
664 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
665 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
666 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
667 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
668 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
669 windowInSecondary->assertNoEvents();
670 monitorInSecondary->assertNoEvents();
671
672 // Test touch down on second display.
673 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
674 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
675 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
676 windowInPrimary->assertNoEvents();
677 monitorInPrimary->assertNoEvents();
678 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
679 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
680
681 // Test inject a non-pointer motion event.
682 // If specific a display, it will dispatch to the focused window of particular display,
683 // or it will dispatch to the focused window of focused display.
684 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
685 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
686 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
687 windowInPrimary->assertNoEvents();
688 monitorInPrimary->assertNoEvents();
689 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
690 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
691}
692
693// Test per-display input monitors for key event.
694TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
695 //Input monitor per display.
696 sp<FakeMonitorReceiver> monitorInPrimary =
697 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
698 sp<FakeMonitorReceiver> monitorInSecondary =
699 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
700
701 // Test inject a key down.
702 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
703 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
704 windowInPrimary->assertNoEvents();
705 monitorInPrimary->assertNoEvents();
706 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
707 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
708}
709
Michael Wrightd02c5b62014-02-10 15:10:22 -0800710} // namespace android