blob: 9fe6481ca02ef417903412e5a46b31f45757334e [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "../InputDispatcher.h"
18
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
20
Michael Wrightd02c5b62014-02-10 15:10:22 -080021#include <gtest/gtest.h>
22#include <linux/input.h>
23
24namespace android {
25
26// An arbitrary time value.
27static const nsecs_t ARBITRARY_TIME = 1234;
28
29// An arbitrary device id.
30static const int32_t DEVICE_ID = 1;
31
Jeff Brownf086ddb2014-02-11 14:28:48 -080032// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080033static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080034
Michael Wrightd02c5b62014-02-10 15:10:22 -080035// An arbitrary injector pid / uid pair that has permission to inject events.
36static const int32_t INJECTOR_PID = 999;
37static const int32_t INJECTOR_UID = 1001;
38
39
40// --- FakeInputDispatcherPolicy ---
41
42class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
43 InputDispatcherConfiguration mConfig;
44
45protected:
46 virtual ~FakeInputDispatcherPolicy() {
47 }
48
49public:
50 FakeInputDispatcherPolicy() {
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,
252 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
253 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800254 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800255 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800256 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
257 << "Should reject motion events with undefined action.";
258
259 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800260 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800261 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800262 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
263 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800264 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800265 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800266 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
267 << "Should reject motion events with pointer down index too large.";
268
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800269 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800270 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800271 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
272 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800273 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800274 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800275 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
276 << "Should reject motion events with pointer down index too small.";
277
278 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800279 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800280 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800281 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
282 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800283 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800284 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
286 << "Should reject motion events with pointer up index too large.";
287
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800288 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800289 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800290 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
291 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800292 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800293 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800294 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
295 << "Should reject motion events with pointer up index too small.";
296
297 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800298 event.initialize(DEVICE_ID, source, DISPLAY_ID,
299 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
300 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800301 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800302 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800303 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
304 << "Should reject motion events with 0 pointers.";
305
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800306 event.initialize(DEVICE_ID, source, DISPLAY_ID,
307 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 ARBITRARY_TIME, ARBITRARY_TIME,
309 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800310 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800311 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800312 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
313 << "Should reject motion events with more than MAX_POINTERS pointers.";
314
315 // Rejects motion events with invalid pointer ids.
316 pointerProperties[0].id = -1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800317 event.initialize(DEVICE_ID, source, DISPLAY_ID,
318 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
319 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800320 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800321 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800322 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
323 << "Should reject motion events with pointer ids less than 0.";
324
325 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800326 event.initialize(DEVICE_ID, source, DISPLAY_ID,
327 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
328 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800329 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800330 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800331 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
332 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
333
334 // Rejects motion events with duplicate pointer ids.
335 pointerProperties[0].id = 1;
336 pointerProperties[1].id = 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800337 event.initialize(DEVICE_ID, source, DISPLAY_ID,
338 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
339 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800340 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800341 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800342 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
343 << "Should reject motion events with duplicate pointer ids.";
344}
345
Arthur Hungb92218b2018-08-14 12:00:21 +0800346// --- InputDispatcherTest SetInputWindowTest ---
347static const int32_t INJECT_EVENT_TIMEOUT = 500;
348static const int32_t DISPATCHING_TIMEOUT = 100;
349
350class FakeApplicationHandle : public InputApplicationHandle {
351public:
352 FakeApplicationHandle() {}
353 virtual ~FakeApplicationHandle() {}
354
355 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800356 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800357 return true;
358 }
359};
360
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800361class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800362public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800363 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
364 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800365 uint32_t consumeSeq;
366 InputEvent* event;
367 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
368 &consumeSeq, &event);
369
370 ASSERT_EQ(OK, status)
371 << mName.c_str() << ": consumer consume should return OK.";
372 ASSERT_TRUE(event != nullptr)
373 << mName.c_str() << ": consumer should have returned non-NULL event.";
374 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800375 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800376
377 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800378 << mName.c_str() << ": event displayId should be the same as expected.";
379
380 int32_t flags;
381 switch (expectedEventType) {
382 case AINPUT_EVENT_TYPE_KEY: {
383 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
384 flags = typedEvent->getFlags();
385 break;
386 }
387 case AINPUT_EVENT_TYPE_MOTION: {
388 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
389 flags = typedEvent->getFlags();
390 break;
391 }
392 default: {
393 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
394 }
395 }
396 ASSERT_EQ(expectedFlags, flags)
397 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800398
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800399 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800400 ASSERT_EQ(OK, status)
401 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
402 }
403
404 void assertNoEvents() {
405 uint32_t consumeSeq;
406 InputEvent* event;
407 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
408 &consumeSeq, &event);
409 ASSERT_NE(OK, status)
410 << mName.c_str()
411 << ": should not have received any events, so consume(..) should not return OK.";
412 }
413
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800414protected:
415 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
416 const std::string name, int32_t displayId) :
417 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
418 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
419 mConsumer = new InputConsumer(mClientChannel);
420 }
421
422 virtual ~FakeInputReceiver() {
423 }
424
425 // return true if the event has been handled.
426 virtual bool handled() {
427 return false;
428 }
429
Arthur Hungb92218b2018-08-14 12:00:21 +0800430 sp<InputDispatcher> mDispatcher;
431 sp<InputChannel> mServerChannel, mClientChannel;
432 InputConsumer *mConsumer;
433 PreallocatedInputEventFactory mEventFactory;
434
435 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800436 int32_t mDisplayId;
437};
438
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800439class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
440public:
441 static const int32_t WIDTH = 600;
442 static const int32_t HEIGHT = 800;
443
444 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
445 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800446 FakeInputReceiver(dispatcher, name, displayId),
chaviwfd6d3512019-03-25 13:23:49 -0700447 mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
Robert Carr4e670e52018-08-15 13:26:12 -0700448 mServerChannel->setToken(new BBinder());
Robert Carr803535b2018-08-02 16:38:15 -0700449 mDispatcher->registerInputChannel(mServerChannel, displayId);
chaviwfd6d3512019-03-25 13:23:49 -0700450
Robert Carr740167f2018-10-11 19:03:41 -0700451 inputApplicationHandle->updateInfo();
452 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800453 }
454
455 virtual bool updateInfo() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800456 mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
Arthur Hung3b413f22018-10-26 18:05:34 +0800457 mInfo.name = mName;
chaviwfd6d3512019-03-25 13:23:49 -0700458 mInfo.layoutParamsFlags = mLayoutParamFlags;
Arthur Hung3b413f22018-10-26 18:05:34 +0800459 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
460 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwfd6d3512019-03-25 13:23:49 -0700461 mInfo.frameLeft = mFrame.left;
462 mInfo.frameTop = mFrame.top;
463 mInfo.frameRight = mFrame.right;
464 mInfo.frameBottom = mFrame.bottom;
Robert Carre07e1032018-11-26 12:55:53 -0800465 mInfo.globalScaleFactor = 1.0;
chaviwfd6d3512019-03-25 13:23:49 -0700466 mInfo.addTouchableRegion(mFrame);
Arthur Hung3b413f22018-10-26 18:05:34 +0800467 mInfo.visible = true;
468 mInfo.canReceiveKeys = true;
469 mInfo.hasFocus = mFocused;
470 mInfo.hasWallpaper = false;
471 mInfo.paused = false;
472 mInfo.layer = 0;
473 mInfo.ownerPid = INJECTOR_PID;
474 mInfo.ownerUid = INJECTOR_UID;
475 mInfo.inputFeatures = 0;
476 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800477
478 return true;
479 }
480
481 void setFocus() {
482 mFocused = true;
483 }
Arthur Hung832bc4a2019-01-28 11:43:17 +0800484
chaviwfd6d3512019-03-25 13:23:49 -0700485 void setFrame(const Rect& frame) {
486 mFrame.set(frame);
487 }
488
489 void setLayoutParamFlags(int32_t flags) {
490 mLayoutParamFlags = flags;
491 }
492
Arthur Hung832bc4a2019-01-28 11:43:17 +0800493 void releaseChannel() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800494 mServerChannel.clear();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800495 InputWindowHandle::releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800496 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800497protected:
498 virtual bool handled() {
499 return true;
500 }
501
502 bool mFocused;
chaviwfd6d3512019-03-25 13:23:49 -0700503 Rect mFrame;
504 int32_t mLayoutParamFlags;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800505};
506
Tiger Huang721e26f2018-07-24 22:26:19 +0800507static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
508 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800509 KeyEvent event;
510 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
511
512 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800513 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800514 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
515 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
516
517 // Inject event until dispatch out.
518 return dispatcher->injectInputEvent(
519 &event,
520 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
521 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
522}
523
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800524static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
chaviwfd6d3512019-03-25 13:23:49 -0700525 int32_t displayId, int32_t x = 100, int32_t y = 200) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800526 MotionEvent event;
527 PointerProperties pointerProperties[1];
528 PointerCoords pointerCoords[1];
529
530 pointerProperties[0].clear();
531 pointerProperties[0].id = 0;
532 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
533
534 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700535 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
536 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800537
538 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
539 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800540 event.initialize(DEVICE_ID, source, displayId,
chaviwfd6d3512019-03-25 13:23:49 -0700541 AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0,
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800542 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
543 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
Arthur Hungb92218b2018-08-14 12:00:21 +0800544 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
545 pointerCoords);
546
547 // Inject event until dispatch out.
548 return dispatcher->injectInputEvent(
549 &event,
550 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
551 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
552}
553
Jackal Guof9696682018-10-05 12:23:23 +0800554static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
555 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
556 // Define a valid key event.
557 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
558 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
559 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
560
561 return args;
562}
563
564static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
565 PointerProperties pointerProperties[1];
566 PointerCoords pointerCoords[1];
567
568 pointerProperties[0].clear();
569 pointerProperties[0].id = 0;
570 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
571
572 pointerCoords[0].clear();
573 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
574 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
575
576 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
577 // Define a valid motion event.
578 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
579 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
580 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
581 AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1, pointerProperties,
582 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0, currentTime,
583 /* videoFrames */ {});
584
585 return args;
586}
587
Arthur Hungb92218b2018-08-14 12:00:21 +0800588TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
589 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800590 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
591 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800592
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800593 std::vector<sp<InputWindowHandle>> inputWindowHandles;
594 inputWindowHandles.push_back(window);
Arthur Hungb92218b2018-08-14 12:00:21 +0800595
596 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800597 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
598 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800599 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
600
601 // Window should receive motion event.
602 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
603}
604
605// The foreground window should receive the first touch down event.
606TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
607 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800608 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
609 ADISPLAY_ID_DEFAULT);
610 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
611 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800612
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800613 std::vector<sp<InputWindowHandle>> inputWindowHandles;
614 inputWindowHandles.push_back(windowTop);
615 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800616
617 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800618 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
619 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800620 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
621
622 // Top window should receive the touch down event. Second window should not receive anything.
623 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
624 windowSecond->assertNoEvents();
625}
626
627TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
628 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800629 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
630 ADISPLAY_ID_DEFAULT);
631 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
632 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800633
Arthur Hung7ab76b12019-01-09 19:17:20 +0800634 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800635 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800636
637 // Expect one focus window exist in display.
638 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800639 std::vector<sp<InputWindowHandle>> inputWindowHandles;
640 inputWindowHandles.push_back(windowTop);
641 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800642
643 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
644 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
645 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
646
647 // Focused window should receive event.
648 windowTop->assertNoEvents();
649 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
650}
651
Arthur Hung7ab76b12019-01-09 19:17:20 +0800652TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
653 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
654 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
655 ADISPLAY_ID_DEFAULT);
656 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
657 ADISPLAY_ID_DEFAULT);
658
659 // Set focused application.
660 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
661
662 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
663 windowTop->setFocus();
664 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800665 std::vector<sp<InputWindowHandle>> inputWindowHandles;
666 inputWindowHandles.push_back(windowTop);
667 inputWindowHandles.push_back(windowSecond);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800668
669 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
670 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
671 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
672
673 // Top focused window should receive event.
674 windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
675 windowSecond->assertNoEvents();
676}
677
Arthur Hung3b413f22018-10-26 18:05:34 +0800678TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
679 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
680
681 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
682 ADISPLAY_ID_DEFAULT);
683 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
684 ADISPLAY_ID_DEFAULT);
685
Arthur Hung832bc4a2019-01-28 11:43:17 +0800686 // Set focused application.
687 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800688
Arthur Hung832bc4a2019-01-28 11:43:17 +0800689 windowTop->setFocus();
690 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800691 std::vector<sp<InputWindowHandle>> inputWindowHandles;
692 inputWindowHandles.push_back(windowTop);
693 inputWindowHandles.push_back(windowSecond);
Arthur Hung3b413f22018-10-26 18:05:34 +0800694 // Release channel for window is no longer valid.
695 windowTop->releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800696 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800697
Arthur Hung832bc4a2019-01-28 11:43:17 +0800698 // Test inject a key down, should dispatch to a valid window.
699 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
700 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800701
702 // Top window is invalid, so it should not receive any input event.
703 windowTop->assertNoEvents();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800704 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800705}
706
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800707/* Test InputDispatcher for MultiDisplay */
708class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
709public:
710 static constexpr int32_t SECOND_DISPLAY_ID = 1;
711 virtual void SetUp() {
712 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800713
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800714 application1 = new FakeApplicationHandle();
715 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
716 ADISPLAY_ID_DEFAULT);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800717 std::vector<sp<InputWindowHandle>> inputWindowHandles;
718 inputWindowHandles.push_back(windowInPrimary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800719 // Set focus window for primary display, but focused display would be second one.
720 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
721 windowInPrimary->setFocus();
722 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800723
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800724 application2 = new FakeApplicationHandle();
725 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
726 SECOND_DISPLAY_ID);
727 // Set focus to second display window.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800728 std::vector<sp<InputWindowHandle>> inputWindowHandles_Second;
729 inputWindowHandles_Second.push_back(windowInSecondary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800730 // Set focus display to second one.
731 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
732 // Set focus window for second display.
733 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
734 windowInSecondary->setFocus();
735 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
736 }
737
738 virtual void TearDown() {
739 InputDispatcherTest::TearDown();
740
741 application1.clear();
742 windowInPrimary.clear();
743 application2.clear();
744 windowInSecondary.clear();
745 }
746
747protected:
748 sp<FakeApplicationHandle> application1;
749 sp<FakeWindowHandle> windowInPrimary;
750 sp<FakeApplicationHandle> application2;
751 sp<FakeWindowHandle> windowInSecondary;
752};
753
754TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
755 // Test touch down on primary display.
756 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
757 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800758 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
759 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
760 windowInSecondary->assertNoEvents();
761
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800762 // Test touch down on second display.
763 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
764 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800765 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
766 windowInPrimary->assertNoEvents();
767 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
768}
769
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800770TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800771 // Test inject a key down with display id specified.
772 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
773 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
774 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
775 windowInSecondary->assertNoEvents();
776
777 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800778 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
779 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
780 windowInPrimary->assertNoEvents();
781 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
782
783 // Remove secondary display.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800784 std::vector<sp<InputWindowHandle>> noWindows;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800785 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800786
787 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800788 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
789 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800790
791 // Test inject a key down, should timeout because of no target window.
792 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
793 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
794 windowInPrimary->assertNoEvents();
795 windowInSecondary->assertNoEvents();
796}
797
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800798class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
799public:
800 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
Michael Wright3dd60e22019-03-27 22:06:44 +0000801 int32_t displayId, bool isGestureMonitor = false)
802 : FakeInputReceiver(dispatcher, name, displayId) {
803 mServerChannel->setToken(new BBinder());
804 mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800805 }
806};
807
808// Test per-display input monitors for motion event.
809TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
810 sp<FakeMonitorReceiver> monitorInPrimary =
811 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
812 sp<FakeMonitorReceiver> monitorInSecondary =
813 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
814
815 // Test touch down on primary display.
816 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
817 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
818 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
819 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
820 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
821 windowInSecondary->assertNoEvents();
822 monitorInSecondary->assertNoEvents();
823
824 // Test touch down on second display.
825 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
826 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
827 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
828 windowInPrimary->assertNoEvents();
829 monitorInPrimary->assertNoEvents();
830 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
831 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
832
833 // Test inject a non-pointer motion event.
834 // If specific a display, it will dispatch to the focused window of particular display,
835 // or it will dispatch to the focused window of focused display.
836 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
837 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
838 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
839 windowInPrimary->assertNoEvents();
840 monitorInPrimary->assertNoEvents();
841 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
842 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
843}
844
845// Test per-display input monitors for key event.
846TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
847 //Input monitor per display.
848 sp<FakeMonitorReceiver> monitorInPrimary =
849 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
850 sp<FakeMonitorReceiver> monitorInSecondary =
851 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
852
853 // Test inject a key down.
854 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
855 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
856 windowInPrimary->assertNoEvents();
857 monitorInPrimary->assertNoEvents();
858 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
859 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
860}
861
Jackal Guof9696682018-10-05 12:23:23 +0800862class InputFilterTest : public InputDispatcherTest {
863protected:
864 static constexpr int32_t SECOND_DISPLAY_ID = 1;
865
866 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
867 NotifyMotionArgs motionArgs;
868
869 motionArgs = generateMotionArgs(
870 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
871 mDispatcher->notifyMotion(&motionArgs);
872 motionArgs = generateMotionArgs(
873 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
874 mDispatcher->notifyMotion(&motionArgs);
875
876 if (expectToBeFiltered) {
877 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&motionArgs);
878 } else {
879 mFakePolicy->assertFilterInputEventWasNotCalled();
880 }
881 }
882
883 void testNotifyKey(bool expectToBeFiltered) {
884 NotifyKeyArgs keyArgs;
885
886 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
887 mDispatcher->notifyKey(&keyArgs);
888 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
889 mDispatcher->notifyKey(&keyArgs);
890
891 if (expectToBeFiltered) {
892 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&keyArgs);
893 } else {
894 mFakePolicy->assertFilterInputEventWasNotCalled();
895 }
896 }
897};
898
899// Test InputFilter for MotionEvent
900TEST_F(InputFilterTest, MotionEvent_InputFilter) {
901 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
902 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
903 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
904
905 // Enable InputFilter
906 mDispatcher->setInputFilterEnabled(true);
907 // Test touch on both primary and second display, and check if both events are filtered.
908 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
909 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
910
911 // Disable InputFilter
912 mDispatcher->setInputFilterEnabled(false);
913 // Test touch on both primary and second display, and check if both events aren't filtered.
914 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
915 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
916}
917
918// Test InputFilter for KeyEvent
919TEST_F(InputFilterTest, KeyEvent_InputFilter) {
920 // Since the InputFilter is disabled by default, check if key event aren't filtered.
921 testNotifyKey(/*expectToBeFiltered*/ false);
922
923 // Enable InputFilter
924 mDispatcher->setInputFilterEnabled(true);
925 // Send a key event, and check if it is filtered.
926 testNotifyKey(/*expectToBeFiltered*/ true);
927
928 // Disable InputFilter
929 mDispatcher->setInputFilterEnabled(false);
930 // Send a key event, and check if it isn't filtered.
931 testNotifyKey(/*expectToBeFiltered*/ false);
932}
933
chaviwfd6d3512019-03-25 13:23:49 -0700934class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
935 virtual void SetUp() {
936 InputDispatcherTest::SetUp();
937
938 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
939 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
940 ADISPLAY_ID_DEFAULT);
941 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
942 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
943 // window.
944 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
945
946 mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
947 ADISPLAY_ID_DEFAULT);
948 mWindowFocused->setFrame(Rect(50, 50, 100, 100));
949 mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
950 mWindowFocusedTouchPoint = 60;
951
952 // Set focused application.
953 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
954 mWindowFocused->setFocus();
955
956 // Expect one focus window exist in display.
957 std::vector<sp<InputWindowHandle>> inputWindowHandles;
958 inputWindowHandles.push_back(mUnfocusedWindow);
959 inputWindowHandles.push_back(mWindowFocused);
960 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
961 }
962
963 virtual void TearDown() {
964 InputDispatcherTest::TearDown();
965
966 mUnfocusedWindow.clear();
967 mWindowFocused.clear();
968 }
969
970protected:
971 sp<FakeWindowHandle> mUnfocusedWindow;
972 sp<FakeWindowHandle> mWindowFocused;
973 int32_t mWindowFocusedTouchPoint;
974};
975
976// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
977// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
978// the onPointerDownOutsideFocus callback.
979TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
980 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
981 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
982 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
983 // Call monitor to wait for the command queue to get flushed.
984 mDispatcher->monitor();
985
986 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
987}
988
989// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
990// DOWN on the window that doesn't have focus. Ensure no window received the
991// onPointerDownOutsideFocus callback.
992TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
993 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
994 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
995 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
996 // Call monitor to wait for the command queue to get flushed.
997 mDispatcher->monitor();
998
999 mFakePolicy->assertOnPointerDownEquals(nullptr);
1000}
1001
1002// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1003// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1004TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1005 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1006 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1007 // Call monitor to wait for the command queue to get flushed.
1008 mDispatcher->monitor();
1009
1010 mFakePolicy->assertOnPointerDownEquals(nullptr);
1011}
1012
1013// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1014// DOWN on the window that already has focus. Ensure no window received the
1015// onPointerDownOutsideFocus callback.
1016TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1017 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
1018 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1019 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
1020 mWindowFocusedTouchPoint))
1021 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1022 // Call monitor to wait for the command queue to get flushed.
1023 mDispatcher->monitor();
1024
1025 mFakePolicy->assertOnPointerDownEquals(nullptr);
1026}
1027
Michael Wrightd02c5b62014-02-10 15:10:22 -08001028} // namespace android