blob: 26adcdd8a991bdca2ee31e020bce4d7e65875da8 [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
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
20
Michael Wrightd02c5b62014-02-10 15:10:22 -080021#include <gtest/gtest.h>
22#include <linux/input.h>
23
24namespace android {
25
26// An arbitrary time value.
27static const nsecs_t ARBITRARY_TIME = 1234;
28
29// An arbitrary device id.
30static const int32_t DEVICE_ID = 1;
31
Jeff Brownf086ddb2014-02-11 14:28:48 -080032// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080033static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080034
Michael Wrightd02c5b62014-02-10 15:10:22 -080035// An arbitrary injector pid / uid pair that has permission to inject events.
36static const int32_t INJECTOR_PID = 999;
37static const int32_t INJECTOR_UID = 1001;
38
39
40// --- FakeInputDispatcherPolicy ---
41
42class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
43 InputDispatcherConfiguration mConfig;
44
45protected:
46 virtual ~FakeInputDispatcherPolicy() {
47 }
48
49public:
50 FakeInputDispatcherPolicy() {
51 }
52
53private:
Narayan Kamath39efe3e2014-10-17 10:37:08 +010054 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080055 }
56
Narayan Kamath39efe3e2014-10-17 10:37:08 +010057 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -070058 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080059 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080060 return 0;
61 }
62
Robert Carr803535b2018-08-02 16:38:15 -070063 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080064 }
65
66 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
67 *outConfig = mConfig;
68 }
69
Narayan Kamath39efe3e2014-10-17 10:37:08 +010070 virtual bool filterInputEvent(const InputEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080071 return true;
72 }
73
Narayan Kamath39efe3e2014-10-17 10:37:08 +010074 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080075 }
76
Narayan Kamath39efe3e2014-10-17 10:37:08 +010077 virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080078 }
79
Robert Carr803535b2018-08-02 16:38:15 -070080 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +010081 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080082 return 0;
83 }
84
Robert Carr803535b2018-08-02 16:38:15 -070085 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +010086 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080087 return false;
88 }
89
Narayan Kamath39efe3e2014-10-17 10:37:08 +010090 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080091 }
92
Narayan Kamath39efe3e2014-10-17 10:37:08 +010093 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080094 }
95
Narayan Kamath39efe3e2014-10-17 10:37:08 +010096 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080097 return false;
98 }
99};
100
101
102// --- InputDispatcherTest ---
103
104class InputDispatcherTest : public testing::Test {
105protected:
106 sp<FakeInputDispatcherPolicy> mFakePolicy;
107 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800108 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800109
110 virtual void SetUp() {
111 mFakePolicy = new FakeInputDispatcherPolicy();
112 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800113 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
114 //Start InputDispatcher thread
115 mDispatcherThread = new InputDispatcherThread(mDispatcher);
116 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800117 }
118
119 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800120 mDispatcherThread->requestExit();
121 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800122 mFakePolicy.clear();
123 mDispatcher.clear();
124 }
125};
126
127
128TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
129 KeyEvent event;
130
131 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100132 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800133 /*action*/ -1, 0,
134 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800135 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800136 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800137 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
138 << "Should reject key events with undefined action.";
139
140 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100141 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800142 AKEY_EVENT_ACTION_MULTIPLE, 0,
143 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800144 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800145 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800146 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
147 << "Should reject key events with ACTION_MULTIPLE.";
148}
149
150TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
151 MotionEvent event;
152 PointerProperties pointerProperties[MAX_POINTERS + 1];
153 PointerCoords pointerCoords[MAX_POINTERS + 1];
154 for (int i = 0; i <= MAX_POINTERS; i++) {
155 pointerProperties[i].clear();
156 pointerProperties[i].id = i;
157 pointerCoords[i].clear();
158 }
159
160 // Rejects undefined motion actions.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800161 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100162 /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800163 ARBITRARY_TIME, ARBITRARY_TIME,
164 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800165 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800166 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800167 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
168 << "Should reject motion events with undefined action.";
169
170 // Rejects pointer down with invalid index.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800171 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100173 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800174 ARBITRARY_TIME, ARBITRARY_TIME,
175 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800176 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800177 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800178 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
179 << "Should reject motion events with pointer down index too large.";
180
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800181 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800182 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100183 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800184 ARBITRARY_TIME, ARBITRARY_TIME,
185 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800186 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800187 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
189 << "Should reject motion events with pointer down index too small.";
190
191 // Rejects pointer up with invalid index.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800192 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100194 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195 ARBITRARY_TIME, ARBITRARY_TIME,
196 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800197 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800198 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800199 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
200 << "Should reject motion events with pointer up index too large.";
201
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800202 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800203 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Michael Wright7b159c92015-05-14 14:48:03 +0100204 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800205 ARBITRARY_TIME, ARBITRARY_TIME,
206 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800207 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800208 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
210 << "Should reject motion events with pointer up index too small.";
211
212 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800213 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100214 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800215 ARBITRARY_TIME, ARBITRARY_TIME,
216 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800217 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800218 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800219 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
220 << "Should reject motion events with 0 pointers.";
221
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800222 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100223 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800224 ARBITRARY_TIME, ARBITRARY_TIME,
225 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800226 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800227 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800228 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
229 << "Should reject motion events with more than MAX_POINTERS pointers.";
230
231 // Rejects motion events with invalid pointer ids.
232 pointerProperties[0].id = -1;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800233 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100234 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800235 ARBITRARY_TIME, ARBITRARY_TIME,
236 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800237 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800238 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800239 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
240 << "Should reject motion events with pointer ids less than 0.";
241
242 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800243 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100244 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800245 ARBITRARY_TIME, ARBITRARY_TIME,
246 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800247 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800248 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
250 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
251
252 // Rejects motion events with duplicate pointer ids.
253 pointerProperties[0].id = 1;
254 pointerProperties[1].id = 1;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800255 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
Michael Wright7b159c92015-05-14 14:48:03 +0100256 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257 ARBITRARY_TIME, ARBITRARY_TIME,
258 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800259 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800260 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800261 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
262 << "Should reject motion events with duplicate pointer ids.";
263}
264
Arthur Hungb92218b2018-08-14 12:00:21 +0800265// --- InputDispatcherTest SetInputWindowTest ---
266static const int32_t INJECT_EVENT_TIMEOUT = 500;
267static const int32_t DISPATCHING_TIMEOUT = 100;
268
269class FakeApplicationHandle : public InputApplicationHandle {
270public:
271 FakeApplicationHandle() {}
272 virtual ~FakeApplicationHandle() {}
273
274 virtual bool updateInfo() {
275 if (!mInfo) {
276 mInfo = new InputApplicationInfo();
277 }
278 mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
279 return true;
280 }
281};
282
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800283class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800284public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800285 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
286 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800287 uint32_t consumeSeq;
288 InputEvent* event;
289 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
290 &consumeSeq, &event);
291
292 ASSERT_EQ(OK, status)
293 << mName.c_str() << ": consumer consume should return OK.";
294 ASSERT_TRUE(event != nullptr)
295 << mName.c_str() << ": consumer should have returned non-NULL event.";
296 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800297 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800298
299 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800300 << mName.c_str() << ": event displayId should be the same as expected.";
301
302 int32_t flags;
303 switch (expectedEventType) {
304 case AINPUT_EVENT_TYPE_KEY: {
305 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
306 flags = typedEvent->getFlags();
307 break;
308 }
309 case AINPUT_EVENT_TYPE_MOTION: {
310 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
311 flags = typedEvent->getFlags();
312 break;
313 }
314 default: {
315 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
316 }
317 }
318 ASSERT_EQ(expectedFlags, flags)
319 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800320
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800321 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800322 ASSERT_EQ(OK, status)
323 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
324 }
325
326 void assertNoEvents() {
327 uint32_t consumeSeq;
328 InputEvent* event;
329 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
330 &consumeSeq, &event);
331 ASSERT_NE(OK, status)
332 << mName.c_str()
333 << ": should not have received any events, so consume(..) should not return OK.";
334 }
335
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800336protected:
337 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
338 const std::string name, int32_t displayId) :
339 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
340 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
341 mConsumer = new InputConsumer(mClientChannel);
342 }
343
344 virtual ~FakeInputReceiver() {
345 }
346
347 // return true if the event has been handled.
348 virtual bool handled() {
349 return false;
350 }
351
Arthur Hungb92218b2018-08-14 12:00:21 +0800352 sp<InputDispatcher> mDispatcher;
353 sp<InputChannel> mServerChannel, mClientChannel;
Robert Carr5c8a0262018-10-03 16:30:44 -0700354 sp<IBinder> mToken;
Arthur Hungb92218b2018-08-14 12:00:21 +0800355 InputConsumer *mConsumer;
356 PreallocatedInputEventFactory mEventFactory;
357
358 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800359 int32_t mDisplayId;
360};
361
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800362class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
363public:
364 static const int32_t WIDTH = 600;
365 static const int32_t HEIGHT = 800;
366
367 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
368 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
369 InputWindowHandle(inputApplicationHandle),
370 FakeInputReceiver(dispatcher, name, displayId),
371 mFocused(false) {
Robert Carr4e670e52018-08-15 13:26:12 -0700372 mServerChannel->setToken(new BBinder());
Robert Carr803535b2018-08-02 16:38:15 -0700373 mDispatcher->registerInputChannel(mServerChannel, displayId);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800374 }
375
376 virtual bool updateInfo() {
Robert Carr5c8a0262018-10-03 16:30:44 -0700377 mInfo.token = mServerChannel->getToken();
Arthur Hung3b413f22018-10-26 18:05:34 +0800378 mInfo.name = mName;
379 mInfo.layoutParamsFlags = 0;
380 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
381 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
382 mInfo.frameLeft = 0;
383 mInfo.frameTop = 0;
384 mInfo.frameRight = WIDTH;
385 mInfo.frameBottom = HEIGHT;
386 mInfo.scaleFactor = 1.0;
387 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
388 mInfo.visible = true;
389 mInfo.canReceiveKeys = true;
390 mInfo.hasFocus = mFocused;
391 mInfo.hasWallpaper = false;
392 mInfo.paused = false;
393 mInfo.layer = 0;
394 mInfo.ownerPid = INJECTOR_PID;
395 mInfo.ownerUid = INJECTOR_UID;
396 mInfo.inputFeatures = 0;
397 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800398
399 return true;
400 }
401
402 void setFocus() {
403 mFocused = true;
404 }
405
406 void assertNoEvents() {
407 uint32_t consumeSeq;
408 InputEvent* event;
409 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
410 &consumeSeq, &event);
411 ASSERT_NE(OK, status)
412 << mName.c_str()
413 << ": should not have received any events, so consume(..) should not return OK.";
414 }
415protected:
416 virtual bool handled() {
417 return true;
418 }
419
420 bool mFocused;
421};
422
Tiger Huang721e26f2018-07-24 22:26:19 +0800423static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
424 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800425 KeyEvent event;
426 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
427
428 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800429 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800430 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
431 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
432
433 // Inject event until dispatch out.
434 return dispatcher->injectInputEvent(
435 &event,
436 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
437 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
438}
439
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800440static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
441 int32_t displayId) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800442 MotionEvent event;
443 PointerProperties pointerProperties[1];
444 PointerCoords pointerCoords[1];
445
446 pointerProperties[0].clear();
447 pointerProperties[0].id = 0;
448 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
449
450 pointerCoords[0].clear();
451 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
452 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
453
454 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
455 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800456 event.initialize(DEVICE_ID, source, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800457 AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
458 AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
459 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
460 pointerCoords);
461
462 // Inject event until dispatch out.
463 return dispatcher->injectInputEvent(
464 &event,
465 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
466 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
467}
468
469TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
470 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800471 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
472 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800473
474 Vector<sp<InputWindowHandle>> inputWindowHandles;
475 inputWindowHandles.add(window);
476
477 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800478 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
479 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800480 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
481
482 // Window should receive motion event.
483 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
484}
485
486// The foreground window should receive the first touch down event.
487TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
488 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800489 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
490 ADISPLAY_ID_DEFAULT);
491 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
492 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800493
494 Vector<sp<InputWindowHandle>> inputWindowHandles;
495 inputWindowHandles.add(windowTop);
496 inputWindowHandles.add(windowSecond);
497
498 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800499 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
500 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800501 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
502
503 // Top window should receive the touch down event. Second window should not receive anything.
504 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
505 windowSecond->assertNoEvents();
506}
507
508TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
509 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800510 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
511 ADISPLAY_ID_DEFAULT);
512 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
513 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800514
515 // Set focus application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800516 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800517
518 // Expect one focus window exist in display.
519 windowSecond->setFocus();
520 Vector<sp<InputWindowHandle>> inputWindowHandles;
521 inputWindowHandles.add(windowTop);
522 inputWindowHandles.add(windowSecond);
523
524 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
525 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
526 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
527
528 // Focused window should receive event.
529 windowTop->assertNoEvents();
530 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
531}
532
Arthur Hung3b413f22018-10-26 18:05:34 +0800533TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
534 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
535
536 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
537 ADISPLAY_ID_DEFAULT);
538 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
539 ADISPLAY_ID_DEFAULT);
540
541 windowTop->setFocus();
542
543 Vector<sp<InputWindowHandle>> inputWindowHandles;
544 inputWindowHandles.add(windowTop);
545 inputWindowHandles.add(windowSecond);
546
547 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
548
549 // Release channel for window is no longer valid.
550 windowTop->releaseChannel();
551
552 // Test inject a motion down, should timeout because of no target channel.
553 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
554 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
555
556 // Top window is invalid, so it should not receive any input event.
557 windowTop->assertNoEvents();
558 windowSecond->assertNoEvents();
559}
560
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800561/* Test InputDispatcher for MultiDisplay */
562class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
563public:
564 static constexpr int32_t SECOND_DISPLAY_ID = 1;
565 virtual void SetUp() {
566 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800567
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800568 application1 = new FakeApplicationHandle();
569 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
570 ADISPLAY_ID_DEFAULT);
571 Vector<sp<InputWindowHandle>> inputWindowHandles;
572 inputWindowHandles.push(windowInPrimary);
573 // Set focus window for primary display, but focused display would be second one.
574 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
575 windowInPrimary->setFocus();
576 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800577
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800578 application2 = new FakeApplicationHandle();
579 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
580 SECOND_DISPLAY_ID);
581 // Set focus to second display window.
582 Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
583 inputWindowHandles_Second.push(windowInSecondary);
584 // Set focus display to second one.
585 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
586 // Set focus window for second display.
587 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
588 windowInSecondary->setFocus();
589 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
590 }
591
592 virtual void TearDown() {
593 InputDispatcherTest::TearDown();
594
595 application1.clear();
596 windowInPrimary.clear();
597 application2.clear();
598 windowInSecondary.clear();
599 }
600
601protected:
602 sp<FakeApplicationHandle> application1;
603 sp<FakeWindowHandle> windowInPrimary;
604 sp<FakeApplicationHandle> application2;
605 sp<FakeWindowHandle> windowInSecondary;
606};
607
608TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
609 // Test touch down on primary display.
610 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
611 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800612 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
613 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
614 windowInSecondary->assertNoEvents();
615
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800616 // Test touch down on second display.
617 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
618 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800619 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
620 windowInPrimary->assertNoEvents();
621 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
622}
623
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800624TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800625 // Test inject a key down with display id specified.
626 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
627 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
628 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
629 windowInSecondary->assertNoEvents();
630
631 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800632 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
633 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
634 windowInPrimary->assertNoEvents();
635 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
636
637 // Remove secondary display.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800638 Vector<sp<InputWindowHandle>> noWindows;
639 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800640
641 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800642 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
643 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800644
645 // Test inject a key down, should timeout because of no target window.
646 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
647 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
648 windowInPrimary->assertNoEvents();
649 windowInSecondary->assertNoEvents();
650}
651
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800652class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
653public:
654 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
655 int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
Robert Carr803535b2018-08-02 16:38:15 -0700656 mDispatcher->registerInputChannel(mServerChannel, displayId);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800657 }
658};
659
660// Test per-display input monitors for motion event.
661TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
662 sp<FakeMonitorReceiver> monitorInPrimary =
663 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
664 sp<FakeMonitorReceiver> monitorInSecondary =
665 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
666
667 // Test touch down on primary display.
668 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
669 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
670 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
671 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
672 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
673 windowInSecondary->assertNoEvents();
674 monitorInSecondary->assertNoEvents();
675
676 // Test touch down on second display.
677 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
678 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
679 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
680 windowInPrimary->assertNoEvents();
681 monitorInPrimary->assertNoEvents();
682 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
683 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
684
685 // Test inject a non-pointer motion event.
686 // If specific a display, it will dispatch to the focused window of particular display,
687 // or it will dispatch to the focused window of focused display.
688 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
689 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
690 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
691 windowInPrimary->assertNoEvents();
692 monitorInPrimary->assertNoEvents();
693 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
694 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
695}
696
697// Test per-display input monitors for key event.
698TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
699 //Input monitor per display.
700 sp<FakeMonitorReceiver> monitorInPrimary =
701 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
702 sp<FakeMonitorReceiver> monitorInSecondary =
703 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
704
705 // Test inject a key down.
706 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
707 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
708 windowInPrimary->assertNoEvents();
709 monitorInPrimary->assertNoEvents();
710 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
711 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
712}
713
Michael Wrightd02c5b62014-02-10 15:10:22 -0800714} // namespace android