blob: 7d69854868a2184e025f5bf9477bd3496ea84025 [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
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tane84e6f92019-08-29 17:28:41 -070019#include <InputDispatcherThread.h>
20
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
22
Michael Wrightd02c5b62014-02-10 15:10:22 -080023#include <gtest/gtest.h>
24#include <linux/input.h>
25
Garfield Tane84e6f92019-08-29 17:28:41 -070026namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080027
28// An arbitrary time value.
29static const nsecs_t ARBITRARY_TIME = 1234;
30
31// An arbitrary device id.
32static const int32_t DEVICE_ID = 1;
33
Jeff Brownf086ddb2014-02-11 14:28:48 -080034// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080035static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080036
Michael Wrightd02c5b62014-02-10 15:10:22 -080037// An arbitrary injector pid / uid pair that has permission to inject events.
38static const int32_t INJECTOR_PID = 999;
39static const int32_t INJECTOR_UID = 1001;
40
41
42// --- FakeInputDispatcherPolicy ---
43
44class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
45 InputDispatcherConfiguration mConfig;
46
47protected:
48 virtual ~FakeInputDispatcherPolicy() {
49 }
50
51public:
52 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080053 mInputEventFiltered = false;
54 mTime = -1;
55 mAction = -1;
56 mDisplayId = -1;
chaviwfd6d3512019-03-25 13:23:49 -070057 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +080058 }
59
60 void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyMotionArgs* args) {
61 ASSERT_TRUE(mInputEventFiltered)
62 << "Expected filterInputEvent() to have been called.";
63
64 ASSERT_EQ(mTime, args->eventTime)
65 << "Expected time of filtered event was not matched";
66 ASSERT_EQ(mAction, args->action)
67 << "Expected action of filtered event was not matched";
68 ASSERT_EQ(mDisplayId, args->displayId)
69 << "Expected displayId of filtered event was not matched";
70
71 reset();
72 }
73
74 void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyKeyArgs* args) {
75 ASSERT_TRUE(mInputEventFiltered)
76 << "Expected filterInputEvent() to have been called.";
77
78 ASSERT_EQ(mTime, args->eventTime)
79 << "Expected time of filtered event was not matched";
80 ASSERT_EQ(mAction, args->action)
81 << "Expected action of filtered event was not matched";
82 ASSERT_EQ(mDisplayId, args->displayId)
83 << "Expected displayId of filtered event was not matched";
84
85 reset();
86 }
87
88 void assertFilterInputEventWasNotCalled() {
89 ASSERT_FALSE(mInputEventFiltered)
90 << "Expected filterInputEvent() to not have been called.";
Michael Wrightd02c5b62014-02-10 15:10:22 -080091 }
92
chaviwfd6d3512019-03-25 13:23:49 -070093 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
94 ASSERT_EQ(mOnPointerDownToken, touchedToken)
95 << "Expected token from onPointerDownOutsideFocus was not matched";
96 reset();
97 }
98
Michael Wrightd02c5b62014-02-10 15:10:22 -080099private:
Jackal Guof9696682018-10-05 12:23:23 +0800100 bool mInputEventFiltered;
101 nsecs_t mTime;
102 int32_t mAction;
103 int32_t mDisplayId;
chaviwfd6d3512019-03-25 13:23:49 -0700104 sp<IBinder> mOnPointerDownToken;
Jackal Guof9696682018-10-05 12:23:23 +0800105
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100106 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800107 }
108
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100109 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700110 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800111 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800112 return 0;
113 }
114
Robert Carr803535b2018-08-02 16:38:15 -0700115 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800116 }
117
chaviw0c06c6e2019-01-09 13:27:07 -0800118 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700119 }
120
Michael Wrightd02c5b62014-02-10 15:10:22 -0800121 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
122 *outConfig = mConfig;
123 }
124
Jackal Guof9696682018-10-05 12:23:23 +0800125 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
126 switch (inputEvent->getType()) {
127 case AINPUT_EVENT_TYPE_KEY: {
128 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
129 mTime = keyEvent->getEventTime();
130 mAction = keyEvent->getAction();
131 mDisplayId = keyEvent->getDisplayId();
132 break;
133 }
134
135 case AINPUT_EVENT_TYPE_MOTION: {
136 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
137 mTime = motionEvent->getEventTime();
138 mAction = motionEvent->getAction();
139 mDisplayId = motionEvent->getDisplayId();
140 break;
141 }
142 }
143
144 mInputEventFiltered = true;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800145 return true;
146 }
147
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100148 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149 }
150
Charles Chen3611f1f2019-01-29 17:26:18 +0800151 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152 }
153
Robert Carr803535b2018-08-02 16:38:15 -0700154 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100155 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800156 return 0;
157 }
158
Robert Carr803535b2018-08-02 16:38:15 -0700159 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100160 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161 return false;
162 }
163
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100164 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800165 }
166
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100167 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800168 }
169
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100170 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800171 return false;
172 }
Jackal Guof9696682018-10-05 12:23:23 +0800173
chaviwfd6d3512019-03-25 13:23:49 -0700174 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
175 mOnPointerDownToken = newToken;
176 }
177
Jackal Guof9696682018-10-05 12:23:23 +0800178 void reset() {
179 mInputEventFiltered = false;
180 mTime = -1;
181 mAction = -1;
182 mDisplayId = -1;
chaviwfd6d3512019-03-25 13:23:49 -0700183 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +0800184 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185};
186
187
188// --- InputDispatcherTest ---
189
190class InputDispatcherTest : public testing::Test {
191protected:
192 sp<FakeInputDispatcherPolicy> mFakePolicy;
193 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800194 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195
196 virtual void SetUp() {
197 mFakePolicy = new FakeInputDispatcherPolicy();
198 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800199 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
200 //Start InputDispatcher thread
201 mDispatcherThread = new InputDispatcherThread(mDispatcher);
202 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800203 }
204
205 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800206 mDispatcherThread->requestExit();
207 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208 mFakePolicy.clear();
209 mDispatcher.clear();
210 }
211};
212
213
214TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
215 KeyEvent event;
216
217 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100218 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800219 /*action*/ -1, 0,
220 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800221 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800222 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800223 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
224 << "Should reject key events with undefined action.";
225
226 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100227 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800228 AKEY_EVENT_ACTION_MULTIPLE, 0,
229 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800230 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800231 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800232 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
233 << "Should reject key events with ACTION_MULTIPLE.";
234}
235
236TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
237 MotionEvent event;
238 PointerProperties pointerProperties[MAX_POINTERS + 1];
239 PointerCoords pointerCoords[MAX_POINTERS + 1];
240 for (int i = 0; i <= MAX_POINTERS; i++) {
241 pointerProperties[i].clear();
242 pointerProperties[i].id = i;
243 pointerCoords[i].clear();
244 }
245
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800246 // Some constants commonly used below
247 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
248 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
249 constexpr int32_t metaState = AMETA_NONE;
250 constexpr MotionClassification classification = MotionClassification::NONE;
251
Michael Wrightd02c5b62014-02-10 15:10:22 -0800252 // Rejects undefined motion actions.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800253 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700254 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
255 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
256 ARBITRARY_TIME, ARBITRARY_TIME,
257 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800258 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800259 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
261 << "Should reject motion events with undefined action.";
262
263 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800264 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700265 AMOTION_EVENT_ACTION_POINTER_DOWN |
266 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
267 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
268 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
269 ARBITRARY_TIME, ARBITRARY_TIME,
270 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800271 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800272 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800273 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
274 << "Should reject motion events with pointer down index too large.";
275
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800276 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700277 AMOTION_EVENT_ACTION_POINTER_DOWN |
278 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
279 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
280 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
281 ARBITRARY_TIME, ARBITRARY_TIME,
282 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800283 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800284 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
286 << "Should reject motion events with pointer down index too small.";
287
288 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800289 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700290 AMOTION_EVENT_ACTION_POINTER_UP |
291 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
292 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
293 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
294 ARBITRARY_TIME, ARBITRARY_TIME,
295 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800296 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800297 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800298 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
299 << "Should reject motion events with pointer up index too large.";
300
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800301 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700302 AMOTION_EVENT_ACTION_POINTER_UP |
303 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
304 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
305 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
306 ARBITRARY_TIME, ARBITRARY_TIME,
307 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800308 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800309 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800310 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
311 << "Should reject motion events with pointer up index too small.";
312
313 // Rejects motion events with invalid number of pointers.
Garfield Tan00f511d2019-06-12 16:55:40 -0700314 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
315 metaState, 0, classification, 0, 0, 0, 0,
316 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
317 ARBITRARY_TIME, ARBITRARY_TIME,
318 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800319 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800320 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800321 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
322 << "Should reject motion events with 0 pointers.";
323
Garfield Tan00f511d2019-06-12 16:55:40 -0700324 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
325 metaState, 0, classification, 0, 0, 0, 0,
326 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
327 ARBITRARY_TIME, ARBITRARY_TIME,
328 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800329 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800330 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800331 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
332 << "Should reject motion events with more than MAX_POINTERS pointers.";
333
334 // Rejects motion events with invalid pointer ids.
335 pointerProperties[0].id = -1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700336 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
337 metaState, 0, classification, 0, 0, 0, 0,
338 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
339 ARBITRARY_TIME, ARBITRARY_TIME,
340 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800341 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800342 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800343 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
344 << "Should reject motion events with pointer ids less than 0.";
345
346 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700347 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
348 metaState, 0, classification, 0, 0, 0, 0,
349 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
350 ARBITRARY_TIME, ARBITRARY_TIME,
351 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800352 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800353 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800354 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
355 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
356
357 // Rejects motion events with duplicate pointer ids.
358 pointerProperties[0].id = 1;
359 pointerProperties[1].id = 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700360 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
361 metaState, 0, classification, 0, 0, 0, 0,
362 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
363 ARBITRARY_TIME, ARBITRARY_TIME,
364 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800365 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800366 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800367 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
368 << "Should reject motion events with duplicate pointer ids.";
369}
370
Arthur Hungb92218b2018-08-14 12:00:21 +0800371// --- InputDispatcherTest SetInputWindowTest ---
372static const int32_t INJECT_EVENT_TIMEOUT = 500;
373static const int32_t DISPATCHING_TIMEOUT = 100;
374
375class FakeApplicationHandle : public InputApplicationHandle {
376public:
377 FakeApplicationHandle() {}
378 virtual ~FakeApplicationHandle() {}
379
380 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800381 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800382 return true;
383 }
384};
385
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800386class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800387public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800388 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
389 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800390 uint32_t consumeSeq;
391 InputEvent* event;
392 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
393 &consumeSeq, &event);
394
395 ASSERT_EQ(OK, status)
396 << mName.c_str() << ": consumer consume should return OK.";
397 ASSERT_TRUE(event != nullptr)
398 << mName.c_str() << ": consumer should have returned non-NULL event.";
399 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800400 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800401
402 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800403 << mName.c_str() << ": event displayId should be the same as expected.";
404
405 int32_t flags;
406 switch (expectedEventType) {
407 case AINPUT_EVENT_TYPE_KEY: {
408 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
409 flags = typedEvent->getFlags();
410 break;
411 }
412 case AINPUT_EVENT_TYPE_MOTION: {
413 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
414 flags = typedEvent->getFlags();
415 break;
416 }
417 default: {
418 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
419 }
420 }
421 ASSERT_EQ(expectedFlags, flags)
422 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800423
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800424 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800425 ASSERT_EQ(OK, status)
426 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
427 }
428
429 void assertNoEvents() {
430 uint32_t consumeSeq;
431 InputEvent* event;
432 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
433 &consumeSeq, &event);
434 ASSERT_NE(OK, status)
435 << mName.c_str()
436 << ": should not have received any events, so consume(..) should not return OK.";
437 }
438
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800439protected:
440 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
441 const std::string name, int32_t displayId) :
442 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
443 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
444 mConsumer = new InputConsumer(mClientChannel);
445 }
446
447 virtual ~FakeInputReceiver() {
448 }
449
450 // return true if the event has been handled.
451 virtual bool handled() {
452 return false;
453 }
454
Arthur Hungb92218b2018-08-14 12:00:21 +0800455 sp<InputDispatcher> mDispatcher;
456 sp<InputChannel> mServerChannel, mClientChannel;
457 InputConsumer *mConsumer;
458 PreallocatedInputEventFactory mEventFactory;
459
460 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800461 int32_t mDisplayId;
462};
463
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800464class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
465public:
466 static const int32_t WIDTH = 600;
467 static const int32_t HEIGHT = 800;
468
469 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
470 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800471 FakeInputReceiver(dispatcher, name, displayId),
chaviwfd6d3512019-03-25 13:23:49 -0700472 mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
Robert Carr4e670e52018-08-15 13:26:12 -0700473 mServerChannel->setToken(new BBinder());
Siarhei Vishniakou7c34b232019-10-11 19:08:48 -0700474 mDispatcher->registerInputChannel(mServerChannel);
chaviwfd6d3512019-03-25 13:23:49 -0700475
Robert Carr740167f2018-10-11 19:03:41 -0700476 inputApplicationHandle->updateInfo();
477 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800478 }
479
480 virtual bool updateInfo() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800481 mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
Arthur Hung3b413f22018-10-26 18:05:34 +0800482 mInfo.name = mName;
chaviwfd6d3512019-03-25 13:23:49 -0700483 mInfo.layoutParamsFlags = mLayoutParamFlags;
Arthur Hung3b413f22018-10-26 18:05:34 +0800484 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
485 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwfd6d3512019-03-25 13:23:49 -0700486 mInfo.frameLeft = mFrame.left;
487 mInfo.frameTop = mFrame.top;
488 mInfo.frameRight = mFrame.right;
489 mInfo.frameBottom = mFrame.bottom;
Robert Carre07e1032018-11-26 12:55:53 -0800490 mInfo.globalScaleFactor = 1.0;
Garfield Tan00f511d2019-06-12 16:55:40 -0700491 mInfo.touchableRegion.clear();
chaviwfd6d3512019-03-25 13:23:49 -0700492 mInfo.addTouchableRegion(mFrame);
Arthur Hung3b413f22018-10-26 18:05:34 +0800493 mInfo.visible = true;
494 mInfo.canReceiveKeys = true;
495 mInfo.hasFocus = mFocused;
496 mInfo.hasWallpaper = false;
497 mInfo.paused = false;
498 mInfo.layer = 0;
499 mInfo.ownerPid = INJECTOR_PID;
500 mInfo.ownerUid = INJECTOR_UID;
501 mInfo.inputFeatures = 0;
502 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800503
504 return true;
505 }
506
507 void setFocus() {
508 mFocused = true;
509 }
Arthur Hung832bc4a2019-01-28 11:43:17 +0800510
chaviwfd6d3512019-03-25 13:23:49 -0700511 void setFrame(const Rect& frame) {
512 mFrame.set(frame);
513 }
514
515 void setLayoutParamFlags(int32_t flags) {
516 mLayoutParamFlags = flags;
517 }
518
Arthur Hung832bc4a2019-01-28 11:43:17 +0800519 void releaseChannel() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800520 mServerChannel.clear();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800521 InputWindowHandle::releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800522 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800523protected:
524 virtual bool handled() {
525 return true;
526 }
527
528 bool mFocused;
chaviwfd6d3512019-03-25 13:23:49 -0700529 Rect mFrame;
530 int32_t mLayoutParamFlags;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800531};
532
Tiger Huang721e26f2018-07-24 22:26:19 +0800533static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
534 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800535 KeyEvent event;
536 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
537
538 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800539 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800540 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
541 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
542
543 // Inject event until dispatch out.
544 return dispatcher->injectInputEvent(
545 &event,
546 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
547 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
548}
549
Garfield Tan00f511d2019-06-12 16:55:40 -0700550static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
551 int32_t source, int32_t displayId, int32_t x, int32_t y,
552 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
553 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800554 MotionEvent event;
555 PointerProperties pointerProperties[1];
556 PointerCoords pointerCoords[1];
557
558 pointerProperties[0].clear();
559 pointerProperties[0].id = 0;
560 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
561
562 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700563 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
564 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800565
566 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
567 // Define a valid motion down event.
Garfield Tan00f511d2019-06-12 16:55:40 -0700568 event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0,
569 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
570 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
571 /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime,
572 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800573
574 // Inject event until dispatch out.
575 return dispatcher->injectInputEvent(
576 &event,
577 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
578 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
579}
580
Garfield Tan00f511d2019-06-12 16:55:40 -0700581static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
582 int32_t displayId, int32_t x = 100, int32_t y = 200) {
583 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
584}
585
Jackal Guof9696682018-10-05 12:23:23 +0800586static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
587 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
588 // Define a valid key event.
589 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
590 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
591 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
592
593 return args;
594}
595
596static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
597 PointerProperties pointerProperties[1];
598 PointerCoords pointerCoords[1];
599
600 pointerProperties[0].clear();
601 pointerProperties[0].id = 0;
602 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
603
604 pointerCoords[0].clear();
605 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
606 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
607
608 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
609 // Define a valid motion event.
610 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700611 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
612 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -0700613 AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties, pointerCoords,
614 /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700615 AMOTION_EVENT_INVALID_CURSOR_POSITION,
616 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800617
618 return args;
619}
620
Arthur Hungb92218b2018-08-14 12:00:21 +0800621TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
622 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800623 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
624 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800625
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800626 std::vector<sp<InputWindowHandle>> inputWindowHandles;
627 inputWindowHandles.push_back(window);
Arthur Hungb92218b2018-08-14 12:00:21 +0800628
629 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800630 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
631 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800632 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
633
634 // Window should receive motion event.
635 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
636}
637
638// The foreground window should receive the first touch down event.
639TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
640 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800641 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
642 ADISPLAY_ID_DEFAULT);
643 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
644 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800645
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800646 std::vector<sp<InputWindowHandle>> inputWindowHandles;
647 inputWindowHandles.push_back(windowTop);
648 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800649
650 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800651 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
652 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800653 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
654
655 // Top window should receive the touch down event. Second window should not receive anything.
656 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
657 windowSecond->assertNoEvents();
658}
659
660TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
661 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800662 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
663 ADISPLAY_ID_DEFAULT);
664 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
665 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800666
Arthur Hung7ab76b12019-01-09 19:17:20 +0800667 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800668 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800669
670 // Expect one focus window exist in display.
671 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800672 std::vector<sp<InputWindowHandle>> inputWindowHandles;
673 inputWindowHandles.push_back(windowTop);
674 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800675
676 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
677 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
678 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
679
680 // Focused window should receive event.
681 windowTop->assertNoEvents();
682 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
683}
684
Arthur Hung7ab76b12019-01-09 19:17:20 +0800685TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
686 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
687 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
688 ADISPLAY_ID_DEFAULT);
689 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
690 ADISPLAY_ID_DEFAULT);
691
692 // Set focused application.
693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
694
695 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
696 windowTop->setFocus();
697 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800698 std::vector<sp<InputWindowHandle>> inputWindowHandles;
699 inputWindowHandles.push_back(windowTop);
700 inputWindowHandles.push_back(windowSecond);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800701
702 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
703 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
704 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
705
706 // Top focused window should receive event.
707 windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
708 windowSecond->assertNoEvents();
709}
710
Arthur Hung3b413f22018-10-26 18:05:34 +0800711TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
712 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
713
714 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
715 ADISPLAY_ID_DEFAULT);
716 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
717 ADISPLAY_ID_DEFAULT);
718
Arthur Hung832bc4a2019-01-28 11:43:17 +0800719 // Set focused application.
720 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800721
Arthur Hung832bc4a2019-01-28 11:43:17 +0800722 windowTop->setFocus();
723 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800724 std::vector<sp<InputWindowHandle>> inputWindowHandles;
725 inputWindowHandles.push_back(windowTop);
726 inputWindowHandles.push_back(windowSecond);
Arthur Hung3b413f22018-10-26 18:05:34 +0800727 // Release channel for window is no longer valid.
728 windowTop->releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800729 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800730
Arthur Hung832bc4a2019-01-28 11:43:17 +0800731 // Test inject a key down, should dispatch to a valid window.
732 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
733 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800734
735 // Top window is invalid, so it should not receive any input event.
736 windowTop->assertNoEvents();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800737 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800738}
739
Garfield Tan00f511d2019-06-12 16:55:40 -0700740TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
741 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
742
743 sp<FakeWindowHandle> windowLeft =
744 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
745 windowLeft->setFrame(Rect(0, 0, 600, 800));
746 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
747 sp<FakeWindowHandle> windowRight =
748 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
749 windowRight->setFrame(Rect(600, 0, 1200, 800));
750 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
751
752 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
753
754 std::vector<sp<InputWindowHandle>> inputWindowHandles{windowLeft, windowRight};
755 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
756
757 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
758 // left window. This event should be dispatched to the left window.
759 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
760 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
761 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
762 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
763 windowRight->assertNoEvents();
764}
765
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800766/* Test InputDispatcher for MultiDisplay */
767class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
768public:
769 static constexpr int32_t SECOND_DISPLAY_ID = 1;
770 virtual void SetUp() {
771 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800772
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800773 application1 = new FakeApplicationHandle();
774 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
775 ADISPLAY_ID_DEFAULT);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800776 std::vector<sp<InputWindowHandle>> inputWindowHandles;
777 inputWindowHandles.push_back(windowInPrimary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800778 // Set focus window for primary display, but focused display would be second one.
779 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
780 windowInPrimary->setFocus();
781 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800782
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800783 application2 = new FakeApplicationHandle();
784 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
785 SECOND_DISPLAY_ID);
786 // Set focus to second display window.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800787 std::vector<sp<InputWindowHandle>> inputWindowHandles_Second;
788 inputWindowHandles_Second.push_back(windowInSecondary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800789 // Set focus display to second one.
790 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
791 // Set focus window for second display.
792 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
793 windowInSecondary->setFocus();
794 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
795 }
796
797 virtual void TearDown() {
798 InputDispatcherTest::TearDown();
799
800 application1.clear();
801 windowInPrimary.clear();
802 application2.clear();
803 windowInSecondary.clear();
804 }
805
806protected:
807 sp<FakeApplicationHandle> application1;
808 sp<FakeWindowHandle> windowInPrimary;
809 sp<FakeApplicationHandle> application2;
810 sp<FakeWindowHandle> windowInSecondary;
811};
812
813TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
814 // Test touch down on primary display.
815 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
816 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800817 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
818 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
819 windowInSecondary->assertNoEvents();
820
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800821 // Test touch down on second display.
822 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
823 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800824 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
825 windowInPrimary->assertNoEvents();
826 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
827}
828
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800829TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800830 // Test inject a key down with display id specified.
831 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
832 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
833 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
834 windowInSecondary->assertNoEvents();
835
836 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800837 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
838 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
839 windowInPrimary->assertNoEvents();
840 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
841
842 // Remove secondary display.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800843 std::vector<sp<InputWindowHandle>> noWindows;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800844 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800845
846 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800847 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
848 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800849
850 // Test inject a key down, should timeout because of no target window.
851 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
852 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
853 windowInPrimary->assertNoEvents();
854 windowInSecondary->assertNoEvents();
855}
856
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800857class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
858public:
859 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
Michael Wright3dd60e22019-03-27 22:06:44 +0000860 int32_t displayId, bool isGestureMonitor = false)
861 : FakeInputReceiver(dispatcher, name, displayId) {
862 mServerChannel->setToken(new BBinder());
863 mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800864 }
865};
866
867// Test per-display input monitors for motion event.
868TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
869 sp<FakeMonitorReceiver> monitorInPrimary =
870 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
871 sp<FakeMonitorReceiver> monitorInSecondary =
872 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
873
874 // Test touch down on primary display.
875 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
876 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
877 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
878 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
879 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
880 windowInSecondary->assertNoEvents();
881 monitorInSecondary->assertNoEvents();
882
883 // Test touch down on second display.
884 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
885 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
886 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
887 windowInPrimary->assertNoEvents();
888 monitorInPrimary->assertNoEvents();
889 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
890 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
891
892 // Test inject a non-pointer motion event.
893 // If specific a display, it will dispatch to the focused window of particular display,
894 // or it will dispatch to the focused window of focused display.
895 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
896 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
897 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
898 windowInPrimary->assertNoEvents();
899 monitorInPrimary->assertNoEvents();
900 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
901 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
902}
903
904// Test per-display input monitors for key event.
905TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
906 //Input monitor per display.
907 sp<FakeMonitorReceiver> monitorInPrimary =
908 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
909 sp<FakeMonitorReceiver> monitorInSecondary =
910 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
911
912 // Test inject a key down.
913 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
914 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
915 windowInPrimary->assertNoEvents();
916 monitorInPrimary->assertNoEvents();
917 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
918 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
919}
920
Jackal Guof9696682018-10-05 12:23:23 +0800921class InputFilterTest : public InputDispatcherTest {
922protected:
923 static constexpr int32_t SECOND_DISPLAY_ID = 1;
924
925 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
926 NotifyMotionArgs motionArgs;
927
928 motionArgs = generateMotionArgs(
929 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
930 mDispatcher->notifyMotion(&motionArgs);
931 motionArgs = generateMotionArgs(
932 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
933 mDispatcher->notifyMotion(&motionArgs);
934
935 if (expectToBeFiltered) {
936 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&motionArgs);
937 } else {
938 mFakePolicy->assertFilterInputEventWasNotCalled();
939 }
940 }
941
942 void testNotifyKey(bool expectToBeFiltered) {
943 NotifyKeyArgs keyArgs;
944
945 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
946 mDispatcher->notifyKey(&keyArgs);
947 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
948 mDispatcher->notifyKey(&keyArgs);
949
950 if (expectToBeFiltered) {
951 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&keyArgs);
952 } else {
953 mFakePolicy->assertFilterInputEventWasNotCalled();
954 }
955 }
956};
957
958// Test InputFilter for MotionEvent
959TEST_F(InputFilterTest, MotionEvent_InputFilter) {
960 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
961 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
962 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
963
964 // Enable InputFilter
965 mDispatcher->setInputFilterEnabled(true);
966 // Test touch on both primary and second display, and check if both events are filtered.
967 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
968 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
969
970 // Disable InputFilter
971 mDispatcher->setInputFilterEnabled(false);
972 // Test touch on both primary and second display, and check if both events aren't filtered.
973 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
974 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
975}
976
977// Test InputFilter for KeyEvent
978TEST_F(InputFilterTest, KeyEvent_InputFilter) {
979 // Since the InputFilter is disabled by default, check if key event aren't filtered.
980 testNotifyKey(/*expectToBeFiltered*/ false);
981
982 // Enable InputFilter
983 mDispatcher->setInputFilterEnabled(true);
984 // Send a key event, and check if it is filtered.
985 testNotifyKey(/*expectToBeFiltered*/ true);
986
987 // Disable InputFilter
988 mDispatcher->setInputFilterEnabled(false);
989 // Send a key event, and check if it isn't filtered.
990 testNotifyKey(/*expectToBeFiltered*/ false);
991}
992
chaviwfd6d3512019-03-25 13:23:49 -0700993class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
994 virtual void SetUp() {
995 InputDispatcherTest::SetUp();
996
997 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
998 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
999 ADISPLAY_ID_DEFAULT);
1000 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1001 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1002 // window.
1003 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1004
1005 mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
1006 ADISPLAY_ID_DEFAULT);
1007 mWindowFocused->setFrame(Rect(50, 50, 100, 100));
1008 mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1009 mWindowFocusedTouchPoint = 60;
1010
1011 // Set focused application.
1012 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1013 mWindowFocused->setFocus();
1014
1015 // Expect one focus window exist in display.
1016 std::vector<sp<InputWindowHandle>> inputWindowHandles;
1017 inputWindowHandles.push_back(mUnfocusedWindow);
1018 inputWindowHandles.push_back(mWindowFocused);
1019 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
1020 }
1021
1022 virtual void TearDown() {
1023 InputDispatcherTest::TearDown();
1024
1025 mUnfocusedWindow.clear();
1026 mWindowFocused.clear();
1027 }
1028
1029protected:
1030 sp<FakeWindowHandle> mUnfocusedWindow;
1031 sp<FakeWindowHandle> mWindowFocused;
1032 int32_t mWindowFocusedTouchPoint;
1033};
1034
1035// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1036// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1037// the onPointerDownOutsideFocus callback.
1038TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1039 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1040 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1041 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1042 // Call monitor to wait for the command queue to get flushed.
1043 mDispatcher->monitor();
1044
1045 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1046}
1047
1048// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1049// DOWN on the window that doesn't have focus. Ensure no window received the
1050// onPointerDownOutsideFocus callback.
1051TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1052 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1053 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1054 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1055 // Call monitor to wait for the command queue to get flushed.
1056 mDispatcher->monitor();
1057
1058 mFakePolicy->assertOnPointerDownEquals(nullptr);
1059}
1060
1061// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1062// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1063TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1064 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1065 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1066 // Call monitor to wait for the command queue to get flushed.
1067 mDispatcher->monitor();
1068
1069 mFakePolicy->assertOnPointerDownEquals(nullptr);
1070}
1071
1072// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1073// DOWN on the window that already has focus. Ensure no window received the
1074// onPointerDownOutsideFocus callback.
1075TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1076 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
1077 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1078 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
1079 mWindowFocusedTouchPoint))
1080 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1081 // Call monitor to wait for the command queue to get flushed.
1082 mDispatcher->monitor();
1083
1084 mFakePolicy->assertOnPointerDownEquals(nullptr);
1085}
1086
Garfield Tane84e6f92019-08-29 17:28:41 -07001087} // namespace android::inputdispatcher