blob: eeff757b48663c8d646df9b54795402178f7fd2d [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan1c7bc862020-01-28 13:24:04 -080019#include <android-base/stringprintf.h>
Robert Carr803535b2018-08-02 16:38:15 -070020#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080021#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070022
Michael Wrightd02c5b62014-02-10 15:10:22 -080023#include <gtest/gtest.h>
24#include <linux/input.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080025#include <cinttypes>
26#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080027#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028
Garfield Tan1c7bc862020-01-28 13:24:04 -080029using android::base::StringPrintf;
30
Garfield Tane84e6f92019-08-29 17:28:41 -070031namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080032
33// An arbitrary time value.
34static const nsecs_t ARBITRARY_TIME = 1234;
35
36// An arbitrary device id.
37static const int32_t DEVICE_ID = 1;
38
Jeff Brownf086ddb2014-02-11 14:28:48 -080039// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080040static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080041
Michael Wrightd02c5b62014-02-10 15:10:22 -080042// An arbitrary injector pid / uid pair that has permission to inject events.
43static const int32_t INJECTOR_PID = 999;
44static const int32_t INJECTOR_UID = 1001;
45
chaviwd1c23182019-12-20 18:44:56 -080046struct PointF {
47 float x;
48 float y;
49};
Michael Wrightd02c5b62014-02-10 15:10:22 -080050
Gang Wang342c9272020-01-13 13:15:04 -050051/**
52 * Return a DOWN key event with KEYCODE_A.
53 */
54static KeyEvent getTestKeyEvent() {
55 KeyEvent event;
56
Garfield Tanfbe732e2020-01-24 11:26:14 -080057 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
58 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
59 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050060 return event;
61}
62
Michael Wrightd02c5b62014-02-10 15:10:22 -080063// --- FakeInputDispatcherPolicy ---
64
65class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
66 InputDispatcherConfiguration mConfig;
67
68protected:
69 virtual ~FakeInputDispatcherPolicy() {
70 }
71
72public:
73 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080074 }
75
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080076 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080077 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
78 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080081 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080082 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
83 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080084 }
85
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080086 void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
Michael Wrightd02c5b62014-02-10 15:10:22 -080087
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080088 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
89 ASSERT_TRUE(mConfigurationChangedTime)
90 << "Timed out waiting for configuration changed call";
91 ASSERT_EQ(*mConfigurationChangedTime, when);
92 mConfigurationChangedTime = std::nullopt;
93 }
94
95 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
96 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -080097 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080098 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
99 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
100 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
101 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
102 mLastNotifySwitch = std::nullopt;
103 }
104
chaviwfd6d3512019-03-25 13:23:49 -0700105 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 ASSERT_EQ(touchedToken, mOnPointerDownToken);
107 mOnPointerDownToken.clear();
108 }
109
110 void assertOnPointerDownWasNotCalled() {
111 ASSERT_TRUE(mOnPointerDownToken == nullptr)
112 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700113 }
114
Garfield Tan1c7bc862020-01-28 13:24:04 -0800115 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
116 mConfig.keyRepeatTimeout = timeout;
117 mConfig.keyRepeatDelay = delay;
118 }
119
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800121 std::unique_ptr<InputEvent> mFilteredEvent;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800122 std::optional<nsecs_t> mConfigurationChangedTime;
chaviwfd6d3512019-03-25 13:23:49 -0700123 sp<IBinder> mOnPointerDownToken;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800124 std::optional<NotifySwitchArgs> mLastNotifySwitch;
Jackal Guof9696682018-10-05 12:23:23 +0800125
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800126 virtual void notifyConfigurationChanged(nsecs_t when) override {
127 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800128 }
129
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700130 virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>&, const sp<IBinder>&,
131 const std::string&) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800132 return 0;
133 }
134
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700135 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800136
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700137 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700138
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700139 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800140 *outConfig = mConfig;
141 }
142
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800143 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800144 switch (inputEvent->getType()) {
145 case AINPUT_EVENT_TYPE_KEY: {
146 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800147 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800148 break;
149 }
150
151 case AINPUT_EVENT_TYPE_MOTION: {
152 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800153 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800154 break;
155 }
156 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157 return true;
158 }
159
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700160 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700162 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800163
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700164 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
165 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166 return 0;
167 }
168
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700169 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
170 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800171 return false;
172 }
173
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800174 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
175 uint32_t policyFlags) override {
176 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
177 * essentially a passthrough for notifySwitch.
178 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800179 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180 }
181
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700182 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700184 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185 return false;
186 }
Jackal Guof9696682018-10-05 12:23:23 +0800187
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700188 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
chaviwfd6d3512019-03-25 13:23:49 -0700189 mOnPointerDownToken = newToken;
190 }
191
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800192 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
193 int32_t displayId) {
194 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
195 ASSERT_EQ(mFilteredEvent->getType(), type);
196
197 if (type == AINPUT_EVENT_TYPE_KEY) {
198 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
199 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
200 EXPECT_EQ(keyEvent.getAction(), action);
201 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
202 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
203 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
204 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
205 EXPECT_EQ(motionEvent.getAction(), action);
206 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
207 } else {
208 FAIL() << "Unknown type: " << type;
209 }
210
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800211 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800212 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213};
214
Gang Wang342c9272020-01-13 13:15:04 -0500215// --- HmacKeyManagerTest ---
216
217class HmacKeyManagerTest : public testing::Test {
218protected:
219 HmacKeyManager mHmacKeyManager;
220};
221
222/**
223 * Ensure that separate calls to sign the same data are generating the same key.
224 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
225 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
226 * tests.
227 */
228TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
229 KeyEvent event = getTestKeyEvent();
230 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
231
232 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
233 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
234 ASSERT_EQ(hmac1, hmac2);
235}
236
237/**
238 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
239 */
240TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
241 KeyEvent event = getTestKeyEvent();
242 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
243 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
244
245 verifiedEvent.deviceId += 1;
246 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
247
248 verifiedEvent.source += 1;
249 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
250
251 verifiedEvent.eventTimeNanos += 1;
252 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
253
254 verifiedEvent.displayId += 1;
255 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
256
257 verifiedEvent.action += 1;
258 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
259
260 verifiedEvent.downTimeNanos += 1;
261 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
262
263 verifiedEvent.flags += 1;
264 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
265
266 verifiedEvent.keyCode += 1;
267 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
268
269 verifiedEvent.scanCode += 1;
270 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
271
272 verifiedEvent.metaState += 1;
273 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
274
275 verifiedEvent.repeatCount += 1;
276 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
277}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800278
279// --- InputDispatcherTest ---
280
281class InputDispatcherTest : public testing::Test {
282protected:
283 sp<FakeInputDispatcherPolicy> mFakePolicy;
284 sp<InputDispatcher> mDispatcher;
285
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700286 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800287 mFakePolicy = new FakeInputDispatcherPolicy();
288 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800289 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
290 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700291 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800292 }
293
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700294 virtual void TearDown() override {
295 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800296 mFakePolicy.clear();
297 mDispatcher.clear();
298 }
299};
300
301
302TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
303 KeyEvent event;
304
305 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800306 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
307 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600308 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
309 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700310 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
311 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
312 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 << "Should reject key events with undefined action.";
314
315 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800316 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
317 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600318 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700319 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
320 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
321 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800322 << "Should reject key events with ACTION_MULTIPLE.";
323}
324
325TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
326 MotionEvent event;
327 PointerProperties pointerProperties[MAX_POINTERS + 1];
328 PointerCoords pointerCoords[MAX_POINTERS + 1];
329 for (int i = 0; i <= MAX_POINTERS; i++) {
330 pointerProperties[i].clear();
331 pointerProperties[i].id = i;
332 pointerCoords[i].clear();
333 }
334
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800335 // Some constants commonly used below
336 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
337 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
338 constexpr int32_t metaState = AMETA_NONE;
339 constexpr MotionClassification classification = MotionClassification::NONE;
340
Michael Wrightd02c5b62014-02-10 15:10:22 -0800341 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800342 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600343 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
344 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
345 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700346 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700347 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
348 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
349 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800350 << "Should reject motion events with undefined action.";
351
352 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800353 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700354 AMOTION_EVENT_ACTION_POINTER_DOWN |
355 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600356 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
357 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
358 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700359 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700360 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
361 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
362 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800363 << "Should reject motion events with pointer down index too large.";
364
Garfield Tanfbe732e2020-01-24 11:26:14 -0800365 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700366 AMOTION_EVENT_ACTION_POINTER_DOWN |
367 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600368 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
369 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
370 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700371 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700372 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
373 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
374 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800375 << "Should reject motion events with pointer down index too small.";
376
377 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800378 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700379 AMOTION_EVENT_ACTION_POINTER_UP |
380 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600381 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
382 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
383 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700384 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700385 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
386 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
387 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800388 << "Should reject motion events with pointer up index too large.";
389
Garfield Tanfbe732e2020-01-24 11:26:14 -0800390 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700391 AMOTION_EVENT_ACTION_POINTER_UP |
392 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600393 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
394 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
395 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700396 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700397 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
398 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
399 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800400 << "Should reject motion events with pointer up index too small.";
401
402 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800403 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
404 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
405 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
406 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
407 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700408 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700409 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
410 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
411 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800412 << "Should reject motion events with 0 pointers.";
413
Garfield Tanfbe732e2020-01-24 11:26:14 -0800414 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
415 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
416 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
417 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
418 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700419 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700420 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
421 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
422 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800423 << "Should reject motion events with more than MAX_POINTERS pointers.";
424
425 // Rejects motion events with invalid pointer ids.
426 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800427 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
428 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
429 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
430 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
431 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700432 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700433 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
434 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
435 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436 << "Should reject motion events with pointer ids less than 0.";
437
438 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800439 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
440 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
441 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
442 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
443 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700444 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700445 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
446 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
447 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800448 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
449
450 // Rejects motion events with duplicate pointer ids.
451 pointerProperties[0].id = 1;
452 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800453 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
454 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
455 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
456 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
457 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700458 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700459 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
460 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
461 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800462 << "Should reject motion events with duplicate pointer ids.";
463}
464
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800465/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
466
467TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
468 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800469 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800470 mDispatcher->notifyConfigurationChanged(&args);
471 ASSERT_TRUE(mDispatcher->waitForIdle());
472
473 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
474}
475
476TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800477 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
478 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800479 mDispatcher->notifySwitch(&args);
480
481 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
482 args.policyFlags |= POLICY_FLAG_TRUSTED;
483 mFakePolicy->assertNotifySwitchWasCalled(args);
484}
485
Arthur Hungb92218b2018-08-14 12:00:21 +0800486// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700487static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
488static constexpr std::chrono::duration DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800489
490class FakeApplicationHandle : public InputApplicationHandle {
491public:
492 FakeApplicationHandle() {}
493 virtual ~FakeApplicationHandle() {}
494
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700495 virtual bool updateInfo() override {
496 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
Arthur Hungb92218b2018-08-14 12:00:21 +0800497 return true;
498 }
499};
500
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800501class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800502public:
chaviwd1c23182019-12-20 18:44:56 -0800503 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
504 : mName(name) {
505 mConsumer = std::make_unique<InputConsumer>(clientChannel);
506 }
507
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800508 InputEvent* consume() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800509 uint32_t consumeSeq;
510 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800511
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800512 std::chrono::time_point start = std::chrono::steady_clock::now();
513 status_t status = WOULD_BLOCK;
514 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800515 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800516 &event);
517 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
518 if (elapsed > 100ms) {
519 break;
520 }
521 }
522
523 if (status == WOULD_BLOCK) {
524 // Just means there's no event available.
525 return nullptr;
526 }
527
528 if (status != OK) {
529 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
530 return nullptr;
531 }
532 if (event == nullptr) {
533 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
534 return nullptr;
535 }
536
chaviwd1c23182019-12-20 18:44:56 -0800537 status = mConsumer->sendFinishedSignal(consumeSeq, true);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800538 if (status != OK) {
539 ADD_FAILURE() << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
540 }
541 return event;
542 }
543
544 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
545 int32_t expectedFlags) {
546 InputEvent* event = consume();
547
548 ASSERT_NE(nullptr, event) << mName.c_str()
549 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800550 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800551 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
552 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800553
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800554 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800555
Tiger Huang8664f8c2018-10-11 19:14:35 +0800556 switch (expectedEventType) {
557 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800558 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
559 EXPECT_EQ(expectedAction, keyEvent.getAction());
560 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800561 break;
562 }
563 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800564 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
565 EXPECT_EQ(expectedAction, motionEvent.getAction());
566 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800567 break;
568 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100569 case AINPUT_EVENT_TYPE_FOCUS: {
570 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
571 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800572 default: {
573 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
574 }
575 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800576 }
577
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100578 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
579 InputEvent* event = consume();
580 ASSERT_NE(nullptr, event) << mName.c_str()
581 << ": consumer should have returned non-NULL event.";
582 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
583 << "Got " << inputEventTypeToString(event->getType())
584 << " event instead of FOCUS event";
585
586 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
587 << mName.c_str() << ": event displayId should always be NONE.";
588
589 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
590 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
591 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
592 }
593
chaviwd1c23182019-12-20 18:44:56 -0800594 void assertNoEvents() {
595 InputEvent* event = consume();
596 ASSERT_EQ(nullptr, event)
597 << mName.c_str()
598 << ": should not have received any events, so consume() should return NULL";
599 }
600
601 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
602
603protected:
604 std::unique_ptr<InputConsumer> mConsumer;
605 PreallocatedInputEventFactory mEventFactory;
606
607 std::string mName;
608};
609
610class FakeWindowHandle : public InputWindowHandle {
611public:
612 static const int32_t WIDTH = 600;
613 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800614
615 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
616 const sp<InputDispatcher>& dispatcher, const std::string name,
617 int32_t displayId, sp<IBinder> token = nullptr)
618 : mName(name) {
619 if (token == nullptr) {
620 sp<InputChannel> serverChannel, clientChannel;
621 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
622 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
623 dispatcher->registerInputChannel(serverChannel);
624 token = serverChannel->getConnectionToken();
625 }
626
627 inputApplicationHandle->updateInfo();
628 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
629
630 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700631 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800632 mInfo.name = name;
633 mInfo.layoutParamsFlags = 0;
634 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700635 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
chaviwd1c23182019-12-20 18:44:56 -0800636 mInfo.frameLeft = 0;
637 mInfo.frameTop = 0;
638 mInfo.frameRight = WIDTH;
639 mInfo.frameBottom = HEIGHT;
640 mInfo.globalScaleFactor = 1.0;
641 mInfo.touchableRegion.clear();
642 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
643 mInfo.visible = true;
644 mInfo.canReceiveKeys = true;
645 mInfo.hasFocus = false;
646 mInfo.hasWallpaper = false;
647 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800648 mInfo.ownerPid = INJECTOR_PID;
649 mInfo.ownerUid = INJECTOR_UID;
650 mInfo.inputFeatures = 0;
651 mInfo.displayId = displayId;
652 }
653
654 virtual bool updateInfo() { return true; }
655
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100656 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800657
658 void setFrame(const Rect& frame) {
659 mInfo.frameLeft = frame.left;
660 mInfo.frameTop = frame.top;
661 mInfo.frameRight = frame.right;
662 mInfo.frameBottom = frame.bottom;
663 mInfo.touchableRegion.clear();
664 mInfo.addTouchableRegion(frame);
665 }
666
667 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
668
chaviwaf87b3e2019-10-01 16:59:28 -0700669 void setWindowScale(float xScale, float yScale) {
670 mInfo.windowXScale = xScale;
671 mInfo.windowYScale = yScale;
672 }
673
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800674 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
675 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
676 expectedFlags);
677 }
678
Svet Ganov5d3bc372020-01-26 23:11:07 -0800679 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
680 int32_t expectedFlags = 0) {
681 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
682 expectedFlags);
683 }
684
685 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
686 int32_t expectedFlags = 0) {
687 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
688 expectedFlags);
689 }
690
691 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
692 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800693 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
694 expectedFlags);
695 }
696
Svet Ganov5d3bc372020-01-26 23:11:07 -0800697 void consumeMotionPointerDown(int32_t pointerIdx,
698 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
699 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
700 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
701 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
702 }
703
704 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
705 int32_t expectedFlags = 0) {
706 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
707 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
708 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
709 }
710
711 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
712 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000713 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
714 expectedFlags);
715 }
716
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100717 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
718 ASSERT_NE(mInputReceiver, nullptr)
719 << "Cannot consume events from a window with no receiver";
720 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
721 }
722
chaviwd1c23182019-12-20 18:44:56 -0800723 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
724 int32_t expectedFlags) {
725 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
726 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
727 expectedFlags);
728 }
729
chaviwaf87b3e2019-10-01 16:59:28 -0700730 InputEvent* consume() {
731 if (mInputReceiver == nullptr) {
732 return nullptr;
733 }
734 return mInputReceiver->consume();
735 }
736
Arthur Hungb92218b2018-08-14 12:00:21 +0800737 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800738 ASSERT_NE(mInputReceiver, nullptr)
739 << "Call 'assertNoEvents' on a window with an InputReceiver";
740 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800741 }
742
chaviwaf87b3e2019-10-01 16:59:28 -0700743 sp<IBinder> getToken() { return mInfo.token; }
744
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100745 const std::string& getName() { return mName; }
746
chaviwd1c23182019-12-20 18:44:56 -0800747private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100748 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800749 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700750 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800751};
752
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700753std::atomic<int32_t> FakeWindowHandle::sId{1};
754
Tiger Huang721e26f2018-07-24 22:26:19 +0800755static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
756 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800757 KeyEvent event;
758 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
759
760 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800761 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
762 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
763 AMETA_NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600764 /* repeatCount */ 0, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800765
766 // Inject event until dispatch out.
767 return dispatcher->injectInputEvent(
768 &event,
769 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
770 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
771}
772
Garfield Tan00f511d2019-06-12 16:55:40 -0700773static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
774 int32_t source, int32_t displayId, int32_t x, int32_t y,
775 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
776 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800777 MotionEvent event;
778 PointerProperties pointerProperties[1];
779 PointerCoords pointerCoords[1];
780
781 pointerProperties[0].clear();
782 pointerProperties[0].id = 0;
783 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
784
785 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700786 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
787 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800788
789 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
790 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
792 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600793 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600795 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
796 /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition,
797 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700798 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800799
800 // Inject event until dispatch out.
801 return dispatcher->injectInputEvent(
802 &event,
803 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
804 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
805}
806
Garfield Tan00f511d2019-06-12 16:55:40 -0700807static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700808 int32_t displayId, const PointF& location = {100, 200}) {
809 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x,
810 location.y);
Garfield Tan00f511d2019-06-12 16:55:40 -0700811}
812
Michael Wright3a240c42019-12-10 20:53:41 +0000813static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700814 int32_t displayId, const PointF& location = {100, 200}) {
815 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location.x,
816 location.y);
Michael Wright3a240c42019-12-10 20:53:41 +0000817}
818
Jackal Guof9696682018-10-05 12:23:23 +0800819static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
820 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
821 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800822 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
823 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
824 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800825
826 return args;
827}
828
chaviwd1c23182019-12-20 18:44:56 -0800829static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
830 const std::vector<PointF>& points) {
831 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700832 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
833 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
834 }
835
chaviwd1c23182019-12-20 18:44:56 -0800836 PointerProperties pointerProperties[pointerCount];
837 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800838
chaviwd1c23182019-12-20 18:44:56 -0800839 for (size_t i = 0; i < pointerCount; i++) {
840 pointerProperties[i].clear();
841 pointerProperties[i].id = i;
842 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800843
chaviwd1c23182019-12-20 18:44:56 -0800844 pointerCoords[i].clear();
845 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
846 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
847 }
Jackal Guof9696682018-10-05 12:23:23 +0800848
849 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
850 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800851 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700852 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
853 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800854 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
855 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700856 AMOTION_EVENT_INVALID_CURSOR_POSITION,
857 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800858
859 return args;
860}
861
chaviwd1c23182019-12-20 18:44:56 -0800862static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
863 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
864}
865
Arthur Hungb92218b2018-08-14 12:00:21 +0800866TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
867 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800868 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
869 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800870
Arthur Hung72d8dc32020-03-28 00:48:39 +0000871 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800872 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
873 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800874 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
875
876 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800877 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800878}
879
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700880/**
881 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
882 * To ensure that window receives only events that were directly inside of it, add
883 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
884 * when finding touched windows.
885 * This test serves as a sanity check for the next test, where setInputWindows is
886 * called twice.
887 */
888TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
889 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
890 sp<FakeWindowHandle> window =
891 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
892 window->setFrame(Rect(0, 0, 100, 100));
893 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
894
895 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
896 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
897 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
898 {50, 50}))
899 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
900
901 // Window should receive motion event.
902 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
903}
904
905/**
906 * Calling setInputWindows twice, with the same info, should not cause any issues.
907 * To ensure that window receives only events that were directly inside of it, add
908 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
909 * when finding touched windows.
910 */
911TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
912 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
913 sp<FakeWindowHandle> window =
914 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
915 window->setFrame(Rect(0, 0, 100, 100));
916 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
917
918 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
920 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
921 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
922 {50, 50}))
923 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
924
925 // Window should receive motion event.
926 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
927}
928
Arthur Hungb92218b2018-08-14 12:00:21 +0800929// The foreground window should receive the first touch down event.
930TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
931 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800932 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
933 ADISPLAY_ID_DEFAULT);
934 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
935 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800936
Arthur Hung72d8dc32020-03-28 00:48:39 +0000937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800938 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
939 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800940 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
941
942 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800943 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800944 windowSecond->assertNoEvents();
945}
946
947TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
948 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800949 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
950 ADISPLAY_ID_DEFAULT);
951 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
952 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800953
Arthur Hung7ab76b12019-01-09 19:17:20 +0800954 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800955 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800956
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100957 // Display should have only one focused window
958 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +0000959 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100960
961 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +0800962 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
963 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
964
965 // Focused window should receive event.
966 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800967 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800968}
969
Arthur Hung7ab76b12019-01-09 19:17:20 +0800970TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
971 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
972 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
973 ADISPLAY_ID_DEFAULT);
974 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
975 ADISPLAY_ID_DEFAULT);
976
977 // Set focused application.
978 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
979
980 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100981 windowTop->setFocus(true);
982 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800983
Arthur Hung72d8dc32020-03-28 00:48:39 +0000984 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100985 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800986 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
987 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
988
989 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800990 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800991 windowSecond->assertNoEvents();
992}
993
Arthur Hung3b413f22018-10-26 18:05:34 +0800994TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
995 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
996
997 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
998 ADISPLAY_ID_DEFAULT);
999 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1000 ADISPLAY_ID_DEFAULT);
1001
Arthur Hung832bc4a2019-01-28 11:43:17 +08001002 // Set focused application.
1003 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001004
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001005 windowTop->setFocus(true);
1006 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001007 // Release channel for window is no longer valid.
1008 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001009 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001010 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001011
Arthur Hung832bc4a2019-01-28 11:43:17 +08001012 // Test inject a key down, should dispatch to a valid window.
1013 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1014 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001015
1016 // Top window is invalid, so it should not receive any input event.
1017 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001018 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001019}
1020
Garfield Tan00f511d2019-06-12 16:55:40 -07001021TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1022 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1023
1024 sp<FakeWindowHandle> windowLeft =
1025 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1026 windowLeft->setFrame(Rect(0, 0, 600, 800));
1027 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1028 sp<FakeWindowHandle> windowRight =
1029 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1030 windowRight->setFrame(Rect(600, 0, 1200, 800));
1031 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1032
1033 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1034
Arthur Hung72d8dc32020-03-28 00:48:39 +00001035 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001036
1037 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1038 // left window. This event should be dispatched to the left window.
1039 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1040 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
1041 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001042 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001043 windowRight->assertNoEvents();
1044}
1045
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001046TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1047 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1048 sp<FakeWindowHandle> window =
1049 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001050 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001051
Arthur Hung72d8dc32020-03-28 00:48:39 +00001052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001053 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001054
1055 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1056 mDispatcher->notifyKey(&keyArgs);
1057
1058 // Window should receive key down event.
1059 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1060
1061 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1062 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001063 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001064 mDispatcher->notifyDeviceReset(&args);
1065 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1066 AKEY_EVENT_FLAG_CANCELED);
1067}
1068
1069TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1070 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1071 sp<FakeWindowHandle> window =
1072 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1073
Arthur Hung72d8dc32020-03-28 00:48:39 +00001074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001075
1076 NotifyMotionArgs motionArgs =
1077 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1078 ADISPLAY_ID_DEFAULT);
1079 mDispatcher->notifyMotion(&motionArgs);
1080
1081 // Window should receive motion down event.
1082 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1083
1084 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1085 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001086 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001087 mDispatcher->notifyDeviceReset(&args);
1088 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1089 0 /*expectedFlags*/);
1090}
1091
Svet Ganov5d3bc372020-01-26 23:11:07 -08001092TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1093 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1094
1095 // Create a couple of windows
1096 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1097 "First Window", ADISPLAY_ID_DEFAULT);
1098 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1099 "Second Window", ADISPLAY_ID_DEFAULT);
1100
1101 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001102 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001103
1104 // Send down to the first window
1105 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1106 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1107 mDispatcher->notifyMotion(&downMotionArgs);
1108 // Only the first window should get the down event
1109 firstWindow->consumeMotionDown();
1110 secondWindow->assertNoEvents();
1111
1112 // Transfer touch focus to the second window
1113 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1114 // The first window gets cancel and the second gets down
1115 firstWindow->consumeMotionCancel();
1116 secondWindow->consumeMotionDown();
1117
1118 // Send up event to the second window
1119 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1120 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1121 mDispatcher->notifyMotion(&upMotionArgs);
1122 // The first window gets no events and the second gets up
1123 firstWindow->assertNoEvents();
1124 secondWindow->consumeMotionUp();
1125}
1126
1127TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1128 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1129
1130 PointF touchPoint = {10, 10};
1131
1132 // Create a couple of windows
1133 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1134 "First Window", ADISPLAY_ID_DEFAULT);
1135 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1136 "Second Window", ADISPLAY_ID_DEFAULT);
1137
1138 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001139 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001140
1141 // Send down to the first window
1142 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1143 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1144 mDispatcher->notifyMotion(&downMotionArgs);
1145 // Only the first window should get the down event
1146 firstWindow->consumeMotionDown();
1147 secondWindow->assertNoEvents();
1148
1149 // Send pointer down to the first window
1150 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1151 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1152 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1153 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1154 // Only the first window should get the pointer down event
1155 firstWindow->consumeMotionPointerDown(1);
1156 secondWindow->assertNoEvents();
1157
1158 // Transfer touch focus to the second window
1159 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1160 // The first window gets cancel and the second gets down and pointer down
1161 firstWindow->consumeMotionCancel();
1162 secondWindow->consumeMotionDown();
1163 secondWindow->consumeMotionPointerDown(1);
1164
1165 // Send pointer up to the second window
1166 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1167 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1168 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1169 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1170 // The first window gets nothing and the second gets pointer up
1171 firstWindow->assertNoEvents();
1172 secondWindow->consumeMotionPointerUp(1);
1173
1174 // Send up event to the second window
1175 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1176 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1177 mDispatcher->notifyMotion(&upMotionArgs);
1178 // The first window gets nothing and the second gets up
1179 firstWindow->assertNoEvents();
1180 secondWindow->consumeMotionUp();
1181}
1182
1183TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1184 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1185
1186 // Create a non touch modal window that supports split touch
1187 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1188 "First Window", ADISPLAY_ID_DEFAULT);
1189 firstWindow->setFrame(Rect(0, 0, 600, 400));
1190 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1191 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1192
1193 // Create a non touch modal window that supports split touch
1194 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1195 "Second Window", ADISPLAY_ID_DEFAULT);
1196 secondWindow->setFrame(Rect(0, 400, 600, 800));
1197 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1198 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1199
1200 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001202
1203 PointF pointInFirst = {300, 200};
1204 PointF pointInSecond = {300, 600};
1205
1206 // Send down to the first window
1207 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1208 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1209 mDispatcher->notifyMotion(&firstDownMotionArgs);
1210 // Only the first window should get the down event
1211 firstWindow->consumeMotionDown();
1212 secondWindow->assertNoEvents();
1213
1214 // Send down to the second window
1215 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1216 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1217 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1218 mDispatcher->notifyMotion(&secondDownMotionArgs);
1219 // The first window gets a move and the second a down
1220 firstWindow->consumeMotionMove();
1221 secondWindow->consumeMotionDown();
1222
1223 // Transfer touch focus to the second window
1224 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1225 // The first window gets cancel and the new gets pointer down (it already saw down)
1226 firstWindow->consumeMotionCancel();
1227 secondWindow->consumeMotionPointerDown(1);
1228
1229 // Send pointer up to the second window
1230 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1231 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1232 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1233 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1234 // The first window gets nothing and the second gets pointer up
1235 firstWindow->assertNoEvents();
1236 secondWindow->consumeMotionPointerUp(1);
1237
1238 // Send up event to the second window
1239 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1240 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1241 mDispatcher->notifyMotion(&upMotionArgs);
1242 // The first window gets nothing and the second gets up
1243 firstWindow->assertNoEvents();
1244 secondWindow->consumeMotionUp();
1245}
1246
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001247TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1248 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1249 sp<FakeWindowHandle> window =
1250 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1251
1252 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001253 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001254
1255 window->consumeFocusEvent(true);
1256
1257 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1258 mDispatcher->notifyKey(&keyArgs);
1259
1260 // Window should receive key down event.
1261 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1262}
1263
1264TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1265 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1266 sp<FakeWindowHandle> window =
1267 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1268
Arthur Hung72d8dc32020-03-28 00:48:39 +00001269 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001270
1271 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1272 mDispatcher->notifyKey(&keyArgs);
1273 mDispatcher->waitForIdle();
1274
1275 window->assertNoEvents();
1276}
1277
1278// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1279TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1280 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1281 sp<FakeWindowHandle> window =
1282 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1283
Arthur Hung72d8dc32020-03-28 00:48:39 +00001284 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001285
1286 // Send key
1287 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1288 mDispatcher->notifyKey(&keyArgs);
1289 // Send motion
1290 NotifyMotionArgs motionArgs =
1291 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1292 ADISPLAY_ID_DEFAULT);
1293 mDispatcher->notifyMotion(&motionArgs);
1294
1295 // Window should receive only the motion event
1296 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1297 window->assertNoEvents(); // Key event or focus event will not be received
1298}
1299
chaviwd1c23182019-12-20 18:44:56 -08001300class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001301public:
1302 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001303 int32_t displayId, bool isGestureMonitor = false) {
1304 sp<InputChannel> serverChannel, clientChannel;
1305 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1306 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1307 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001308 }
1309
chaviwd1c23182019-12-20 18:44:56 -08001310 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1311
1312 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1313 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1314 expectedDisplayId, expectedFlags);
1315 }
1316
1317 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1318 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1319 expectedDisplayId, expectedFlags);
1320 }
1321
1322 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1323 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1324 expectedDisplayId, expectedFlags);
1325 }
1326
1327 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1328
1329private:
1330 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001331};
1332
1333// Tests for gesture monitors
1334TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1335 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1336 sp<FakeWindowHandle> window =
1337 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001338 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001339
chaviwd1c23182019-12-20 18:44:56 -08001340 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1341 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001342
1343 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1344 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1345 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1346 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001347 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001348}
1349
1350TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1351 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1352 sp<FakeWindowHandle> window =
1353 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1354
1355 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001356 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001357
Arthur Hung72d8dc32020-03-28 00:48:39 +00001358 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001359 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001360
chaviwd1c23182019-12-20 18:44:56 -08001361 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1362 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001363
1364 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1365 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1366 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001367 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001368}
1369
1370TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1371 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1372 sp<FakeWindowHandle> window =
1373 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001374 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001375
chaviwd1c23182019-12-20 18:44:56 -08001376 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1377 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001378
1379 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1380 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1381 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1382 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001383 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001384
1385 window->releaseChannel();
1386
chaviwd1c23182019-12-20 18:44:56 -08001387 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001388
1389 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1390 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1391 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001392 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001393}
1394
chaviw81e2bb92019-12-18 15:03:51 -08001395TEST_F(InputDispatcherTest, TestMoveEvent) {
1396 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1397 sp<FakeWindowHandle> window =
1398 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1399
Arthur Hung72d8dc32020-03-28 00:48:39 +00001400 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001401
1402 NotifyMotionArgs motionArgs =
1403 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1404 ADISPLAY_ID_DEFAULT);
1405
1406 mDispatcher->notifyMotion(&motionArgs);
1407 // Window should receive motion down event.
1408 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1409
1410 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001411 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001412 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1413 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1414 motionArgs.pointerCoords[0].getX() - 10);
1415
1416 mDispatcher->notifyMotion(&motionArgs);
1417 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1418 0 /*expectedFlags*/);
1419}
1420
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001421/**
1422 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1423 * the device default right away. In the test scenario, we check both the default value,
1424 * and the action of enabling / disabling.
1425 */
1426TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1427 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1428 sp<FakeWindowHandle> window =
1429 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1430
1431 // Set focused application.
1432 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1433 window->setFocus(true);
1434
1435 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001437 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1438
1439 SCOPED_TRACE("Remove the window to trigger focus loss");
1440 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001441 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001442 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1443
1444 SCOPED_TRACE("Disable touch mode");
1445 mDispatcher->setInTouchMode(false);
1446 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001448 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1449
1450 SCOPED_TRACE("Remove the window to trigger focus loss");
1451 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001453 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1454
1455 SCOPED_TRACE("Enable touch mode again");
1456 mDispatcher->setInTouchMode(true);
1457 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001459 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1460
1461 window->assertNoEvents();
1462}
1463
Gang Wange9087892020-01-07 12:17:14 -05001464TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1465 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1466 sp<FakeWindowHandle> window =
1467 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1468
1469 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1470 window->setFocus(true);
1471
Arthur Hung72d8dc32020-03-28 00:48:39 +00001472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001473 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1474
1475 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1476 mDispatcher->notifyKey(&keyArgs);
1477
1478 InputEvent* event = window->consume();
1479 ASSERT_NE(event, nullptr);
1480
1481 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1482 ASSERT_NE(verified, nullptr);
1483 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1484
1485 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1486 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1487 ASSERT_EQ(keyArgs.source, verified->source);
1488 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1489
1490 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1491
1492 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1493 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001494 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1495 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1496 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1497 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1498 ASSERT_EQ(0, verifiedKey.repeatCount);
1499}
1500
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001501TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1502 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1503 sp<FakeWindowHandle> window =
1504 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1505
1506 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1507
Arthur Hung72d8dc32020-03-28 00:48:39 +00001508 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001509
1510 NotifyMotionArgs motionArgs =
1511 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1512 ADISPLAY_ID_DEFAULT);
1513 mDispatcher->notifyMotion(&motionArgs);
1514
1515 InputEvent* event = window->consume();
1516 ASSERT_NE(event, nullptr);
1517
1518 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1519 ASSERT_NE(verified, nullptr);
1520 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1521
1522 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1523 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1524 EXPECT_EQ(motionArgs.source, verified->source);
1525 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1526
1527 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1528
1529 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1530 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1531 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1532 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1533 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1534 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1535 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1536}
1537
Garfield Tan1c7bc862020-01-28 13:24:04 -08001538class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
1539protected:
1540 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
1541 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
1542
1543 sp<FakeApplicationHandle> mApp;
1544 sp<FakeWindowHandle> mWindow;
1545
1546 virtual void SetUp() override {
1547 mFakePolicy = new FakeInputDispatcherPolicy();
1548 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
1549 mDispatcher = new InputDispatcher(mFakePolicy);
1550 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
1551 ASSERT_EQ(OK, mDispatcher->start());
1552
1553 setUpWindow();
1554 }
1555
1556 void setUpWindow() {
1557 mApp = new FakeApplicationHandle();
1558 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1559
1560 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08001562
1563 mWindow->consumeFocusEvent(true);
1564 }
1565
1566 void sendAndConsumeKeyDown() {
1567 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1568 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
1569 mDispatcher->notifyKey(&keyArgs);
1570
1571 // Window should receive key down event.
1572 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1573 }
1574
1575 void expectKeyRepeatOnce(int32_t repeatCount) {
1576 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
1577 InputEvent* repeatEvent = mWindow->consume();
1578 ASSERT_NE(nullptr, repeatEvent);
1579
1580 uint32_t eventType = repeatEvent->getType();
1581 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
1582
1583 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
1584 uint32_t eventAction = repeatKeyEvent->getAction();
1585 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
1586 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
1587 }
1588
1589 void sendAndConsumeKeyUp() {
1590 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
1591 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
1592 mDispatcher->notifyKey(&keyArgs);
1593
1594 // Window should receive key down event.
1595 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1596 0 /*expectedFlags*/);
1597 }
1598};
1599
1600TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
1601 sendAndConsumeKeyDown();
1602 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1603 expectKeyRepeatOnce(repeatCount);
1604 }
1605}
1606
1607TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
1608 sendAndConsumeKeyDown();
1609 expectKeyRepeatOnce(1 /*repeatCount*/);
1610 sendAndConsumeKeyUp();
1611 mWindow->assertNoEvents();
1612}
1613
1614TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
1615 sendAndConsumeKeyDown();
1616 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1617 InputEvent* repeatEvent = mWindow->consume();
1618 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1619 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
1620 IdGenerator::getSource(repeatEvent->getId()));
1621 }
1622}
1623
1624TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
1625 sendAndConsumeKeyDown();
1626
1627 std::unordered_set<int32_t> idSet;
1628 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1629 InputEvent* repeatEvent = mWindow->consume();
1630 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1631 int32_t id = repeatEvent->getId();
1632 EXPECT_EQ(idSet.end(), idSet.find(id));
1633 idSet.insert(id);
1634 }
1635}
1636
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001637/* Test InputDispatcher for MultiDisplay */
1638class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1639public:
1640 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001641 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001642 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001643
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001644 application1 = new FakeApplicationHandle();
1645 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1646 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001647
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001648 // Set focus window for primary display, but focused display would be second one.
1649 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001650 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001652 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001653
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001654 application2 = new FakeApplicationHandle();
1655 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1656 SECOND_DISPLAY_ID);
1657 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001658 // Set focus display to second one.
1659 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1660 // Set focus window for second display.
1661 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001662 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001663 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001664 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001665 }
1666
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001667 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001668 InputDispatcherTest::TearDown();
1669
1670 application1.clear();
1671 windowInPrimary.clear();
1672 application2.clear();
1673 windowInSecondary.clear();
1674 }
1675
1676protected:
1677 sp<FakeApplicationHandle> application1;
1678 sp<FakeWindowHandle> windowInPrimary;
1679 sp<FakeApplicationHandle> application2;
1680 sp<FakeWindowHandle> windowInSecondary;
1681};
1682
1683TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1684 // Test touch down on primary display.
1685 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1686 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001687 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001688 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001689 windowInSecondary->assertNoEvents();
1690
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001691 // Test touch down on second display.
1692 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1693 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001694 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1695 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001696 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001697}
1698
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001699TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001700 // Test inject a key down with display id specified.
1701 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1702 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001703 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001704 windowInSecondary->assertNoEvents();
1705
1706 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001707 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1708 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1709 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001710 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001711
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001712 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001713 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08001714
1715 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001716 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1717 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001718
1719 // Test inject a key down, should timeout because of no target window.
1720 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1721 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1722 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001723 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001724 windowInSecondary->assertNoEvents();
1725}
1726
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001727// Test per-display input monitors for motion event.
1728TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001729 FakeMonitorReceiver monitorInPrimary =
1730 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1731 FakeMonitorReceiver monitorInSecondary =
1732 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001733
1734 // Test touch down on primary display.
1735 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1736 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1737 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001738 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001739 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001740 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001741 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001742
1743 // Test touch down on second display.
1744 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1745 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1746 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1747 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001748 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001749 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001750 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001751
1752 // Test inject a non-pointer motion event.
1753 // If specific a display, it will dispatch to the focused window of particular display,
1754 // or it will dispatch to the focused window of focused display.
1755 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1756 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1757 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1758 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001759 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001760 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001761 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001762}
1763
1764// Test per-display input monitors for key event.
1765TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1766 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001767 FakeMonitorReceiver monitorInPrimary =
1768 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1769 FakeMonitorReceiver monitorInSecondary =
1770 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001771
1772 // Test inject a key down.
1773 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1774 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1775 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001776 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001777 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001778 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001779}
1780
Jackal Guof9696682018-10-05 12:23:23 +08001781class InputFilterTest : public InputDispatcherTest {
1782protected:
1783 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1784
1785 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1786 NotifyMotionArgs motionArgs;
1787
1788 motionArgs = generateMotionArgs(
1789 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1790 mDispatcher->notifyMotion(&motionArgs);
1791 motionArgs = generateMotionArgs(
1792 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1793 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001794 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001795 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001796 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001797 } else {
1798 mFakePolicy->assertFilterInputEventWasNotCalled();
1799 }
1800 }
1801
1802 void testNotifyKey(bool expectToBeFiltered) {
1803 NotifyKeyArgs keyArgs;
1804
1805 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1806 mDispatcher->notifyKey(&keyArgs);
1807 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1808 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001809 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001810
1811 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001812 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001813 } else {
1814 mFakePolicy->assertFilterInputEventWasNotCalled();
1815 }
1816 }
1817};
1818
1819// Test InputFilter for MotionEvent
1820TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1821 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1822 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1823 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1824
1825 // Enable InputFilter
1826 mDispatcher->setInputFilterEnabled(true);
1827 // Test touch on both primary and second display, and check if both events are filtered.
1828 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1829 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1830
1831 // Disable InputFilter
1832 mDispatcher->setInputFilterEnabled(false);
1833 // Test touch on both primary and second display, and check if both events aren't filtered.
1834 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1835 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1836}
1837
1838// Test InputFilter for KeyEvent
1839TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1840 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1841 testNotifyKey(/*expectToBeFiltered*/ false);
1842
1843 // Enable InputFilter
1844 mDispatcher->setInputFilterEnabled(true);
1845 // Send a key event, and check if it is filtered.
1846 testNotifyKey(/*expectToBeFiltered*/ true);
1847
1848 // Disable InputFilter
1849 mDispatcher->setInputFilterEnabled(false);
1850 // Send a key event, and check if it isn't filtered.
1851 testNotifyKey(/*expectToBeFiltered*/ false);
1852}
1853
chaviwfd6d3512019-03-25 13:23:49 -07001854class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001855 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001856 InputDispatcherTest::SetUp();
1857
1858 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1859 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1860 ADISPLAY_ID_DEFAULT);
1861 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1862 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1863 // window.
1864 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1865
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001866 mFocusedWindow =
1867 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1868 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1869 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07001870
1871 // Set focused application.
1872 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001873 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001874
1875 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001876 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001877 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001878 }
1879
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001880 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001881 InputDispatcherTest::TearDown();
1882
1883 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001884 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001885 }
1886
1887protected:
1888 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001889 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001890 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07001891};
1892
1893// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1894// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1895// the onPointerDownOutsideFocus callback.
1896TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001897 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1898 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1899 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07001900 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001901 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07001902
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001903 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001904 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1905}
1906
1907// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1908// DOWN on the window that doesn't have focus. Ensure no window received the
1909// onPointerDownOutsideFocus callback.
1910TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001911 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1912 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07001913 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001914 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07001915
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001916 ASSERT_TRUE(mDispatcher->waitForIdle());
1917 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001918}
1919
1920// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1921// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1922TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1923 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1924 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001925 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07001926
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001927 ASSERT_TRUE(mDispatcher->waitForIdle());
1928 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001929}
1930
1931// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1932// DOWN on the window that already has focus. Ensure no window received the
1933// onPointerDownOutsideFocus callback.
1934TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1935 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001936 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1937 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001938 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07001939 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001940 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07001941
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001942 ASSERT_TRUE(mDispatcher->waitForIdle());
1943 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001944}
1945
chaviwaf87b3e2019-10-01 16:59:28 -07001946// These tests ensures we can send touch events to a single client when there are multiple input
1947// windows that point to the same client token.
1948class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
1949 virtual void SetUp() override {
1950 InputDispatcherTest::SetUp();
1951
1952 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1953 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
1954 ADISPLAY_ID_DEFAULT);
1955 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
1956 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
1957 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1958 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07001959 mWindow1->setFrame(Rect(0, 0, 100, 100));
1960
1961 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
1962 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
1963 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1964 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07001965 mWindow2->setFrame(Rect(100, 100, 200, 200));
1966
Arthur Hung72d8dc32020-03-28 00:48:39 +00001967 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07001968 }
1969
1970protected:
1971 sp<FakeWindowHandle> mWindow1;
1972 sp<FakeWindowHandle> mWindow2;
1973
1974 // Helper function to convert the point from screen coordinates into the window's space
1975 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
1976 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
1977 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
1978 return {x, y};
1979 }
1980
1981 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
1982 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001983 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07001984 InputEvent* event = window->consume();
1985
1986 ASSERT_NE(nullptr, event) << name.c_str()
1987 << ": consumer should have returned non-NULL event.";
1988
1989 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
1990 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
1991 << " event, got " << inputEventTypeToString(event->getType()) << " event";
1992
1993 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
1994 EXPECT_EQ(expectedAction, motionEvent.getAction());
1995
1996 for (size_t i = 0; i < points.size(); i++) {
1997 float expectedX = points[i].x;
1998 float expectedY = points[i].y;
1999
2000 EXPECT_EQ(expectedX, motionEvent.getX(i))
2001 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2002 << ", got " << motionEvent.getX(i);
2003 EXPECT_EQ(expectedY, motionEvent.getY(i))
2004 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2005 << ", got " << motionEvent.getY(i);
2006 }
2007 }
2008};
2009
2010TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2011 // Touch Window 1
2012 PointF touchedPoint = {10, 10};
2013 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2014
2015 NotifyMotionArgs motionArgs =
2016 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2017 ADISPLAY_ID_DEFAULT, {touchedPoint});
2018 mDispatcher->notifyMotion(&motionArgs);
2019 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2020
2021 // Release touch on Window 1
2022 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2023 ADISPLAY_ID_DEFAULT, {touchedPoint});
2024 mDispatcher->notifyMotion(&motionArgs);
2025 // consume the UP event
2026 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2027
2028 // Touch Window 2
2029 touchedPoint = {150, 150};
2030 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2031
2032 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2033 ADISPLAY_ID_DEFAULT, {touchedPoint});
2034 mDispatcher->notifyMotion(&motionArgs);
2035
2036 // Consuming from window1 since it's the window that has the InputReceiver
2037 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2038}
2039
2040TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2041 mWindow2->setWindowScale(0.5f, 0.5f);
2042
2043 // Touch Window 1
2044 PointF touchedPoint = {10, 10};
2045 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2046
2047 NotifyMotionArgs motionArgs =
2048 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2049 ADISPLAY_ID_DEFAULT, {touchedPoint});
2050 mDispatcher->notifyMotion(&motionArgs);
2051 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2052
2053 // Release touch on Window 1
2054 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2055 ADISPLAY_ID_DEFAULT, {touchedPoint});
2056 mDispatcher->notifyMotion(&motionArgs);
2057 // consume the UP event
2058 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2059
2060 // Touch Window 2
2061 touchedPoint = {150, 150};
2062 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2063
2064 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2065 ADISPLAY_ID_DEFAULT, {touchedPoint});
2066 mDispatcher->notifyMotion(&motionArgs);
2067
2068 // Consuming from window1 since it's the window that has the InputReceiver
2069 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2070}
2071
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002072TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2073 mWindow2->setWindowScale(0.5f, 0.5f);
2074
2075 // Touch Window 1
2076 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2077 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2078
2079 NotifyMotionArgs motionArgs =
2080 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2081 ADISPLAY_ID_DEFAULT, touchedPoints);
2082 mDispatcher->notifyMotion(&motionArgs);
2083 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2084
2085 // Touch Window 2
2086 int32_t actionPointerDown =
2087 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2088 touchedPoints.emplace_back(PointF{150, 150});
2089 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2090
2091 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2092 ADISPLAY_ID_DEFAULT, touchedPoints);
2093 mDispatcher->notifyMotion(&motionArgs);
2094
2095 // Consuming from window1 since it's the window that has the InputReceiver
2096 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2097}
2098
2099TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2100 mWindow2->setWindowScale(0.5f, 0.5f);
2101
2102 // Touch Window 1
2103 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2104 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2105
2106 NotifyMotionArgs motionArgs =
2107 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2108 ADISPLAY_ID_DEFAULT, touchedPoints);
2109 mDispatcher->notifyMotion(&motionArgs);
2110 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2111
2112 // Touch Window 2
2113 int32_t actionPointerDown =
2114 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2115 touchedPoints.emplace_back(PointF{150, 150});
2116 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2117
2118 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2119 ADISPLAY_ID_DEFAULT, touchedPoints);
2120 mDispatcher->notifyMotion(&motionArgs);
2121
2122 // Consuming from window1 since it's the window that has the InputReceiver
2123 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2124
2125 // Move both windows
2126 touchedPoints = {{20, 20}, {175, 175}};
2127 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2128 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2129
2130 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2131 ADISPLAY_ID_DEFAULT, touchedPoints);
2132 mDispatcher->notifyMotion(&motionArgs);
2133
2134 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2135}
2136
2137TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2138 mWindow1->setWindowScale(0.5f, 0.5f);
2139
2140 // Touch Window 1
2141 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2142 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2143
2144 NotifyMotionArgs motionArgs =
2145 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2146 ADISPLAY_ID_DEFAULT, touchedPoints);
2147 mDispatcher->notifyMotion(&motionArgs);
2148 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2149
2150 // Touch Window 2
2151 int32_t actionPointerDown =
2152 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2153 touchedPoints.emplace_back(PointF{150, 150});
2154 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2155
2156 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2157 ADISPLAY_ID_DEFAULT, touchedPoints);
2158 mDispatcher->notifyMotion(&motionArgs);
2159
2160 // Consuming from window1 since it's the window that has the InputReceiver
2161 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2162
2163 // Move both windows
2164 touchedPoints = {{20, 20}, {175, 175}};
2165 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2166 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2167
2168 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2169 ADISPLAY_ID_DEFAULT, touchedPoints);
2170 mDispatcher->notifyMotion(&motionArgs);
2171
2172 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2173}
2174
Garfield Tane84e6f92019-08-29 17:28:41 -07002175} // namespace android::inputdispatcher