blob: 551bee18e8062b307da0de56b6d2424afa228e35 [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 Tane4fc0102019-09-11 13:16:25 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan73007b62019-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 Tan73007b62019-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,
254 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
255 ARBITRARY_TIME, ARBITRARY_TIME, /*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,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800263 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800264 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
265 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800266 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800267 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800268 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
269 << "Should reject motion events with pointer down index too large.";
270
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800271 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800272 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800273 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
274 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800275 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800276 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800277 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
278 << "Should reject motion events with pointer down index too small.";
279
280 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800281 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800282 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800283 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
284 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800285 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800286 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800287 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
288 << "Should reject motion events with pointer up index too large.";
289
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800290 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800291 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800292 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
293 ARBITRARY_TIME, ARBITRARY_TIME, /*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 small.";
298
299 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800300 event.initialize(DEVICE_ID, source, DISPLAY_ID,
301 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
302 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800303 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800304 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800305 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
306 << "Should reject motion events with 0 pointers.";
307
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800308 event.initialize(DEVICE_ID, source, DISPLAY_ID,
309 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800310 ARBITRARY_TIME, ARBITRARY_TIME,
311 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800312 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800313 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800314 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
315 << "Should reject motion events with more than MAX_POINTERS pointers.";
316
317 // Rejects motion events with invalid pointer ids.
318 pointerProperties[0].id = -1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800319 event.initialize(DEVICE_ID, source, DISPLAY_ID,
320 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
321 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800322 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800323 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800324 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
325 << "Should reject motion events with pointer ids less than 0.";
326
327 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800328 event.initialize(DEVICE_ID, source, DISPLAY_ID,
329 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
330 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800331 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800332 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800333 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
334 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
335
336 // Rejects motion events with duplicate pointer ids.
337 pointerProperties[0].id = 1;
338 pointerProperties[1].id = 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800339 event.initialize(DEVICE_ID, source, DISPLAY_ID,
340 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
341 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800342 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800343 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800344 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
345 << "Should reject motion events with duplicate pointer ids.";
346}
347
Arthur Hungb92218b2018-08-14 12:00:21 +0800348// --- InputDispatcherTest SetInputWindowTest ---
349static const int32_t INJECT_EVENT_TIMEOUT = 500;
350static const int32_t DISPATCHING_TIMEOUT = 100;
351
352class FakeApplicationHandle : public InputApplicationHandle {
353public:
354 FakeApplicationHandle() {}
355 virtual ~FakeApplicationHandle() {}
356
357 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800358 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800359 return true;
360 }
361};
362
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800363class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800364public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800365 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
366 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800367 uint32_t consumeSeq;
368 InputEvent* event;
369 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
370 &consumeSeq, &event);
371
372 ASSERT_EQ(OK, status)
373 << mName.c_str() << ": consumer consume should return OK.";
374 ASSERT_TRUE(event != nullptr)
375 << mName.c_str() << ": consumer should have returned non-NULL event.";
376 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800377 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800378
379 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800380 << mName.c_str() << ": event displayId should be the same as expected.";
381
382 int32_t flags;
383 switch (expectedEventType) {
384 case AINPUT_EVENT_TYPE_KEY: {
385 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
386 flags = typedEvent->getFlags();
387 break;
388 }
389 case AINPUT_EVENT_TYPE_MOTION: {
390 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
391 flags = typedEvent->getFlags();
392 break;
393 }
394 default: {
395 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
396 }
397 }
398 ASSERT_EQ(expectedFlags, flags)
399 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800400
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800401 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800402 ASSERT_EQ(OK, status)
403 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
404 }
405
406 void assertNoEvents() {
407 uint32_t consumeSeq;
408 InputEvent* event;
409 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
410 &consumeSeq, &event);
411 ASSERT_NE(OK, status)
412 << mName.c_str()
413 << ": should not have received any events, so consume(..) should not return OK.";
414 }
415
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800416protected:
417 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
418 const std::string name, int32_t displayId) :
419 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
420 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
421 mConsumer = new InputConsumer(mClientChannel);
422 }
423
424 virtual ~FakeInputReceiver() {
425 }
426
427 // return true if the event has been handled.
428 virtual bool handled() {
429 return false;
430 }
431
Arthur Hungb92218b2018-08-14 12:00:21 +0800432 sp<InputDispatcher> mDispatcher;
433 sp<InputChannel> mServerChannel, mClientChannel;
434 InputConsumer *mConsumer;
435 PreallocatedInputEventFactory mEventFactory;
436
437 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800438 int32_t mDisplayId;
439};
440
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800441class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
442public:
443 static const int32_t WIDTH = 600;
444 static const int32_t HEIGHT = 800;
445
446 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
447 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800448 FakeInputReceiver(dispatcher, name, displayId),
chaviwfd6d3512019-03-25 13:23:49 -0700449 mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
Robert Carr4e670e52018-08-15 13:26:12 -0700450 mServerChannel->setToken(new BBinder());
Robert Carr803535b2018-08-02 16:38:15 -0700451 mDispatcher->registerInputChannel(mServerChannel, displayId);
chaviwfd6d3512019-03-25 13:23:49 -0700452
Robert Carr740167f2018-10-11 19:03:41 -0700453 inputApplicationHandle->updateInfo();
454 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800455 }
456
457 virtual bool updateInfo() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800458 mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
Arthur Hung3b413f22018-10-26 18:05:34 +0800459 mInfo.name = mName;
chaviwfd6d3512019-03-25 13:23:49 -0700460 mInfo.layoutParamsFlags = mLayoutParamFlags;
Arthur Hung3b413f22018-10-26 18:05:34 +0800461 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
462 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwfd6d3512019-03-25 13:23:49 -0700463 mInfo.frameLeft = mFrame.left;
464 mInfo.frameTop = mFrame.top;
465 mInfo.frameRight = mFrame.right;
466 mInfo.frameBottom = mFrame.bottom;
Robert Carre07e1032018-11-26 12:55:53 -0800467 mInfo.globalScaleFactor = 1.0;
chaviwfd6d3512019-03-25 13:23:49 -0700468 mInfo.addTouchableRegion(mFrame);
Arthur Hung3b413f22018-10-26 18:05:34 +0800469 mInfo.visible = true;
470 mInfo.canReceiveKeys = true;
471 mInfo.hasFocus = mFocused;
472 mInfo.hasWallpaper = false;
473 mInfo.paused = false;
474 mInfo.layer = 0;
475 mInfo.ownerPid = INJECTOR_PID;
476 mInfo.ownerUid = INJECTOR_UID;
477 mInfo.inputFeatures = 0;
478 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800479
480 return true;
481 }
482
483 void setFocus() {
484 mFocused = true;
485 }
Arthur Hung832bc4a2019-01-28 11:43:17 +0800486
chaviwfd6d3512019-03-25 13:23:49 -0700487 void setFrame(const Rect& frame) {
488 mFrame.set(frame);
489 }
490
491 void setLayoutParamFlags(int32_t flags) {
492 mLayoutParamFlags = flags;
493 }
494
Arthur Hung832bc4a2019-01-28 11:43:17 +0800495 void releaseChannel() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800496 mServerChannel.clear();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800497 InputWindowHandle::releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800498 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800499protected:
500 virtual bool handled() {
501 return true;
502 }
503
504 bool mFocused;
chaviwfd6d3512019-03-25 13:23:49 -0700505 Rect mFrame;
506 int32_t mLayoutParamFlags;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800507};
508
Tiger Huang721e26f2018-07-24 22:26:19 +0800509static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
510 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800511 KeyEvent event;
512 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
513
514 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800515 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800516 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
517 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
518
519 // Inject event until dispatch out.
520 return dispatcher->injectInputEvent(
521 &event,
522 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
523 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
524}
525
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800526static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
chaviwfd6d3512019-03-25 13:23:49 -0700527 int32_t displayId, int32_t x = 100, int32_t y = 200) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800528 MotionEvent event;
529 PointerProperties pointerProperties[1];
530 PointerCoords pointerCoords[1];
531
532 pointerProperties[0].clear();
533 pointerProperties[0].id = 0;
534 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
535
536 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700537 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
538 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800539
540 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
541 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800542 event.initialize(DEVICE_ID, source, displayId,
chaviwfd6d3512019-03-25 13:23:49 -0700543 AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0,
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800544 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
545 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
Arthur Hungb92218b2018-08-14 12:00:21 +0800546 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
547 pointerCoords);
548
549 // Inject event until dispatch out.
550 return dispatcher->injectInputEvent(
551 &event,
552 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
553 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
554}
555
Jackal Guof9696682018-10-05 12:23:23 +0800556static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
557 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
558 // Define a valid key event.
559 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
560 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
561 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
562
563 return args;
564}
565
566static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
567 PointerProperties pointerProperties[1];
568 PointerCoords pointerCoords[1];
569
570 pointerProperties[0].clear();
571 pointerProperties[0].id = 0;
572 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
573
574 pointerCoords[0].clear();
575 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
576 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
577
578 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
579 // Define a valid motion event.
580 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
581 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
582 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
583 AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1, pointerProperties,
584 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0, currentTime,
585 /* videoFrames */ {});
586
587 return args;
588}
589
Arthur Hungb92218b2018-08-14 12:00:21 +0800590TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
591 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800592 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
593 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800594
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800595 std::vector<sp<InputWindowHandle>> inputWindowHandles;
596 inputWindowHandles.push_back(window);
Arthur Hungb92218b2018-08-14 12:00:21 +0800597
598 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800599 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
600 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800601 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
602
603 // Window should receive motion event.
604 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
605}
606
607// The foreground window should receive the first touch down event.
608TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
609 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800610 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
611 ADISPLAY_ID_DEFAULT);
612 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
613 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800614
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800615 std::vector<sp<InputWindowHandle>> inputWindowHandles;
616 inputWindowHandles.push_back(windowTop);
617 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800618
619 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800620 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
621 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800622 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
623
624 // Top window should receive the touch down event. Second window should not receive anything.
625 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
626 windowSecond->assertNoEvents();
627}
628
629TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
630 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800631 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
632 ADISPLAY_ID_DEFAULT);
633 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
634 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800635
Arthur Hung7ab76b12019-01-09 19:17:20 +0800636 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800637 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800638
639 // Expect one focus window exist in display.
640 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800641 std::vector<sp<InputWindowHandle>> inputWindowHandles;
642 inputWindowHandles.push_back(windowTop);
643 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800644
645 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
646 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
647 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
648
649 // Focused window should receive event.
650 windowTop->assertNoEvents();
651 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
652}
653
Arthur Hung7ab76b12019-01-09 19:17:20 +0800654TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
655 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
656 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
657 ADISPLAY_ID_DEFAULT);
658 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
659 ADISPLAY_ID_DEFAULT);
660
661 // Set focused application.
662 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
663
664 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
665 windowTop->setFocus();
666 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800667 std::vector<sp<InputWindowHandle>> inputWindowHandles;
668 inputWindowHandles.push_back(windowTop);
669 inputWindowHandles.push_back(windowSecond);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800670
671 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
672 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
673 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
674
675 // Top focused window should receive event.
676 windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
677 windowSecond->assertNoEvents();
678}
679
Arthur Hung3b413f22018-10-26 18:05:34 +0800680TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
681 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
682
683 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
684 ADISPLAY_ID_DEFAULT);
685 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
686 ADISPLAY_ID_DEFAULT);
687
Arthur Hung832bc4a2019-01-28 11:43:17 +0800688 // Set focused application.
689 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800690
Arthur Hung832bc4a2019-01-28 11:43:17 +0800691 windowTop->setFocus();
692 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800693 std::vector<sp<InputWindowHandle>> inputWindowHandles;
694 inputWindowHandles.push_back(windowTop);
695 inputWindowHandles.push_back(windowSecond);
Arthur Hung3b413f22018-10-26 18:05:34 +0800696 // Release channel for window is no longer valid.
697 windowTop->releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800698 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800699
Arthur Hung832bc4a2019-01-28 11:43:17 +0800700 // Test inject a key down, should dispatch to a valid window.
701 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
702 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800703
704 // Top window is invalid, so it should not receive any input event.
705 windowTop->assertNoEvents();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800706 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800707}
708
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800709/* Test InputDispatcher for MultiDisplay */
710class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
711public:
712 static constexpr int32_t SECOND_DISPLAY_ID = 1;
713 virtual void SetUp() {
714 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800715
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800716 application1 = new FakeApplicationHandle();
717 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
718 ADISPLAY_ID_DEFAULT);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800719 std::vector<sp<InputWindowHandle>> inputWindowHandles;
720 inputWindowHandles.push_back(windowInPrimary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800721 // Set focus window for primary display, but focused display would be second one.
722 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
723 windowInPrimary->setFocus();
724 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800725
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800726 application2 = new FakeApplicationHandle();
727 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
728 SECOND_DISPLAY_ID);
729 // Set focus to second display window.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800730 std::vector<sp<InputWindowHandle>> inputWindowHandles_Second;
731 inputWindowHandles_Second.push_back(windowInSecondary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800732 // Set focus display to second one.
733 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
734 // Set focus window for second display.
735 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
736 windowInSecondary->setFocus();
737 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
738 }
739
740 virtual void TearDown() {
741 InputDispatcherTest::TearDown();
742
743 application1.clear();
744 windowInPrimary.clear();
745 application2.clear();
746 windowInSecondary.clear();
747 }
748
749protected:
750 sp<FakeApplicationHandle> application1;
751 sp<FakeWindowHandle> windowInPrimary;
752 sp<FakeApplicationHandle> application2;
753 sp<FakeWindowHandle> windowInSecondary;
754};
755
756TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
757 // Test touch down on primary display.
758 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
759 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800760 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
761 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
762 windowInSecondary->assertNoEvents();
763
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800764 // Test touch down on second display.
765 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
766 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800767 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
768 windowInPrimary->assertNoEvents();
769 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
770}
771
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800772TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800773 // Test inject a key down with display id specified.
774 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
775 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
776 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
777 windowInSecondary->assertNoEvents();
778
779 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800780 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
781 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
782 windowInPrimary->assertNoEvents();
783 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
784
785 // Remove secondary display.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800786 std::vector<sp<InputWindowHandle>> noWindows;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800787 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800788
789 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800790 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
791 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800792
793 // Test inject a key down, should timeout because of no target window.
794 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
795 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
796 windowInPrimary->assertNoEvents();
797 windowInSecondary->assertNoEvents();
798}
799
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800800class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
801public:
802 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
Michael Wright3dd60e22019-03-27 22:06:44 +0000803 int32_t displayId, bool isGestureMonitor = false)
804 : FakeInputReceiver(dispatcher, name, displayId) {
805 mServerChannel->setToken(new BBinder());
806 mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800807 }
808};
809
810// Test per-display input monitors for motion event.
811TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
812 sp<FakeMonitorReceiver> monitorInPrimary =
813 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
814 sp<FakeMonitorReceiver> monitorInSecondary =
815 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
816
817 // Test touch down on primary display.
818 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
819 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
820 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
821 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
822 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
823 windowInSecondary->assertNoEvents();
824 monitorInSecondary->assertNoEvents();
825
826 // Test touch down on second display.
827 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
828 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
829 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
830 windowInPrimary->assertNoEvents();
831 monitorInPrimary->assertNoEvents();
832 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
833 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
834
835 // Test inject a non-pointer motion event.
836 // If specific a display, it will dispatch to the focused window of particular display,
837 // or it will dispatch to the focused window of focused display.
838 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
839 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
840 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
841 windowInPrimary->assertNoEvents();
842 monitorInPrimary->assertNoEvents();
843 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
844 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
845}
846
847// Test per-display input monitors for key event.
848TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
849 //Input monitor per display.
850 sp<FakeMonitorReceiver> monitorInPrimary =
851 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
852 sp<FakeMonitorReceiver> monitorInSecondary =
853 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
854
855 // Test inject a key down.
856 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
857 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
858 windowInPrimary->assertNoEvents();
859 monitorInPrimary->assertNoEvents();
860 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
861 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
862}
863
Jackal Guof9696682018-10-05 12:23:23 +0800864class InputFilterTest : public InputDispatcherTest {
865protected:
866 static constexpr int32_t SECOND_DISPLAY_ID = 1;
867
868 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
869 NotifyMotionArgs motionArgs;
870
871 motionArgs = generateMotionArgs(
872 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
873 mDispatcher->notifyMotion(&motionArgs);
874 motionArgs = generateMotionArgs(
875 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
876 mDispatcher->notifyMotion(&motionArgs);
877
878 if (expectToBeFiltered) {
879 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&motionArgs);
880 } else {
881 mFakePolicy->assertFilterInputEventWasNotCalled();
882 }
883 }
884
885 void testNotifyKey(bool expectToBeFiltered) {
886 NotifyKeyArgs keyArgs;
887
888 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
889 mDispatcher->notifyKey(&keyArgs);
890 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
891 mDispatcher->notifyKey(&keyArgs);
892
893 if (expectToBeFiltered) {
894 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&keyArgs);
895 } else {
896 mFakePolicy->assertFilterInputEventWasNotCalled();
897 }
898 }
899};
900
901// Test InputFilter for MotionEvent
902TEST_F(InputFilterTest, MotionEvent_InputFilter) {
903 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
904 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
905 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
906
907 // Enable InputFilter
908 mDispatcher->setInputFilterEnabled(true);
909 // Test touch on both primary and second display, and check if both events are filtered.
910 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
911 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
912
913 // Disable InputFilter
914 mDispatcher->setInputFilterEnabled(false);
915 // Test touch on both primary and second display, and check if both events aren't filtered.
916 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
917 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
918}
919
920// Test InputFilter for KeyEvent
921TEST_F(InputFilterTest, KeyEvent_InputFilter) {
922 // Since the InputFilter is disabled by default, check if key event aren't filtered.
923 testNotifyKey(/*expectToBeFiltered*/ false);
924
925 // Enable InputFilter
926 mDispatcher->setInputFilterEnabled(true);
927 // Send a key event, and check if it is filtered.
928 testNotifyKey(/*expectToBeFiltered*/ true);
929
930 // Disable InputFilter
931 mDispatcher->setInputFilterEnabled(false);
932 // Send a key event, and check if it isn't filtered.
933 testNotifyKey(/*expectToBeFiltered*/ false);
934}
935
chaviwfd6d3512019-03-25 13:23:49 -0700936class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
937 virtual void SetUp() {
938 InputDispatcherTest::SetUp();
939
940 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
941 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
942 ADISPLAY_ID_DEFAULT);
943 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
944 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
945 // window.
946 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
947
948 mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
949 ADISPLAY_ID_DEFAULT);
950 mWindowFocused->setFrame(Rect(50, 50, 100, 100));
951 mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
952 mWindowFocusedTouchPoint = 60;
953
954 // Set focused application.
955 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
956 mWindowFocused->setFocus();
957
958 // Expect one focus window exist in display.
959 std::vector<sp<InputWindowHandle>> inputWindowHandles;
960 inputWindowHandles.push_back(mUnfocusedWindow);
961 inputWindowHandles.push_back(mWindowFocused);
962 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
963 }
964
965 virtual void TearDown() {
966 InputDispatcherTest::TearDown();
967
968 mUnfocusedWindow.clear();
969 mWindowFocused.clear();
970 }
971
972protected:
973 sp<FakeWindowHandle> mUnfocusedWindow;
974 sp<FakeWindowHandle> mWindowFocused;
975 int32_t mWindowFocusedTouchPoint;
976};
977
978// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
979// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
980// the onPointerDownOutsideFocus callback.
981TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
982 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
983 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
984 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
985 // Call monitor to wait for the command queue to get flushed.
986 mDispatcher->monitor();
987
988 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
989}
990
991// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
992// DOWN on the window that doesn't have focus. Ensure no window received the
993// onPointerDownOutsideFocus callback.
994TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
995 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
996 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
997 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
998 // Call monitor to wait for the command queue to get flushed.
999 mDispatcher->monitor();
1000
1001 mFakePolicy->assertOnPointerDownEquals(nullptr);
1002}
1003
1004// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1005// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1006TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1007 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1008 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1009 // Call monitor to wait for the command queue to get flushed.
1010 mDispatcher->monitor();
1011
1012 mFakePolicy->assertOnPointerDownEquals(nullptr);
1013}
1014
1015// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1016// DOWN on the window that already has focus. Ensure no window received the
1017// onPointerDownOutsideFocus callback.
1018TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1019 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
1020 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1021 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
1022 mWindowFocusedTouchPoint))
1023 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1024 // Call monitor to wait for the command queue to get flushed.
1025 mDispatcher->monitor();
1026
1027 mFakePolicy->assertOnPointerDownEquals(nullptr);
1028}
1029
Garfield Tan73007b62019-08-29 17:28:41 -07001030} // namespace android::inputdispatcher