blob: f05f7e5a794a3f40bf0c4974c1d5efbf9ac80196 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080020#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070021
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
23#include <linux/input.h>
chaviwd1c23182019-12-20 18:44:56 -080024#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025
Garfield Tane84e6f92019-08-29 17:28:41 -070026namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080027
28// An arbitrary time value.
29static const nsecs_t ARBITRARY_TIME = 1234;
30
31// An arbitrary device id.
32static const int32_t DEVICE_ID = 1;
33
Jeff Brownf086ddb2014-02-11 14:28:48 -080034// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080035static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080036
Michael Wrightd02c5b62014-02-10 15:10:22 -080037// An arbitrary injector pid / uid pair that has permission to inject events.
38static const int32_t INJECTOR_PID = 999;
39static const int32_t INJECTOR_UID = 1001;
40
chaviwd1c23182019-12-20 18:44:56 -080041struct PointF {
42 float x;
43 float y;
44};
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Gang Wang342c9272020-01-13 13:15:04 -050046/**
47 * Return a DOWN key event with KEYCODE_A.
48 */
49static KeyEvent getTestKeyEvent() {
50 KeyEvent event;
51
Garfield Tanfbe732e2020-01-24 11:26:14 -080052 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
53 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
54 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050055 return event;
56}
57
Michael Wrightd02c5b62014-02-10 15:10:22 -080058// --- FakeInputDispatcherPolicy ---
59
60class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
61 InputDispatcherConfiguration mConfig;
62
63protected:
64 virtual ~FakeInputDispatcherPolicy() {
65 }
66
67public:
68 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080069 }
70
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080071 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080072 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
73 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080074 }
75
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080076 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080077 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
78 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080081 void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
Michael Wrightd02c5b62014-02-10 15:10:22 -080082
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080083 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
84 ASSERT_TRUE(mConfigurationChangedTime)
85 << "Timed out waiting for configuration changed call";
86 ASSERT_EQ(*mConfigurationChangedTime, when);
87 mConfigurationChangedTime = std::nullopt;
88 }
89
90 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
91 ASSERT_TRUE(mLastNotifySwitch);
92 // We do not check sequenceNum because it is not exposed to the policy
93 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
94 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
95 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
96 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
97 mLastNotifySwitch = std::nullopt;
98 }
99
chaviwfd6d3512019-03-25 13:23:49 -0700100 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800101 ASSERT_EQ(touchedToken, mOnPointerDownToken);
102 mOnPointerDownToken.clear();
103 }
104
105 void assertOnPointerDownWasNotCalled() {
106 ASSERT_TRUE(mOnPointerDownToken == nullptr)
107 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700108 }
109
Michael Wrightd02c5b62014-02-10 15:10:22 -0800110private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800111 std::unique_ptr<InputEvent> mFilteredEvent;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800112 std::optional<nsecs_t> mConfigurationChangedTime;
chaviwfd6d3512019-03-25 13:23:49 -0700113 sp<IBinder> mOnPointerDownToken;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800114 std::optional<NotifySwitchArgs> mLastNotifySwitch;
Jackal Guof9696682018-10-05 12:23:23 +0800115
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800116 virtual void notifyConfigurationChanged(nsecs_t when) override {
117 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800118 }
119
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100120 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700121 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800122 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800123 return 0;
124 }
125
Robert Carr803535b2018-08-02 16:38:15 -0700126 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800127 }
128
chaviw0c06c6e2019-01-09 13:27:07 -0800129 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700130 }
131
Michael Wrightd02c5b62014-02-10 15:10:22 -0800132 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
133 *outConfig = mConfig;
134 }
135
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800136 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800137 switch (inputEvent->getType()) {
138 case AINPUT_EVENT_TYPE_KEY: {
139 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800140 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800141 break;
142 }
143
144 case AINPUT_EVENT_TYPE_MOTION: {
145 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800146 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800147 break;
148 }
149 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800150 return true;
151 }
152
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 }
155
Charles Chen3611f1f2019-01-29 17:26:18 +0800156 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157 }
158
Robert Carr803535b2018-08-02 16:38:15 -0700159 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100160 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161 return 0;
162 }
163
Robert Carr803535b2018-08-02 16:38:15 -0700164 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100165 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166 return false;
167 }
168
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800169 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
170 uint32_t policyFlags) override {
171 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
172 * essentially a passthrough for notifySwitch.
173 */
174 mLastNotifySwitch =
175 NotifySwitchArgs(1 /*sequenceNum*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176 }
177
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100178 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800179 }
180
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100181 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800182 return false;
183 }
Jackal Guof9696682018-10-05 12:23:23 +0800184
chaviwfd6d3512019-03-25 13:23:49 -0700185 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
186 mOnPointerDownToken = newToken;
187 }
188
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800189 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
190 int32_t displayId) {
191 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
192 ASSERT_EQ(mFilteredEvent->getType(), type);
193
194 if (type == AINPUT_EVENT_TYPE_KEY) {
195 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
196 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
197 EXPECT_EQ(keyEvent.getAction(), action);
198 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
199 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
200 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
201 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
202 EXPECT_EQ(motionEvent.getAction(), action);
203 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
204 } else {
205 FAIL() << "Unknown type: " << type;
206 }
207
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800208 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800209 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210};
211
Gang Wang342c9272020-01-13 13:15:04 -0500212// --- HmacKeyManagerTest ---
213
214class HmacKeyManagerTest : public testing::Test {
215protected:
216 HmacKeyManager mHmacKeyManager;
217};
218
219/**
220 * Ensure that separate calls to sign the same data are generating the same key.
221 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
222 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
223 * tests.
224 */
225TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
226 KeyEvent event = getTestKeyEvent();
227 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
228
229 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
230 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
231 ASSERT_EQ(hmac1, hmac2);
232}
233
234/**
235 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
236 */
237TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
238 KeyEvent event = getTestKeyEvent();
239 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
240 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
241
242 verifiedEvent.deviceId += 1;
243 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
244
245 verifiedEvent.source += 1;
246 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
247
248 verifiedEvent.eventTimeNanos += 1;
249 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
250
251 verifiedEvent.displayId += 1;
252 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
253
254 verifiedEvent.action += 1;
255 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
256
257 verifiedEvent.downTimeNanos += 1;
258 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
259
260 verifiedEvent.flags += 1;
261 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
262
263 verifiedEvent.keyCode += 1;
264 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
265
266 verifiedEvent.scanCode += 1;
267 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
268
269 verifiedEvent.metaState += 1;
270 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
271
272 verifiedEvent.repeatCount += 1;
273 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
274}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800275
276// --- InputDispatcherTest ---
277
278class InputDispatcherTest : public testing::Test {
279protected:
280 sp<FakeInputDispatcherPolicy> mFakePolicy;
281 sp<InputDispatcher> mDispatcher;
282
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700283 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800284 mFakePolicy = new FakeInputDispatcherPolicy();
285 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800286 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
287 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700288 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800289 }
290
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700291 virtual void TearDown() override {
292 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800293 mFakePolicy.clear();
294 mDispatcher.clear();
295 }
296};
297
298
299TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
300 KeyEvent event;
301
302 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800303 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
304 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600305 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
306 ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800307 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800308 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800309 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
310 << "Should reject key events with undefined action.";
311
312 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800313 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
314 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600315 ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800316 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800317 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800318 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
319 << "Should reject key events with ACTION_MULTIPLE.";
320}
321
322TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
323 MotionEvent event;
324 PointerProperties pointerProperties[MAX_POINTERS + 1];
325 PointerCoords pointerCoords[MAX_POINTERS + 1];
326 for (int i = 0; i <= MAX_POINTERS; i++) {
327 pointerProperties[i].clear();
328 pointerProperties[i].id = i;
329 pointerCoords[i].clear();
330 }
331
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800332 // Some constants commonly used below
333 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
334 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
335 constexpr int32_t metaState = AMETA_NONE;
336 constexpr MotionClassification classification = MotionClassification::NONE;
337
Michael Wrightd02c5b62014-02-10 15:10:22 -0800338 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800339 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600340 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
341 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
342 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700343 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800344 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800345 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
347 << "Should reject motion events with undefined action.";
348
349 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800350 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700351 AMOTION_EVENT_ACTION_POINTER_DOWN |
352 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600353 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
354 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
355 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700356 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800357 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800358 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800359 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
360 << "Should reject motion events with pointer down index too large.";
361
Garfield Tanfbe732e2020-01-24 11:26:14 -0800362 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700363 AMOTION_EVENT_ACTION_POINTER_DOWN |
364 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600365 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
366 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
367 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700368 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800369 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800370 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800371 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
372 << "Should reject motion events with pointer down index too small.";
373
374 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800375 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700376 AMOTION_EVENT_ACTION_POINTER_UP |
377 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600378 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
379 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
380 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700381 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800382 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800383 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800384 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
385 << "Should reject motion events with pointer up index too large.";
386
Garfield Tanfbe732e2020-01-24 11:26:14 -0800387 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700388 AMOTION_EVENT_ACTION_POINTER_UP |
389 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600390 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
391 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
392 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700393 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800394 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800395 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
397 << "Should reject motion events with pointer up index too small.";
398
399 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800400 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
401 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
402 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
403 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
404 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700405 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800406 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800407 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800408 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
409 << "Should reject motion events with 0 pointers.";
410
Garfield Tanfbe732e2020-01-24 11:26:14 -0800411 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
412 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
413 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
414 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
415 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700416 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800417 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800418 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800419 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
420 << "Should reject motion events with more than MAX_POINTERS pointers.";
421
422 // Rejects motion events with invalid pointer ids.
423 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800424 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
425 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
426 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
427 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
428 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700429 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800430 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800431 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800432 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
433 << "Should reject motion events with pointer ids less than 0.";
434
435 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800436 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
437 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
438 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
439 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
440 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700441 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800442 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800443 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800444 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
445 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
446
447 // Rejects motion events with duplicate pointer ids.
448 pointerProperties[0].id = 1;
449 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800450 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
451 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
452 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
453 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
454 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700455 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800456 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800457 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800458 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
459 << "Should reject motion events with duplicate pointer ids.";
460}
461
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800462/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
463
464TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
465 constexpr nsecs_t eventTime = 20;
466 NotifyConfigurationChangedArgs args(10 /*sequenceNum*/, eventTime);
467 mDispatcher->notifyConfigurationChanged(&args);
468 ASSERT_TRUE(mDispatcher->waitForIdle());
469
470 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
471}
472
473TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
474 NotifySwitchArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, 0 /*policyFlags*/,
475 1 /*switchValues*/, 2 /*switchMask*/);
476 mDispatcher->notifySwitch(&args);
477
478 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
479 args.policyFlags |= POLICY_FLAG_TRUSTED;
480 mFakePolicy->assertNotifySwitchWasCalled(args);
481}
482
Arthur Hungb92218b2018-08-14 12:00:21 +0800483// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800484static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
485static constexpr int32_t DISPATCHING_TIMEOUT = 100;
Arthur Hungb92218b2018-08-14 12:00:21 +0800486
487class FakeApplicationHandle : public InputApplicationHandle {
488public:
489 FakeApplicationHandle() {}
490 virtual ~FakeApplicationHandle() {}
491
492 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800493 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800494 return true;
495 }
496};
497
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800498class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800499public:
chaviwd1c23182019-12-20 18:44:56 -0800500 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
501 : mName(name) {
502 mConsumer = std::make_unique<InputConsumer>(clientChannel);
503 }
504
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800505 InputEvent* consume() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800506 uint32_t consumeSeq;
507 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800508
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800509 std::chrono::time_point start = std::chrono::steady_clock::now();
510 status_t status = WOULD_BLOCK;
511 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800512 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800513 &event);
514 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
515 if (elapsed > 100ms) {
516 break;
517 }
518 }
519
520 if (status == WOULD_BLOCK) {
521 // Just means there's no event available.
522 return nullptr;
523 }
524
525 if (status != OK) {
526 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
527 return nullptr;
528 }
529 if (event == nullptr) {
530 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
531 return nullptr;
532 }
533
chaviwd1c23182019-12-20 18:44:56 -0800534 status = mConsumer->sendFinishedSignal(consumeSeq, true);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800535 if (status != OK) {
536 ADD_FAILURE() << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
537 }
538 return event;
539 }
540
541 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
542 int32_t expectedFlags) {
543 InputEvent* event = consume();
544
545 ASSERT_NE(nullptr, event) << mName.c_str()
546 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800547 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800548 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
549 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800550
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800551 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800552
Tiger Huang8664f8c2018-10-11 19:14:35 +0800553 switch (expectedEventType) {
554 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800555 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
556 EXPECT_EQ(expectedAction, keyEvent.getAction());
557 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800558 break;
559 }
560 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800561 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
562 EXPECT_EQ(expectedAction, motionEvent.getAction());
563 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800564 break;
565 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100566 case AINPUT_EVENT_TYPE_FOCUS: {
567 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
568 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800569 default: {
570 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
571 }
572 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800573 }
574
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100575 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
576 InputEvent* event = consume();
577 ASSERT_NE(nullptr, event) << mName.c_str()
578 << ": consumer should have returned non-NULL event.";
579 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
580 << "Got " << inputEventTypeToString(event->getType())
581 << " event instead of FOCUS event";
582
583 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
584 << mName.c_str() << ": event displayId should always be NONE.";
585
586 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
587 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
588 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
589 }
590
chaviwd1c23182019-12-20 18:44:56 -0800591 void assertNoEvents() {
592 InputEvent* event = consume();
593 ASSERT_EQ(nullptr, event)
594 << mName.c_str()
595 << ": should not have received any events, so consume() should return NULL";
596 }
597
598 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
599
600protected:
601 std::unique_ptr<InputConsumer> mConsumer;
602 PreallocatedInputEventFactory mEventFactory;
603
604 std::string mName;
605};
606
607class FakeWindowHandle : public InputWindowHandle {
608public:
609 static const int32_t WIDTH = 600;
610 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800611
612 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
613 const sp<InputDispatcher>& dispatcher, const std::string name,
614 int32_t displayId, sp<IBinder> token = nullptr)
615 : mName(name) {
616 if (token == nullptr) {
617 sp<InputChannel> serverChannel, clientChannel;
618 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
619 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
620 dispatcher->registerInputChannel(serverChannel);
621 token = serverChannel->getConnectionToken();
622 }
623
624 inputApplicationHandle->updateInfo();
625 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
626
627 mInfo.token = token;
chaviwaf87b3e2019-10-01 16:59:28 -0700628 mInfo.id = 0;
chaviwd1c23182019-12-20 18:44:56 -0800629 mInfo.name = name;
630 mInfo.layoutParamsFlags = 0;
631 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
632 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
633 mInfo.frameLeft = 0;
634 mInfo.frameTop = 0;
635 mInfo.frameRight = WIDTH;
636 mInfo.frameBottom = HEIGHT;
637 mInfo.globalScaleFactor = 1.0;
638 mInfo.touchableRegion.clear();
639 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
640 mInfo.visible = true;
641 mInfo.canReceiveKeys = true;
642 mInfo.hasFocus = false;
643 mInfo.hasWallpaper = false;
644 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800645 mInfo.ownerPid = INJECTOR_PID;
646 mInfo.ownerUid = INJECTOR_UID;
647 mInfo.inputFeatures = 0;
648 mInfo.displayId = displayId;
649 }
650
651 virtual bool updateInfo() { return true; }
652
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100653 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800654
655 void setFrame(const Rect& frame) {
656 mInfo.frameLeft = frame.left;
657 mInfo.frameTop = frame.top;
658 mInfo.frameRight = frame.right;
659 mInfo.frameBottom = frame.bottom;
660 mInfo.touchableRegion.clear();
661 mInfo.addTouchableRegion(frame);
662 }
663
664 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
665
chaviwaf87b3e2019-10-01 16:59:28 -0700666 void setId(int32_t id) { mInfo.id = id; }
667
668 void setWindowScale(float xScale, float yScale) {
669 mInfo.windowXScale = xScale;
670 mInfo.windowYScale = yScale;
671 }
672
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800673 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
674 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
675 expectedFlags);
676 }
677
Svet Ganov5d3bc372020-01-26 23:11:07 -0800678 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
679 int32_t expectedFlags = 0) {
680 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
681 expectedFlags);
682 }
683
684 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
685 int32_t expectedFlags = 0) {
686 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
687 expectedFlags);
688 }
689
690 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
691 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800692 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
693 expectedFlags);
694 }
695
Svet Ganov5d3bc372020-01-26 23:11:07 -0800696 void consumeMotionPointerDown(int32_t pointerIdx,
697 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
698 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
699 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
700 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
701 }
702
703 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
704 int32_t expectedFlags = 0) {
705 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
706 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
707 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
708 }
709
710 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
711 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000712 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
713 expectedFlags);
714 }
715
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100716 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
717 ASSERT_NE(mInputReceiver, nullptr)
718 << "Cannot consume events from a window with no receiver";
719 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
720 }
721
chaviwd1c23182019-12-20 18:44:56 -0800722 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
723 int32_t expectedFlags) {
724 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
725 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
726 expectedFlags);
727 }
728
chaviwaf87b3e2019-10-01 16:59:28 -0700729 InputEvent* consume() {
730 if (mInputReceiver == nullptr) {
731 return nullptr;
732 }
733 return mInputReceiver->consume();
734 }
735
Arthur Hungb92218b2018-08-14 12:00:21 +0800736 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800737 ASSERT_NE(mInputReceiver, nullptr)
738 << "Call 'assertNoEvents' on a window with an InputReceiver";
739 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800740 }
741
chaviwaf87b3e2019-10-01 16:59:28 -0700742 sp<IBinder> getToken() { return mInfo.token; }
743
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100744 const std::string& getName() { return mName; }
745
chaviwd1c23182019-12-20 18:44:56 -0800746private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100747 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800748 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800749};
750
Tiger Huang721e26f2018-07-24 22:26:19 +0800751static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
752 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800753 KeyEvent event;
754 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
755
756 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800757 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
758 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
759 AMETA_NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600760 /* repeatCount */ 0, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800761
762 // Inject event until dispatch out.
763 return dispatcher->injectInputEvent(
764 &event,
765 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
766 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
767}
768
Garfield Tan00f511d2019-06-12 16:55:40 -0700769static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
770 int32_t source, int32_t displayId, int32_t x, int32_t y,
771 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
772 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800773 MotionEvent event;
774 PointerProperties pointerProperties[1];
775 PointerCoords pointerCoords[1];
776
777 pointerProperties[0].clear();
778 pointerProperties[0].id = 0;
779 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
780
781 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700782 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
783 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800784
785 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
786 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800787 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
788 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600789 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700790 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600791 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
792 /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition,
793 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800795
796 // Inject event until dispatch out.
797 return dispatcher->injectInputEvent(
798 &event,
799 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
800 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
801}
802
Garfield Tan00f511d2019-06-12 16:55:40 -0700803static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
804 int32_t displayId, int32_t x = 100, int32_t y = 200) {
805 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
806}
807
Michael Wright3a240c42019-12-10 20:53:41 +0000808static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
809 int32_t displayId, int32_t x = 100, int32_t y = 200) {
810 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
811}
812
Jackal Guof9696682018-10-05 12:23:23 +0800813static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
814 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
815 // Define a valid key event.
816 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
817 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
818 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
819
820 return args;
821}
822
chaviwd1c23182019-12-20 18:44:56 -0800823static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
824 const std::vector<PointF>& points) {
825 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700826 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
827 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
828 }
829
chaviwd1c23182019-12-20 18:44:56 -0800830 PointerProperties pointerProperties[pointerCount];
831 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800832
chaviwd1c23182019-12-20 18:44:56 -0800833 for (size_t i = 0; i < pointerCount; i++) {
834 pointerProperties[i].clear();
835 pointerProperties[i].id = i;
836 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800837
chaviwd1c23182019-12-20 18:44:56 -0800838 pointerCoords[i].clear();
839 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
840 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
841 }
Jackal Guof9696682018-10-05 12:23:23 +0800842
843 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
844 // Define a valid motion event.
845 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700846 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
847 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800848 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
849 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700850 AMOTION_EVENT_INVALID_CURSOR_POSITION,
851 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800852
853 return args;
854}
855
chaviwd1c23182019-12-20 18:44:56 -0800856static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
857 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
858}
859
Arthur Hungb92218b2018-08-14 12:00:21 +0800860TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
861 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800862 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
863 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800864
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800865 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800866 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
867 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800868 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
869
870 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800871 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800872}
873
874// The foreground window should receive the first touch down event.
875TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
876 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800877 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
878 ADISPLAY_ID_DEFAULT);
879 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
880 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800881
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800882 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800883 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
884 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800885 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
886
887 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800888 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800889 windowSecond->assertNoEvents();
890}
891
892TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
893 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800894 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
895 ADISPLAY_ID_DEFAULT);
896 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
897 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800898
Arthur Hung7ab76b12019-01-09 19:17:20 +0800899 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800900 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800901
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100902 // Display should have only one focused window
903 windowSecond->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800904 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100905
906 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +0800907 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
908 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
909
910 // Focused window should receive event.
911 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800912 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800913}
914
Arthur Hung7ab76b12019-01-09 19:17:20 +0800915TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
916 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
917 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
918 ADISPLAY_ID_DEFAULT);
919 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
920 ADISPLAY_ID_DEFAULT);
921
922 // Set focused application.
923 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
924
925 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100926 windowTop->setFocus(true);
927 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800928
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800929 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100930 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800931 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
932 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
933
934 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800935 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800936 windowSecond->assertNoEvents();
937}
938
Arthur Hung3b413f22018-10-26 18:05:34 +0800939TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
940 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
941
942 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
943 ADISPLAY_ID_DEFAULT);
944 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
945 ADISPLAY_ID_DEFAULT);
946
Arthur Hung832bc4a2019-01-28 11:43:17 +0800947 // Set focused application.
948 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800949
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100950 windowTop->setFocus(true);
951 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800952 // Release channel for window is no longer valid.
953 windowTop->releaseChannel();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800954 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100955 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800956
Arthur Hung832bc4a2019-01-28 11:43:17 +0800957 // Test inject a key down, should dispatch to a valid window.
958 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
959 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800960
961 // Top window is invalid, so it should not receive any input event.
962 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800963 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800964}
965
Garfield Tan00f511d2019-06-12 16:55:40 -0700966TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
967 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
968
969 sp<FakeWindowHandle> windowLeft =
970 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
971 windowLeft->setFrame(Rect(0, 0, 600, 800));
972 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
973 sp<FakeWindowHandle> windowRight =
974 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
975 windowRight->setFrame(Rect(600, 0, 1200, 800));
976 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
977
978 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
979
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800980 mDispatcher->setInputWindows({windowLeft, windowRight}, ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700981
982 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
983 // left window. This event should be dispatched to the left window.
984 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
985 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
986 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800987 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700988 windowRight->assertNoEvents();
989}
990
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800991TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
992 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
993 sp<FakeWindowHandle> window =
994 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100995 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800996
997 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100998 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800999
1000 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1001 mDispatcher->notifyKey(&keyArgs);
1002
1003 // Window should receive key down event.
1004 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1005
1006 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1007 // on the app side.
1008 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
1009 mDispatcher->notifyDeviceReset(&args);
1010 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1011 AKEY_EVENT_FLAG_CANCELED);
1012}
1013
1014TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1015 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1016 sp<FakeWindowHandle> window =
1017 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1018
1019 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1020
1021 NotifyMotionArgs motionArgs =
1022 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1023 ADISPLAY_ID_DEFAULT);
1024 mDispatcher->notifyMotion(&motionArgs);
1025
1026 // Window should receive motion down event.
1027 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1028
1029 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1030 // on the app side.
1031 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
1032 mDispatcher->notifyDeviceReset(&args);
1033 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1034 0 /*expectedFlags*/);
1035}
1036
Svet Ganov5d3bc372020-01-26 23:11:07 -08001037TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1038 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1039
1040 // Create a couple of windows
1041 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1042 "First Window", ADISPLAY_ID_DEFAULT);
1043 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1044 "Second Window", ADISPLAY_ID_DEFAULT);
1045
1046 // Add the windows to the dispatcher
1047 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1048
1049 // Send down to the first window
1050 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1051 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1052 mDispatcher->notifyMotion(&downMotionArgs);
1053 // Only the first window should get the down event
1054 firstWindow->consumeMotionDown();
1055 secondWindow->assertNoEvents();
1056
1057 // Transfer touch focus to the second window
1058 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1059 // The first window gets cancel and the second gets down
1060 firstWindow->consumeMotionCancel();
1061 secondWindow->consumeMotionDown();
1062
1063 // Send up event to the second window
1064 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1065 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1066 mDispatcher->notifyMotion(&upMotionArgs);
1067 // The first window gets no events and the second gets up
1068 firstWindow->assertNoEvents();
1069 secondWindow->consumeMotionUp();
1070}
1071
1072TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1073 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1074
1075 PointF touchPoint = {10, 10};
1076
1077 // Create a couple of windows
1078 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1079 "First Window", ADISPLAY_ID_DEFAULT);
1080 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1081 "Second Window", ADISPLAY_ID_DEFAULT);
1082
1083 // Add the windows to the dispatcher
1084 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1085
1086 // Send down to the first window
1087 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1088 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1089 mDispatcher->notifyMotion(&downMotionArgs);
1090 // Only the first window should get the down event
1091 firstWindow->consumeMotionDown();
1092 secondWindow->assertNoEvents();
1093
1094 // Send pointer down to the first window
1095 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1096 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1097 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1098 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1099 // Only the first window should get the pointer down event
1100 firstWindow->consumeMotionPointerDown(1);
1101 secondWindow->assertNoEvents();
1102
1103 // Transfer touch focus to the second window
1104 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1105 // The first window gets cancel and the second gets down and pointer down
1106 firstWindow->consumeMotionCancel();
1107 secondWindow->consumeMotionDown();
1108 secondWindow->consumeMotionPointerDown(1);
1109
1110 // Send pointer up to the second window
1111 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1112 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1114 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1115 // The first window gets nothing and the second gets pointer up
1116 firstWindow->assertNoEvents();
1117 secondWindow->consumeMotionPointerUp(1);
1118
1119 // Send up event to the second window
1120 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1121 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1122 mDispatcher->notifyMotion(&upMotionArgs);
1123 // The first window gets nothing and the second gets up
1124 firstWindow->assertNoEvents();
1125 secondWindow->consumeMotionUp();
1126}
1127
1128TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1129 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1130
1131 // Create a non touch modal window that supports split touch
1132 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1133 "First Window", ADISPLAY_ID_DEFAULT);
1134 firstWindow->setFrame(Rect(0, 0, 600, 400));
1135 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1136 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1137
1138 // Create a non touch modal window that supports split touch
1139 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1140 "Second Window", ADISPLAY_ID_DEFAULT);
1141 secondWindow->setFrame(Rect(0, 400, 600, 800));
1142 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1143 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1144
1145 // Add the windows to the dispatcher
1146 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1147
1148 PointF pointInFirst = {300, 200};
1149 PointF pointInSecond = {300, 600};
1150
1151 // Send down to the first window
1152 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1153 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1154 mDispatcher->notifyMotion(&firstDownMotionArgs);
1155 // Only the first window should get the down event
1156 firstWindow->consumeMotionDown();
1157 secondWindow->assertNoEvents();
1158
1159 // Send down to the second window
1160 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1161 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1162 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1163 mDispatcher->notifyMotion(&secondDownMotionArgs);
1164 // The first window gets a move and the second a down
1165 firstWindow->consumeMotionMove();
1166 secondWindow->consumeMotionDown();
1167
1168 // Transfer touch focus to the second window
1169 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1170 // The first window gets cancel and the new gets pointer down (it already saw down)
1171 firstWindow->consumeMotionCancel();
1172 secondWindow->consumeMotionPointerDown(1);
1173
1174 // Send pointer up to the second window
1175 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1176 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1177 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1178 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1179 // The first window gets nothing and the second gets pointer up
1180 firstWindow->assertNoEvents();
1181 secondWindow->consumeMotionPointerUp(1);
1182
1183 // Send up event to the second window
1184 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1185 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1186 mDispatcher->notifyMotion(&upMotionArgs);
1187 // The first window gets nothing and the second gets up
1188 firstWindow->assertNoEvents();
1189 secondWindow->consumeMotionUp();
1190}
1191
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001192TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1193 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1194 sp<FakeWindowHandle> window =
1195 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1196
1197 window->setFocus(true);
1198 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1199
1200 window->consumeFocusEvent(true);
1201
1202 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1203 mDispatcher->notifyKey(&keyArgs);
1204
1205 // Window should receive key down event.
1206 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1207}
1208
1209TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1210 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1211 sp<FakeWindowHandle> window =
1212 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1213
1214 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1215
1216 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1217 mDispatcher->notifyKey(&keyArgs);
1218 mDispatcher->waitForIdle();
1219
1220 window->assertNoEvents();
1221}
1222
1223// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1224TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1225 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1226 sp<FakeWindowHandle> window =
1227 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1228
1229 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1230
1231 // Send key
1232 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1233 mDispatcher->notifyKey(&keyArgs);
1234 // Send motion
1235 NotifyMotionArgs motionArgs =
1236 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1237 ADISPLAY_ID_DEFAULT);
1238 mDispatcher->notifyMotion(&motionArgs);
1239
1240 // Window should receive only the motion event
1241 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1242 window->assertNoEvents(); // Key event or focus event will not be received
1243}
1244
chaviwd1c23182019-12-20 18:44:56 -08001245class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001246public:
1247 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001248 int32_t displayId, bool isGestureMonitor = false) {
1249 sp<InputChannel> serverChannel, clientChannel;
1250 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1251 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1252 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001253 }
1254
chaviwd1c23182019-12-20 18:44:56 -08001255 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1256
1257 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1258 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1259 expectedDisplayId, expectedFlags);
1260 }
1261
1262 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1263 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1264 expectedDisplayId, expectedFlags);
1265 }
1266
1267 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1268 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1269 expectedDisplayId, expectedFlags);
1270 }
1271
1272 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1273
1274private:
1275 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001276};
1277
1278// Tests for gesture monitors
1279TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1280 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1281 sp<FakeWindowHandle> window =
1282 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1283 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1284
chaviwd1c23182019-12-20 18:44:56 -08001285 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1286 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001287
1288 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1289 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1290 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1291 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001292 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001293}
1294
1295TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1296 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1297 sp<FakeWindowHandle> window =
1298 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1299
1300 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001301 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001302
1303 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001304 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001305
chaviwd1c23182019-12-20 18:44:56 -08001306 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1307 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001308
1309 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1310 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1311 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001312 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001313}
1314
1315TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1316 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1317 sp<FakeWindowHandle> window =
1318 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1319 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1320
chaviwd1c23182019-12-20 18:44:56 -08001321 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1322 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001323
1324 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1325 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1326 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1327 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001328 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001329
1330 window->releaseChannel();
1331
chaviwd1c23182019-12-20 18:44:56 -08001332 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001333
1334 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1335 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1336 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001337 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001338}
1339
chaviw81e2bb92019-12-18 15:03:51 -08001340TEST_F(InputDispatcherTest, TestMoveEvent) {
1341 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1342 sp<FakeWindowHandle> window =
1343 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1344
1345 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1346
1347 NotifyMotionArgs motionArgs =
1348 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1349 ADISPLAY_ID_DEFAULT);
1350
1351 mDispatcher->notifyMotion(&motionArgs);
1352 // Window should receive motion down event.
1353 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1354
1355 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
1356 motionArgs.sequenceNum += 1;
1357 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1358 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1359 motionArgs.pointerCoords[0].getX() - 10);
1360
1361 mDispatcher->notifyMotion(&motionArgs);
1362 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1363 0 /*expectedFlags*/);
1364}
1365
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001366/**
1367 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1368 * the device default right away. In the test scenario, we check both the default value,
1369 * and the action of enabling / disabling.
1370 */
1371TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1372 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1373 sp<FakeWindowHandle> window =
1374 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1375
1376 // Set focused application.
1377 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1378 window->setFocus(true);
1379
1380 SCOPED_TRACE("Check default value of touch mode");
1381 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1382 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1383
1384 SCOPED_TRACE("Remove the window to trigger focus loss");
1385 window->setFocus(false);
1386 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1387 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1388
1389 SCOPED_TRACE("Disable touch mode");
1390 mDispatcher->setInTouchMode(false);
1391 window->setFocus(true);
1392 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1393 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1394
1395 SCOPED_TRACE("Remove the window to trigger focus loss");
1396 window->setFocus(false);
1397 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1398 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1399
1400 SCOPED_TRACE("Enable touch mode again");
1401 mDispatcher->setInTouchMode(true);
1402 window->setFocus(true);
1403 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1404 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1405
1406 window->assertNoEvents();
1407}
1408
Gang Wange9087892020-01-07 12:17:14 -05001409TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1410 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1411 sp<FakeWindowHandle> window =
1412 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1413
1414 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1415 window->setFocus(true);
1416
1417 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1418 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1419
1420 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1421 mDispatcher->notifyKey(&keyArgs);
1422
1423 InputEvent* event = window->consume();
1424 ASSERT_NE(event, nullptr);
1425
1426 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1427 ASSERT_NE(verified, nullptr);
1428 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1429
1430 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1431 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1432 ASSERT_EQ(keyArgs.source, verified->source);
1433 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1434
1435 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1436
1437 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1438 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
1439 ASSERT_EQ(keyArgs.eventTime, verifiedKey.eventTimeNanos);
1440 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1441 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1442 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1443 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1444 ASSERT_EQ(0, verifiedKey.repeatCount);
1445}
1446
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001447/* Test InputDispatcher for MultiDisplay */
1448class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1449public:
1450 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001451 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001452 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001453
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001454 application1 = new FakeApplicationHandle();
1455 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1456 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001457
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001458 // Set focus window for primary display, but focused display would be second one.
1459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001460 windowInPrimary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001461 mDispatcher->setInputWindows({windowInPrimary}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001462 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001463
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001464 application2 = new FakeApplicationHandle();
1465 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1466 SECOND_DISPLAY_ID);
1467 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001468 // Set focus display to second one.
1469 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1470 // Set focus window for second display.
1471 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001472 windowInSecondary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001473 mDispatcher->setInputWindows({windowInSecondary}, SECOND_DISPLAY_ID);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001474 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001475 }
1476
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001477 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001478 InputDispatcherTest::TearDown();
1479
1480 application1.clear();
1481 windowInPrimary.clear();
1482 application2.clear();
1483 windowInSecondary.clear();
1484 }
1485
1486protected:
1487 sp<FakeApplicationHandle> application1;
1488 sp<FakeWindowHandle> windowInPrimary;
1489 sp<FakeApplicationHandle> application2;
1490 sp<FakeWindowHandle> windowInSecondary;
1491};
1492
1493TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1494 // Test touch down on primary display.
1495 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1496 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001497 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001498 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001499 windowInSecondary->assertNoEvents();
1500
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001501 // Test touch down on second display.
1502 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1503 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001504 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1505 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001506 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001507}
1508
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001509TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001510 // Test inject a key down with display id specified.
1511 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1512 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001513 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001514 windowInSecondary->assertNoEvents();
1515
1516 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001517 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1518 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1519 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001520 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001521
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001522 // Remove all windows in secondary display.
1523 mDispatcher->setInputWindows({}, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001524
1525 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001526 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1527 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001528
1529 // Test inject a key down, should timeout because of no target window.
1530 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1531 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1532 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001533 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001534 windowInSecondary->assertNoEvents();
1535}
1536
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001537// Test per-display input monitors for motion event.
1538TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001539 FakeMonitorReceiver monitorInPrimary =
1540 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1541 FakeMonitorReceiver monitorInSecondary =
1542 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001543
1544 // Test touch down on primary display.
1545 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1547 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001548 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001549 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001550 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001551 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001552
1553 // Test touch down on second display.
1554 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1555 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1556 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1557 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001558 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001559 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001560 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001561
1562 // Test inject a non-pointer motion event.
1563 // If specific a display, it will dispatch to the focused window of particular display,
1564 // or it will dispatch to the focused window of focused display.
1565 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1566 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1567 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1568 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001569 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001570 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001571 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001572}
1573
1574// Test per-display input monitors for key event.
1575TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1576 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001577 FakeMonitorReceiver monitorInPrimary =
1578 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1579 FakeMonitorReceiver monitorInSecondary =
1580 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001581
1582 // Test inject a key down.
1583 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1584 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1585 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001586 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001587 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001588 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001589}
1590
Jackal Guof9696682018-10-05 12:23:23 +08001591class InputFilterTest : public InputDispatcherTest {
1592protected:
1593 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1594
1595 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1596 NotifyMotionArgs motionArgs;
1597
1598 motionArgs = generateMotionArgs(
1599 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1600 mDispatcher->notifyMotion(&motionArgs);
1601 motionArgs = generateMotionArgs(
1602 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1603 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001604 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001605 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001606 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001607 } else {
1608 mFakePolicy->assertFilterInputEventWasNotCalled();
1609 }
1610 }
1611
1612 void testNotifyKey(bool expectToBeFiltered) {
1613 NotifyKeyArgs keyArgs;
1614
1615 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1616 mDispatcher->notifyKey(&keyArgs);
1617 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1618 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001619 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001620
1621 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001622 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001623 } else {
1624 mFakePolicy->assertFilterInputEventWasNotCalled();
1625 }
1626 }
1627};
1628
1629// Test InputFilter for MotionEvent
1630TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1631 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1632 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1633 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1634
1635 // Enable InputFilter
1636 mDispatcher->setInputFilterEnabled(true);
1637 // Test touch on both primary and second display, and check if both events are filtered.
1638 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1639 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1640
1641 // Disable InputFilter
1642 mDispatcher->setInputFilterEnabled(false);
1643 // Test touch on both primary and second display, and check if both events aren't filtered.
1644 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1645 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1646}
1647
1648// Test InputFilter for KeyEvent
1649TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1650 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1651 testNotifyKey(/*expectToBeFiltered*/ false);
1652
1653 // Enable InputFilter
1654 mDispatcher->setInputFilterEnabled(true);
1655 // Send a key event, and check if it is filtered.
1656 testNotifyKey(/*expectToBeFiltered*/ true);
1657
1658 // Disable InputFilter
1659 mDispatcher->setInputFilterEnabled(false);
1660 // Send a key event, and check if it isn't filtered.
1661 testNotifyKey(/*expectToBeFiltered*/ false);
1662}
1663
chaviwfd6d3512019-03-25 13:23:49 -07001664class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001665 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001666 InputDispatcherTest::SetUp();
1667
1668 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1669 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1670 ADISPLAY_ID_DEFAULT);
1671 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1672 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1673 // window.
1674 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1675
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001676 mFocusedWindow =
1677 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1678 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1679 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1680 mFocusedWindowTouchPoint = 60;
chaviwfd6d3512019-03-25 13:23:49 -07001681
1682 // Set focused application.
1683 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001684 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001685
1686 // Expect one focus window exist in display.
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001687 mDispatcher->setInputWindows({mUnfocusedWindow, mFocusedWindow}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001688 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001689 }
1690
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001691 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001692 InputDispatcherTest::TearDown();
1693
1694 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001695 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001696 }
1697
1698protected:
1699 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001700 sp<FakeWindowHandle> mFocusedWindow;
1701 int32_t mFocusedWindowTouchPoint;
chaviwfd6d3512019-03-25 13:23:49 -07001702};
1703
1704// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1705// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1706// the onPointerDownOutsideFocus callback.
1707TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1708 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1709 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1710 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001711
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001712 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001713 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1714}
1715
1716// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1717// DOWN on the window that doesn't have focus. Ensure no window received the
1718// onPointerDownOutsideFocus callback.
1719TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1720 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1721 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1722 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001723
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001724 ASSERT_TRUE(mDispatcher->waitForIdle());
1725 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001726}
1727
1728// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1729// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1730TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1731 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1732 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001733
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001734 ASSERT_TRUE(mDispatcher->waitForIdle());
1735 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001736}
1737
1738// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1739// DOWN on the window that already has focus. Ensure no window received the
1740// onPointerDownOutsideFocus callback.
1741TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1742 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001743 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1744 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1745 mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
chaviwfd6d3512019-03-25 13:23:49 -07001746 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001747
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001748 ASSERT_TRUE(mDispatcher->waitForIdle());
1749 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001750}
1751
chaviwaf87b3e2019-10-01 16:59:28 -07001752// These tests ensures we can send touch events to a single client when there are multiple input
1753// windows that point to the same client token.
1754class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
1755 virtual void SetUp() override {
1756 InputDispatcherTest::SetUp();
1757
1758 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1759 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
1760 ADISPLAY_ID_DEFAULT);
1761 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
1762 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
1763 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1764 InputWindowInfo::FLAG_SPLIT_TOUCH);
1765 mWindow1->setId(0);
1766 mWindow1->setFrame(Rect(0, 0, 100, 100));
1767
1768 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
1769 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
1770 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1771 InputWindowInfo::FLAG_SPLIT_TOUCH);
1772 mWindow2->setId(1);
1773 mWindow2->setFrame(Rect(100, 100, 200, 200));
1774
1775 mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT);
1776 }
1777
1778protected:
1779 sp<FakeWindowHandle> mWindow1;
1780 sp<FakeWindowHandle> mWindow2;
1781
1782 // Helper function to convert the point from screen coordinates into the window's space
1783 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
1784 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
1785 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
1786 return {x, y};
1787 }
1788
1789 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
1790 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001791 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07001792 InputEvent* event = window->consume();
1793
1794 ASSERT_NE(nullptr, event) << name.c_str()
1795 << ": consumer should have returned non-NULL event.";
1796
1797 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
1798 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
1799 << " event, got " << inputEventTypeToString(event->getType()) << " event";
1800
1801 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
1802 EXPECT_EQ(expectedAction, motionEvent.getAction());
1803
1804 for (size_t i = 0; i < points.size(); i++) {
1805 float expectedX = points[i].x;
1806 float expectedY = points[i].y;
1807
1808 EXPECT_EQ(expectedX, motionEvent.getX(i))
1809 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
1810 << ", got " << motionEvent.getX(i);
1811 EXPECT_EQ(expectedY, motionEvent.getY(i))
1812 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
1813 << ", got " << motionEvent.getY(i);
1814 }
1815 }
1816};
1817
1818TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
1819 // Touch Window 1
1820 PointF touchedPoint = {10, 10};
1821 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1822
1823 NotifyMotionArgs motionArgs =
1824 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1825 ADISPLAY_ID_DEFAULT, {touchedPoint});
1826 mDispatcher->notifyMotion(&motionArgs);
1827 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1828
1829 // Release touch on Window 1
1830 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1831 ADISPLAY_ID_DEFAULT, {touchedPoint});
1832 mDispatcher->notifyMotion(&motionArgs);
1833 // consume the UP event
1834 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1835
1836 // Touch Window 2
1837 touchedPoint = {150, 150};
1838 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1839
1840 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1841 ADISPLAY_ID_DEFAULT, {touchedPoint});
1842 mDispatcher->notifyMotion(&motionArgs);
1843
1844 // Consuming from window1 since it's the window that has the InputReceiver
1845 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1846}
1847
1848TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
1849 mWindow2->setWindowScale(0.5f, 0.5f);
1850
1851 // Touch Window 1
1852 PointF touchedPoint = {10, 10};
1853 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1854
1855 NotifyMotionArgs motionArgs =
1856 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1857 ADISPLAY_ID_DEFAULT, {touchedPoint});
1858 mDispatcher->notifyMotion(&motionArgs);
1859 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1860
1861 // Release touch on Window 1
1862 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1863 ADISPLAY_ID_DEFAULT, {touchedPoint});
1864 mDispatcher->notifyMotion(&motionArgs);
1865 // consume the UP event
1866 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1867
1868 // Touch Window 2
1869 touchedPoint = {150, 150};
1870 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1871
1872 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1873 ADISPLAY_ID_DEFAULT, {touchedPoint});
1874 mDispatcher->notifyMotion(&motionArgs);
1875
1876 // Consuming from window1 since it's the window that has the InputReceiver
1877 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1878}
1879
Chavi Weingarten65f98b82020-01-16 18:56:50 +00001880TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
1881 mWindow2->setWindowScale(0.5f, 0.5f);
1882
1883 // Touch Window 1
1884 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1885 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1886
1887 NotifyMotionArgs motionArgs =
1888 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1889 ADISPLAY_ID_DEFAULT, touchedPoints);
1890 mDispatcher->notifyMotion(&motionArgs);
1891 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1892
1893 // Touch Window 2
1894 int32_t actionPointerDown =
1895 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1896 touchedPoints.emplace_back(PointF{150, 150});
1897 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1898
1899 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1900 ADISPLAY_ID_DEFAULT, touchedPoints);
1901 mDispatcher->notifyMotion(&motionArgs);
1902
1903 // Consuming from window1 since it's the window that has the InputReceiver
1904 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1905}
1906
1907TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
1908 mWindow2->setWindowScale(0.5f, 0.5f);
1909
1910 // Touch Window 1
1911 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1912 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1913
1914 NotifyMotionArgs motionArgs =
1915 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1916 ADISPLAY_ID_DEFAULT, touchedPoints);
1917 mDispatcher->notifyMotion(&motionArgs);
1918 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1919
1920 // Touch Window 2
1921 int32_t actionPointerDown =
1922 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1923 touchedPoints.emplace_back(PointF{150, 150});
1924 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1925
1926 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1927 ADISPLAY_ID_DEFAULT, touchedPoints);
1928 mDispatcher->notifyMotion(&motionArgs);
1929
1930 // Consuming from window1 since it's the window that has the InputReceiver
1931 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1932
1933 // Move both windows
1934 touchedPoints = {{20, 20}, {175, 175}};
1935 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1936 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1937
1938 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1939 ADISPLAY_ID_DEFAULT, touchedPoints);
1940 mDispatcher->notifyMotion(&motionArgs);
1941
1942 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1943}
1944
1945TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
1946 mWindow1->setWindowScale(0.5f, 0.5f);
1947
1948 // Touch Window 1
1949 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1950 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1951
1952 NotifyMotionArgs motionArgs =
1953 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1954 ADISPLAY_ID_DEFAULT, touchedPoints);
1955 mDispatcher->notifyMotion(&motionArgs);
1956 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1957
1958 // Touch Window 2
1959 int32_t actionPointerDown =
1960 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1961 touchedPoints.emplace_back(PointF{150, 150});
1962 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1963
1964 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1965 ADISPLAY_ID_DEFAULT, touchedPoints);
1966 mDispatcher->notifyMotion(&motionArgs);
1967
1968 // Consuming from window1 since it's the window that has the InputReceiver
1969 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1970
1971 // Move both windows
1972 touchedPoints = {{20, 20}, {175, 175}};
1973 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1974 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1975
1976 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1977 ADISPLAY_ID_DEFAULT, touchedPoints);
1978 mDispatcher->notifyMotion(&motionArgs);
1979
1980 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1981}
1982
Garfield Tane84e6f92019-08-29 17:28:41 -07001983} // namespace android::inputdispatcher