blob: 8474b1cb8ae1462c4cac07165f6824c4f2812e05 [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
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() {
Jackal Guof9696682018-10-05 12:23:23 +080051 mInputEventFiltered = false;
52 mTime = -1;
53 mAction = -1;
54 mDisplayId = -1;
chaviwfd6d3512019-03-25 13:23:49 -070055 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +080056 }
57
58 void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyMotionArgs* args) {
59 ASSERT_TRUE(mInputEventFiltered)
60 << "Expected filterInputEvent() to have been called.";
61
62 ASSERT_EQ(mTime, args->eventTime)
63 << "Expected time of filtered event was not matched";
64 ASSERT_EQ(mAction, args->action)
65 << "Expected action of filtered event was not matched";
66 ASSERT_EQ(mDisplayId, args->displayId)
67 << "Expected displayId of filtered event was not matched";
68
69 reset();
70 }
71
72 void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyKeyArgs* args) {
73 ASSERT_TRUE(mInputEventFiltered)
74 << "Expected filterInputEvent() to have been called.";
75
76 ASSERT_EQ(mTime, args->eventTime)
77 << "Expected time of filtered event was not matched";
78 ASSERT_EQ(mAction, args->action)
79 << "Expected action of filtered event was not matched";
80 ASSERT_EQ(mDisplayId, args->displayId)
81 << "Expected displayId of filtered event was not matched";
82
83 reset();
84 }
85
86 void assertFilterInputEventWasNotCalled() {
87 ASSERT_FALSE(mInputEventFiltered)
88 << "Expected filterInputEvent() to not have been called.";
Michael Wrightd02c5b62014-02-10 15:10:22 -080089 }
90
chaviwfd6d3512019-03-25 13:23:49 -070091 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
92 ASSERT_EQ(mOnPointerDownToken, touchedToken)
93 << "Expected token from onPointerDownOutsideFocus was not matched";
94 reset();
95 }
96
Michael Wrightd02c5b62014-02-10 15:10:22 -080097private:
Jackal Guof9696682018-10-05 12:23:23 +080098 bool mInputEventFiltered;
99 nsecs_t mTime;
100 int32_t mAction;
101 int32_t mDisplayId;
chaviwfd6d3512019-03-25 13:23:49 -0700102 sp<IBinder> mOnPointerDownToken;
Jackal Guof9696682018-10-05 12:23:23 +0800103
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100104 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800105 }
106
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100107 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700108 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800109 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800110 return 0;
111 }
112
Robert Carr803535b2018-08-02 16:38:15 -0700113 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800114 }
115
chaviw0c06c6e2019-01-09 13:27:07 -0800116 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700117 }
118
Michael Wrightd02c5b62014-02-10 15:10:22 -0800119 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
120 *outConfig = mConfig;
121 }
122
Jackal Guof9696682018-10-05 12:23:23 +0800123 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
124 switch (inputEvent->getType()) {
125 case AINPUT_EVENT_TYPE_KEY: {
126 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
127 mTime = keyEvent->getEventTime();
128 mAction = keyEvent->getAction();
129 mDisplayId = keyEvent->getDisplayId();
130 break;
131 }
132
133 case AINPUT_EVENT_TYPE_MOTION: {
134 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
135 mTime = motionEvent->getEventTime();
136 mAction = motionEvent->getAction();
137 mDisplayId = motionEvent->getDisplayId();
138 break;
139 }
140 }
141
142 mInputEventFiltered = true;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800143 return true;
144 }
145
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100146 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800147 }
148
Charles Chen3611f1f2019-01-29 17:26:18 +0800149 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800150 }
151
Robert Carr803535b2018-08-02 16:38:15 -0700152 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 return 0;
155 }
156
Robert Carr803535b2018-08-02 16:38:15 -0700157 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100158 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800159 return false;
160 }
161
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100162 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800163 }
164
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100165 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166 }
167
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100168 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800169 return false;
170 }
Jackal Guof9696682018-10-05 12:23:23 +0800171
chaviwfd6d3512019-03-25 13:23:49 -0700172 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
173 mOnPointerDownToken = newToken;
174 }
175
Jackal Guof9696682018-10-05 12:23:23 +0800176 void reset() {
177 mInputEventFiltered = false;
178 mTime = -1;
179 mAction = -1;
180 mDisplayId = -1;
chaviwfd6d3512019-03-25 13:23:49 -0700181 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +0800182 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183};
184
185
186// --- InputDispatcherTest ---
187
188class InputDispatcherTest : public testing::Test {
189protected:
190 sp<FakeInputDispatcherPolicy> mFakePolicy;
191 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800192 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193
194 virtual void SetUp() {
195 mFakePolicy = new FakeInputDispatcherPolicy();
196 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800197 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
198 //Start InputDispatcher thread
199 mDispatcherThread = new InputDispatcherThread(mDispatcher);
200 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800201 }
202
203 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800204 mDispatcherThread->requestExit();
205 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206 mFakePolicy.clear();
207 mDispatcher.clear();
208 }
209};
210
211
212TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
213 KeyEvent event;
214
215 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100216 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217 /*action*/ -1, 0,
218 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800219 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800220 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800221 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
222 << "Should reject key events with undefined action.";
223
224 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100225 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800226 AKEY_EVENT_ACTION_MULTIPLE, 0,
227 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800228 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800229 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800230 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
231 << "Should reject key events with ACTION_MULTIPLE.";
232}
233
234TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
235 MotionEvent event;
236 PointerProperties pointerProperties[MAX_POINTERS + 1];
237 PointerCoords pointerCoords[MAX_POINTERS + 1];
238 for (int i = 0; i <= MAX_POINTERS; i++) {
239 pointerProperties[i].clear();
240 pointerProperties[i].id = i;
241 pointerCoords[i].clear();
242 }
243
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800244 // Some constants commonly used below
245 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
246 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
247 constexpr int32_t metaState = AMETA_NONE;
248 constexpr MotionClassification classification = MotionClassification::NONE;
249
Michael Wrightd02c5b62014-02-10 15:10:22 -0800250 // Rejects undefined motion actions.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800251 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700252 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
253 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
254 ARBITRARY_TIME, ARBITRARY_TIME,
255 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800256 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800257 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800258 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
259 << "Should reject motion events with undefined action.";
260
261 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800262 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700263 AMOTION_EVENT_ACTION_POINTER_DOWN |
264 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
265 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
266 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
267 ARBITRARY_TIME, ARBITRARY_TIME,
268 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800269 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800270 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
272 << "Should reject motion events with pointer down index too large.";
273
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800274 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700275 AMOTION_EVENT_ACTION_POINTER_DOWN |
276 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
277 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
278 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
279 ARBITRARY_TIME, ARBITRARY_TIME,
280 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800281 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800282 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
284 << "Should reject motion events with pointer down index too small.";
285
286 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800287 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700288 AMOTION_EVENT_ACTION_POINTER_UP |
289 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
290 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
291 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
292 ARBITRARY_TIME, ARBITRARY_TIME,
293 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800294 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800295 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800296 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
297 << "Should reject motion events with pointer up index too large.";
298
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800299 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700300 AMOTION_EVENT_ACTION_POINTER_UP |
301 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
302 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
303 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
304 ARBITRARY_TIME, ARBITRARY_TIME,
305 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800306 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800307 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
309 << "Should reject motion events with pointer up index too small.";
310
311 // Rejects motion events with invalid number of pointers.
Garfield Tan00f511d2019-06-12 16:55:40 -0700312 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
313 metaState, 0, classification, 0, 0, 0, 0,
314 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
315 ARBITRARY_TIME, ARBITRARY_TIME,
316 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800317 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800318 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
320 << "Should reject motion events with 0 pointers.";
321
Garfield Tan00f511d2019-06-12 16:55:40 -0700322 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
323 metaState, 0, classification, 0, 0, 0, 0,
324 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
325 ARBITRARY_TIME, ARBITRARY_TIME,
326 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800327 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800328 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800329 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
330 << "Should reject motion events with more than MAX_POINTERS pointers.";
331
332 // Rejects motion events with invalid pointer ids.
333 pointerProperties[0].id = -1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700334 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
335 metaState, 0, classification, 0, 0, 0, 0,
336 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
337 ARBITRARY_TIME, ARBITRARY_TIME,
338 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800339 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800340 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800341 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
342 << "Should reject motion events with pointer ids less than 0.";
343
344 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700345 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
346 metaState, 0, classification, 0, 0, 0, 0,
347 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
348 ARBITRARY_TIME, ARBITRARY_TIME,
349 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800350 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800351 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800352 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
353 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
354
355 // Rejects motion events with duplicate pointer ids.
356 pointerProperties[0].id = 1;
357 pointerProperties[1].id = 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700358 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
359 metaState, 0, classification, 0, 0, 0, 0,
360 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
361 ARBITRARY_TIME, ARBITRARY_TIME,
362 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800363 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800364 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800365 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
366 << "Should reject motion events with duplicate pointer ids.";
367}
368
Arthur Hungb92218b2018-08-14 12:00:21 +0800369// --- InputDispatcherTest SetInputWindowTest ---
370static const int32_t INJECT_EVENT_TIMEOUT = 500;
371static const int32_t DISPATCHING_TIMEOUT = 100;
372
373class FakeApplicationHandle : public InputApplicationHandle {
374public:
375 FakeApplicationHandle() {}
376 virtual ~FakeApplicationHandle() {}
377
378 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800379 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800380 return true;
381 }
382};
383
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800384class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800385public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800386 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
387 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800388 uint32_t consumeSeq;
389 InputEvent* event;
390 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
391 &consumeSeq, &event);
392
393 ASSERT_EQ(OK, status)
394 << mName.c_str() << ": consumer consume should return OK.";
395 ASSERT_TRUE(event != nullptr)
396 << mName.c_str() << ": consumer should have returned non-NULL event.";
397 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800398 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800399
400 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800401 << mName.c_str() << ": event displayId should be the same as expected.";
402
403 int32_t flags;
404 switch (expectedEventType) {
405 case AINPUT_EVENT_TYPE_KEY: {
406 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
407 flags = typedEvent->getFlags();
408 break;
409 }
410 case AINPUT_EVENT_TYPE_MOTION: {
411 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
412 flags = typedEvent->getFlags();
413 break;
414 }
415 default: {
416 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
417 }
418 }
419 ASSERT_EQ(expectedFlags, flags)
420 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800421
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800422 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800423 ASSERT_EQ(OK, status)
424 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
425 }
426
427 void assertNoEvents() {
428 uint32_t consumeSeq;
429 InputEvent* event;
430 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
431 &consumeSeq, &event);
432 ASSERT_NE(OK, status)
433 << mName.c_str()
434 << ": should not have received any events, so consume(..) should not return OK.";
435 }
436
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800437protected:
438 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
439 const std::string name, int32_t displayId) :
440 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
441 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
442 mConsumer = new InputConsumer(mClientChannel);
443 }
444
445 virtual ~FakeInputReceiver() {
446 }
447
448 // return true if the event has been handled.
449 virtual bool handled() {
450 return false;
451 }
452
Arthur Hungb92218b2018-08-14 12:00:21 +0800453 sp<InputDispatcher> mDispatcher;
454 sp<InputChannel> mServerChannel, mClientChannel;
455 InputConsumer *mConsumer;
456 PreallocatedInputEventFactory mEventFactory;
457
458 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800459 int32_t mDisplayId;
460};
461
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800462class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
463public:
464 static const int32_t WIDTH = 600;
465 static const int32_t HEIGHT = 800;
466
467 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
468 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800469 FakeInputReceiver(dispatcher, name, displayId),
chaviwfd6d3512019-03-25 13:23:49 -0700470 mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
Robert Carr4e670e52018-08-15 13:26:12 -0700471 mServerChannel->setToken(new BBinder());
Robert Carr803535b2018-08-02 16:38:15 -0700472 mDispatcher->registerInputChannel(mServerChannel, displayId);
chaviwfd6d3512019-03-25 13:23:49 -0700473
Robert Carr740167f2018-10-11 19:03:41 -0700474 inputApplicationHandle->updateInfo();
475 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800476 }
477
478 virtual bool updateInfo() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800479 mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
Arthur Hung3b413f22018-10-26 18:05:34 +0800480 mInfo.name = mName;
chaviwfd6d3512019-03-25 13:23:49 -0700481 mInfo.layoutParamsFlags = mLayoutParamFlags;
Arthur Hung3b413f22018-10-26 18:05:34 +0800482 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
483 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwfd6d3512019-03-25 13:23:49 -0700484 mInfo.frameLeft = mFrame.left;
485 mInfo.frameTop = mFrame.top;
486 mInfo.frameRight = mFrame.right;
487 mInfo.frameBottom = mFrame.bottom;
Robert Carre07e1032018-11-26 12:55:53 -0800488 mInfo.globalScaleFactor = 1.0;
Garfield Tan00f511d2019-06-12 16:55:40 -0700489 mInfo.touchableRegion.clear();
chaviwfd6d3512019-03-25 13:23:49 -0700490 mInfo.addTouchableRegion(mFrame);
Arthur Hung3b413f22018-10-26 18:05:34 +0800491 mInfo.visible = true;
492 mInfo.canReceiveKeys = true;
493 mInfo.hasFocus = mFocused;
494 mInfo.hasWallpaper = false;
495 mInfo.paused = false;
496 mInfo.layer = 0;
497 mInfo.ownerPid = INJECTOR_PID;
498 mInfo.ownerUid = INJECTOR_UID;
499 mInfo.inputFeatures = 0;
500 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800501
502 return true;
503 }
504
505 void setFocus() {
506 mFocused = true;
507 }
Arthur Hung832bc4a2019-01-28 11:43:17 +0800508
chaviwfd6d3512019-03-25 13:23:49 -0700509 void setFrame(const Rect& frame) {
510 mFrame.set(frame);
511 }
512
513 void setLayoutParamFlags(int32_t flags) {
514 mLayoutParamFlags = flags;
515 }
516
Arthur Hung832bc4a2019-01-28 11:43:17 +0800517 void releaseChannel() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800518 mServerChannel.clear();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800519 InputWindowHandle::releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800520 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800521protected:
522 virtual bool handled() {
523 return true;
524 }
525
526 bool mFocused;
chaviwfd6d3512019-03-25 13:23:49 -0700527 Rect mFrame;
528 int32_t mLayoutParamFlags;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800529};
530
Tiger Huang721e26f2018-07-24 22:26:19 +0800531static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
532 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800533 KeyEvent event;
534 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
535
536 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800537 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800538 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
539 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
540
541 // Inject event until dispatch out.
542 return dispatcher->injectInputEvent(
543 &event,
544 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
545 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
546}
547
Garfield Tan00f511d2019-06-12 16:55:40 -0700548static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
549 int32_t source, int32_t displayId, int32_t x, int32_t y,
550 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
551 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800552 MotionEvent event;
553 PointerProperties pointerProperties[1];
554 PointerCoords pointerCoords[1];
555
556 pointerProperties[0].clear();
557 pointerProperties[0].id = 0;
558 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
559
560 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700561 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
562 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800563
564 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
565 // Define a valid motion down event.
Garfield Tan00f511d2019-06-12 16:55:40 -0700566 event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0,
567 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
568 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
569 /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime,
570 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800571
572 // Inject event until dispatch out.
573 return dispatcher->injectInputEvent(
574 &event,
575 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
576 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
577}
578
Garfield Tan00f511d2019-06-12 16:55:40 -0700579static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
580 int32_t displayId, int32_t x = 100, int32_t y = 200) {
581 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
582}
583
Jackal Guof9696682018-10-05 12:23:23 +0800584static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
585 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
586 // Define a valid key event.
587 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
588 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
589 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
590
591 return args;
592}
593
594static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
595 PointerProperties pointerProperties[1];
596 PointerCoords pointerCoords[1];
597
598 pointerProperties[0].clear();
599 pointerProperties[0].id = 0;
600 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
601
602 pointerCoords[0].clear();
603 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
604 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
605
606 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
607 // Define a valid motion event.
608 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700609 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
610 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -0700611 AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties, pointerCoords,
612 /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700613 AMOTION_EVENT_INVALID_CURSOR_POSITION,
614 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800615
616 return args;
617}
618
Arthur Hungb92218b2018-08-14 12:00:21 +0800619TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
620 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800621 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
622 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800623
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800624 std::vector<sp<InputWindowHandle>> inputWindowHandles;
625 inputWindowHandles.push_back(window);
Arthur Hungb92218b2018-08-14 12:00:21 +0800626
627 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800628 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
629 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800630 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
631
632 // Window should receive motion event.
633 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
634}
635
636// The foreground window should receive the first touch down event.
637TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
638 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800639 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
640 ADISPLAY_ID_DEFAULT);
641 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
642 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800643
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800644 std::vector<sp<InputWindowHandle>> inputWindowHandles;
645 inputWindowHandles.push_back(windowTop);
646 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800647
648 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800649 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
650 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800651 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
652
653 // Top window should receive the touch down event. Second window should not receive anything.
654 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
655 windowSecond->assertNoEvents();
656}
657
658TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
659 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800660 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
661 ADISPLAY_ID_DEFAULT);
662 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
663 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800664
Arthur Hung7ab76b12019-01-09 19:17:20 +0800665 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800666 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800667
668 // Expect one focus window exist in display.
669 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800670 std::vector<sp<InputWindowHandle>> inputWindowHandles;
671 inputWindowHandles.push_back(windowTop);
672 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800673
674 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
675 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
676 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
677
678 // Focused window should receive event.
679 windowTop->assertNoEvents();
680 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
681}
682
Arthur Hung7ab76b12019-01-09 19:17:20 +0800683TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
684 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
685 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
686 ADISPLAY_ID_DEFAULT);
687 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
688 ADISPLAY_ID_DEFAULT);
689
690 // Set focused application.
691 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
692
693 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
694 windowTop->setFocus();
695 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800696 std::vector<sp<InputWindowHandle>> inputWindowHandles;
697 inputWindowHandles.push_back(windowTop);
698 inputWindowHandles.push_back(windowSecond);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800699
700 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
701 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
702 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
703
704 // Top focused window should receive event.
705 windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
706 windowSecond->assertNoEvents();
707}
708
Arthur Hung3b413f22018-10-26 18:05:34 +0800709TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
710 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
711
712 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
713 ADISPLAY_ID_DEFAULT);
714 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
715 ADISPLAY_ID_DEFAULT);
716
Arthur Hung832bc4a2019-01-28 11:43:17 +0800717 // Set focused application.
718 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800719
Arthur Hung832bc4a2019-01-28 11:43:17 +0800720 windowTop->setFocus();
721 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800722 std::vector<sp<InputWindowHandle>> inputWindowHandles;
723 inputWindowHandles.push_back(windowTop);
724 inputWindowHandles.push_back(windowSecond);
Arthur Hung3b413f22018-10-26 18:05:34 +0800725 // Release channel for window is no longer valid.
726 windowTop->releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800727 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800728
Arthur Hung832bc4a2019-01-28 11:43:17 +0800729 // Test inject a key down, should dispatch to a valid window.
730 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
731 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800732
733 // Top window is invalid, so it should not receive any input event.
734 windowTop->assertNoEvents();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800735 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800736}
737
Garfield Tan00f511d2019-06-12 16:55:40 -0700738TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
739 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
740
741 sp<FakeWindowHandle> windowLeft =
742 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
743 windowLeft->setFrame(Rect(0, 0, 600, 800));
744 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
745 sp<FakeWindowHandle> windowRight =
746 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
747 windowRight->setFrame(Rect(600, 0, 1200, 800));
748 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
749
750 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
751
752 std::vector<sp<InputWindowHandle>> inputWindowHandles{windowLeft, windowRight};
753 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
754
755 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
756 // left window. This event should be dispatched to the left window.
757 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
758 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
759 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
760 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
761 windowRight->assertNoEvents();
762}
763
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800764/* Test InputDispatcher for MultiDisplay */
765class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
766public:
767 static constexpr int32_t SECOND_DISPLAY_ID = 1;
768 virtual void SetUp() {
769 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800770
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800771 application1 = new FakeApplicationHandle();
772 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
773 ADISPLAY_ID_DEFAULT);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800774 std::vector<sp<InputWindowHandle>> inputWindowHandles;
775 inputWindowHandles.push_back(windowInPrimary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800776 // Set focus window for primary display, but focused display would be second one.
777 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
778 windowInPrimary->setFocus();
779 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800780
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800781 application2 = new FakeApplicationHandle();
782 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
783 SECOND_DISPLAY_ID);
784 // Set focus to second display window.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800785 std::vector<sp<InputWindowHandle>> inputWindowHandles_Second;
786 inputWindowHandles_Second.push_back(windowInSecondary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800787 // Set focus display to second one.
788 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
789 // Set focus window for second display.
790 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
791 windowInSecondary->setFocus();
792 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
793 }
794
795 virtual void TearDown() {
796 InputDispatcherTest::TearDown();
797
798 application1.clear();
799 windowInPrimary.clear();
800 application2.clear();
801 windowInSecondary.clear();
802 }
803
804protected:
805 sp<FakeApplicationHandle> application1;
806 sp<FakeWindowHandle> windowInPrimary;
807 sp<FakeApplicationHandle> application2;
808 sp<FakeWindowHandle> windowInSecondary;
809};
810
811TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
812 // Test touch down on primary display.
813 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
814 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800815 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
816 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
817 windowInSecondary->assertNoEvents();
818
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800819 // Test touch down on second display.
820 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
821 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800822 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
823 windowInPrimary->assertNoEvents();
824 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
825}
826
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800827TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800828 // Test inject a key down with display id specified.
829 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
830 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
831 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
832 windowInSecondary->assertNoEvents();
833
834 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800835 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
836 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
837 windowInPrimary->assertNoEvents();
838 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
839
840 // Remove secondary display.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800841 std::vector<sp<InputWindowHandle>> noWindows;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800842 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800843
844 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800845 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
846 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800847
848 // Test inject a key down, should timeout because of no target window.
849 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
850 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
851 windowInPrimary->assertNoEvents();
852 windowInSecondary->assertNoEvents();
853}
854
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800855class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
856public:
857 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
Michael Wright3dd60e22019-03-27 22:06:44 +0000858 int32_t displayId, bool isGestureMonitor = false)
859 : FakeInputReceiver(dispatcher, name, displayId) {
860 mServerChannel->setToken(new BBinder());
861 mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800862 }
863};
864
865// Test per-display input monitors for motion event.
866TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
867 sp<FakeMonitorReceiver> monitorInPrimary =
868 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
869 sp<FakeMonitorReceiver> monitorInSecondary =
870 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
871
872 // Test touch down on primary display.
873 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
874 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
875 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
876 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
877 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
878 windowInSecondary->assertNoEvents();
879 monitorInSecondary->assertNoEvents();
880
881 // Test touch down on second display.
882 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
883 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
884 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
885 windowInPrimary->assertNoEvents();
886 monitorInPrimary->assertNoEvents();
887 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
888 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
889
890 // Test inject a non-pointer motion event.
891 // If specific a display, it will dispatch to the focused window of particular display,
892 // or it will dispatch to the focused window of focused display.
893 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
894 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
895 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
896 windowInPrimary->assertNoEvents();
897 monitorInPrimary->assertNoEvents();
898 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
899 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
900}
901
902// Test per-display input monitors for key event.
903TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
904 //Input monitor per display.
905 sp<FakeMonitorReceiver> monitorInPrimary =
906 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
907 sp<FakeMonitorReceiver> monitorInSecondary =
908 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
909
910 // Test inject a key down.
911 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
912 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
913 windowInPrimary->assertNoEvents();
914 monitorInPrimary->assertNoEvents();
915 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
916 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
917}
918
Jackal Guof9696682018-10-05 12:23:23 +0800919class InputFilterTest : public InputDispatcherTest {
920protected:
921 static constexpr int32_t SECOND_DISPLAY_ID = 1;
922
923 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
924 NotifyMotionArgs motionArgs;
925
926 motionArgs = generateMotionArgs(
927 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
928 mDispatcher->notifyMotion(&motionArgs);
929 motionArgs = generateMotionArgs(
930 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
931 mDispatcher->notifyMotion(&motionArgs);
932
933 if (expectToBeFiltered) {
934 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&motionArgs);
935 } else {
936 mFakePolicy->assertFilterInputEventWasNotCalled();
937 }
938 }
939
940 void testNotifyKey(bool expectToBeFiltered) {
941 NotifyKeyArgs keyArgs;
942
943 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
944 mDispatcher->notifyKey(&keyArgs);
945 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
946 mDispatcher->notifyKey(&keyArgs);
947
948 if (expectToBeFiltered) {
949 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&keyArgs);
950 } else {
951 mFakePolicy->assertFilterInputEventWasNotCalled();
952 }
953 }
954};
955
956// Test InputFilter for MotionEvent
957TEST_F(InputFilterTest, MotionEvent_InputFilter) {
958 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
959 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
960 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
961
962 // Enable InputFilter
963 mDispatcher->setInputFilterEnabled(true);
964 // Test touch on both primary and second display, and check if both events are filtered.
965 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
966 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
967
968 // Disable InputFilter
969 mDispatcher->setInputFilterEnabled(false);
970 // Test touch on both primary and second display, and check if both events aren't filtered.
971 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
972 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
973}
974
975// Test InputFilter for KeyEvent
976TEST_F(InputFilterTest, KeyEvent_InputFilter) {
977 // Since the InputFilter is disabled by default, check if key event aren't filtered.
978 testNotifyKey(/*expectToBeFiltered*/ false);
979
980 // Enable InputFilter
981 mDispatcher->setInputFilterEnabled(true);
982 // Send a key event, and check if it is filtered.
983 testNotifyKey(/*expectToBeFiltered*/ true);
984
985 // Disable InputFilter
986 mDispatcher->setInputFilterEnabled(false);
987 // Send a key event, and check if it isn't filtered.
988 testNotifyKey(/*expectToBeFiltered*/ false);
989}
990
chaviwfd6d3512019-03-25 13:23:49 -0700991class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
992 virtual void SetUp() {
993 InputDispatcherTest::SetUp();
994
995 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
996 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
997 ADISPLAY_ID_DEFAULT);
998 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
999 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1000 // window.
1001 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1002
1003 mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
1004 ADISPLAY_ID_DEFAULT);
1005 mWindowFocused->setFrame(Rect(50, 50, 100, 100));
1006 mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1007 mWindowFocusedTouchPoint = 60;
1008
1009 // Set focused application.
1010 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1011 mWindowFocused->setFocus();
1012
1013 // Expect one focus window exist in display.
1014 std::vector<sp<InputWindowHandle>> inputWindowHandles;
1015 inputWindowHandles.push_back(mUnfocusedWindow);
1016 inputWindowHandles.push_back(mWindowFocused);
1017 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
1018 }
1019
1020 virtual void TearDown() {
1021 InputDispatcherTest::TearDown();
1022
1023 mUnfocusedWindow.clear();
1024 mWindowFocused.clear();
1025 }
1026
1027protected:
1028 sp<FakeWindowHandle> mUnfocusedWindow;
1029 sp<FakeWindowHandle> mWindowFocused;
1030 int32_t mWindowFocusedTouchPoint;
1031};
1032
1033// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1034// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1035// the onPointerDownOutsideFocus callback.
1036TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1037 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1038 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1039 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1040 // Call monitor to wait for the command queue to get flushed.
1041 mDispatcher->monitor();
1042
1043 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1044}
1045
1046// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1047// DOWN on the window that doesn't have focus. Ensure no window received the
1048// onPointerDownOutsideFocus callback.
1049TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1050 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1051 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1052 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1053 // Call monitor to wait for the command queue to get flushed.
1054 mDispatcher->monitor();
1055
1056 mFakePolicy->assertOnPointerDownEquals(nullptr);
1057}
1058
1059// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1060// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1061TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1062 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1063 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1064 // Call monitor to wait for the command queue to get flushed.
1065 mDispatcher->monitor();
1066
1067 mFakePolicy->assertOnPointerDownEquals(nullptr);
1068}
1069
1070// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1071// DOWN on the window that already has focus. Ensure no window received the
1072// onPointerDownOutsideFocus callback.
1073TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1074 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
1075 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1076 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
1077 mWindowFocusedTouchPoint))
1078 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1079 // Call monitor to wait for the command queue to get flushed.
1080 mDispatcher->monitor();
1081
1082 mFakePolicy->assertOnPointerDownEquals(nullptr);
1083}
1084
Michael Wrightd02c5b62014-02-10 15:10:22 -08001085} // namespace android