blob: 270f891d366cfcde9c52d13e8884b592b3a187b0 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080020#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070021
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
23#include <linux/input.h>
chaviwd1c23182019-12-20 18:44:56 -080024#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025
Garfield Tane84e6f92019-08-29 17:28:41 -070026namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080027
28// An arbitrary time value.
29static const nsecs_t ARBITRARY_TIME = 1234;
30
31// An arbitrary device id.
32static const int32_t DEVICE_ID = 1;
33
Jeff Brownf086ddb2014-02-11 14:28:48 -080034// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080035static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080036
Michael Wrightd02c5b62014-02-10 15:10:22 -080037// An arbitrary injector pid / uid pair that has permission to inject events.
38static const int32_t INJECTOR_PID = 999;
39static const int32_t INJECTOR_UID = 1001;
40
chaviwd1c23182019-12-20 18:44:56 -080041struct PointF {
42 float x;
43 float y;
44};
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Gang Wang342c9272020-01-13 13:15:04 -050046/**
47 * Return a DOWN key event with KEYCODE_A.
48 */
49static KeyEvent getTestKeyEvent() {
50 KeyEvent event;
51
Garfield Tanfbe732e2020-01-24 11:26:14 -080052 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
53 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
54 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050055 return event;
56}
57
Michael Wrightd02c5b62014-02-10 15:10:22 -080058// --- FakeInputDispatcherPolicy ---
59
60class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
61 InputDispatcherConfiguration mConfig;
62
63protected:
64 virtual ~FakeInputDispatcherPolicy() {
65 }
66
67public:
68 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080069 }
70
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080071 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080072 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
73 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080074 }
75
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080076 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080077 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
78 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080081 void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
Michael Wrightd02c5b62014-02-10 15:10:22 -080082
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080083 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
84 ASSERT_TRUE(mConfigurationChangedTime)
85 << "Timed out waiting for configuration changed call";
86 ASSERT_EQ(*mConfigurationChangedTime, when);
87 mConfigurationChangedTime = std::nullopt;
88 }
89
90 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
91 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -080092 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080093 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
94 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
95 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
96 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
97 mLastNotifySwitch = std::nullopt;
98 }
99
chaviwfd6d3512019-03-25 13:23:49 -0700100 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800101 ASSERT_EQ(touchedToken, mOnPointerDownToken);
102 mOnPointerDownToken.clear();
103 }
104
105 void assertOnPointerDownWasNotCalled() {
106 ASSERT_TRUE(mOnPointerDownToken == nullptr)
107 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700108 }
109
Michael Wrightd02c5b62014-02-10 15:10:22 -0800110private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800111 std::unique_ptr<InputEvent> mFilteredEvent;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800112 std::optional<nsecs_t> mConfigurationChangedTime;
chaviwfd6d3512019-03-25 13:23:49 -0700113 sp<IBinder> mOnPointerDownToken;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800114 std::optional<NotifySwitchArgs> mLastNotifySwitch;
Jackal Guof9696682018-10-05 12:23:23 +0800115
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800116 virtual void notifyConfigurationChanged(nsecs_t when) override {
117 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800118 }
119
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100120 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700121 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800122 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800123 return 0;
124 }
125
Robert Carr803535b2018-08-02 16:38:15 -0700126 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800127 }
128
chaviw0c06c6e2019-01-09 13:27:07 -0800129 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700130 }
131
Michael Wrightd02c5b62014-02-10 15:10:22 -0800132 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
133 *outConfig = mConfig;
134 }
135
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800136 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800137 switch (inputEvent->getType()) {
138 case AINPUT_EVENT_TYPE_KEY: {
139 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800140 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800141 break;
142 }
143
144 case AINPUT_EVENT_TYPE_MOTION: {
145 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800146 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800147 break;
148 }
149 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800150 return true;
151 }
152
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 }
155
Charles Chen3611f1f2019-01-29 17:26:18 +0800156 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157 }
158
Robert Carr803535b2018-08-02 16:38:15 -0700159 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100160 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161 return 0;
162 }
163
Robert Carr803535b2018-08-02 16:38:15 -0700164 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100165 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166 return false;
167 }
168
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800169 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
170 uint32_t policyFlags) override {
171 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
172 * essentially a passthrough for notifySwitch.
173 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800174 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800175 }
176
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100177 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800178 }
179
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100180 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800181 return false;
182 }
Jackal Guof9696682018-10-05 12:23:23 +0800183
chaviwfd6d3512019-03-25 13:23:49 -0700184 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
185 mOnPointerDownToken = newToken;
186 }
187
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800188 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
189 int32_t displayId) {
190 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
191 ASSERT_EQ(mFilteredEvent->getType(), type);
192
193 if (type == AINPUT_EVENT_TYPE_KEY) {
194 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
195 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
196 EXPECT_EQ(keyEvent.getAction(), action);
197 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
198 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
199 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
200 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
201 EXPECT_EQ(motionEvent.getAction(), action);
202 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
203 } else {
204 FAIL() << "Unknown type: " << type;
205 }
206
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800207 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800208 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209};
210
Gang Wang342c9272020-01-13 13:15:04 -0500211// --- HmacKeyManagerTest ---
212
213class HmacKeyManagerTest : public testing::Test {
214protected:
215 HmacKeyManager mHmacKeyManager;
216};
217
218/**
219 * Ensure that separate calls to sign the same data are generating the same key.
220 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
221 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
222 * tests.
223 */
224TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
225 KeyEvent event = getTestKeyEvent();
226 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
227
228 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
229 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
230 ASSERT_EQ(hmac1, hmac2);
231}
232
233/**
234 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
235 */
236TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
237 KeyEvent event = getTestKeyEvent();
238 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
239 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
240
241 verifiedEvent.deviceId += 1;
242 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
243
244 verifiedEvent.source += 1;
245 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
246
247 verifiedEvent.eventTimeNanos += 1;
248 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
249
250 verifiedEvent.displayId += 1;
251 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
252
253 verifiedEvent.action += 1;
254 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
255
256 verifiedEvent.downTimeNanos += 1;
257 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
258
259 verifiedEvent.flags += 1;
260 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
261
262 verifiedEvent.keyCode += 1;
263 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
264
265 verifiedEvent.scanCode += 1;
266 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
267
268 verifiedEvent.metaState += 1;
269 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
270
271 verifiedEvent.repeatCount += 1;
272 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
273}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800274
275// --- InputDispatcherTest ---
276
277class InputDispatcherTest : public testing::Test {
278protected:
279 sp<FakeInputDispatcherPolicy> mFakePolicy;
280 sp<InputDispatcher> mDispatcher;
281
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700282 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283 mFakePolicy = new FakeInputDispatcherPolicy();
284 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800285 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
286 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700287 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800288 }
289
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700290 virtual void TearDown() override {
291 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800292 mFakePolicy.clear();
293 mDispatcher.clear();
294 }
295};
296
297
298TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
299 KeyEvent event;
300
301 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800302 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
303 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600304 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
305 ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800306 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800307 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
309 << "Should reject key events with undefined action.";
310
311 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800312 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
313 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600314 ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800315 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800316 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800317 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
318 << "Should reject key events with ACTION_MULTIPLE.";
319}
320
321TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
322 MotionEvent event;
323 PointerProperties pointerProperties[MAX_POINTERS + 1];
324 PointerCoords pointerCoords[MAX_POINTERS + 1];
325 for (int i = 0; i <= MAX_POINTERS; i++) {
326 pointerProperties[i].clear();
327 pointerProperties[i].id = i;
328 pointerCoords[i].clear();
329 }
330
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800331 // Some constants commonly used below
332 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
333 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
334 constexpr int32_t metaState = AMETA_NONE;
335 constexpr MotionClassification classification = MotionClassification::NONE;
336
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800338 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600339 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
340 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
341 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700342 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800343 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800344 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
346 << "Should reject motion events with undefined action.";
347
348 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800349 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700350 AMOTION_EVENT_ACTION_POINTER_DOWN |
351 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600352 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
353 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
354 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700355 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800356 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800357 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800358 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
359 << "Should reject motion events with pointer down index too large.";
360
Garfield Tanfbe732e2020-01-24 11:26:14 -0800361 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700362 AMOTION_EVENT_ACTION_POINTER_DOWN |
363 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600364 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
365 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
366 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700367 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800368 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800369 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800370 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
371 << "Should reject motion events with pointer down index too small.";
372
373 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800374 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700375 AMOTION_EVENT_ACTION_POINTER_UP |
376 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600377 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
378 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
379 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700380 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800381 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800382 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800383 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
384 << "Should reject motion events with pointer up index too large.";
385
Garfield Tanfbe732e2020-01-24 11:26:14 -0800386 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700387 AMOTION_EVENT_ACTION_POINTER_UP |
388 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600389 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
390 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
391 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700392 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800393 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800394 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800395 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
396 << "Should reject motion events with pointer up index too small.";
397
398 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800399 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
400 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
401 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
402 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
403 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700404 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800405 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800406 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800407 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
408 << "Should reject motion events with 0 pointers.";
409
Garfield Tanfbe732e2020-01-24 11:26:14 -0800410 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
411 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
412 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
413 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
414 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700415 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800416 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800417 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800418 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
419 << "Should reject motion events with more than MAX_POINTERS pointers.";
420
421 // Rejects motion events with invalid pointer ids.
422 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800423 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
424 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
425 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
426 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
427 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700428 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800429 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800430 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800431 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
432 << "Should reject motion events with pointer ids less than 0.";
433
434 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800435 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
436 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
437 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
438 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
439 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700440 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800441 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800442 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800443 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
444 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
445
446 // Rejects motion events with duplicate pointer ids.
447 pointerProperties[0].id = 1;
448 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800449 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
450 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
451 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
452 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
453 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700454 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800455 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800456 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800457 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
458 << "Should reject motion events with duplicate pointer ids.";
459}
460
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800461/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
462
463TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
464 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800465 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800466 mDispatcher->notifyConfigurationChanged(&args);
467 ASSERT_TRUE(mDispatcher->waitForIdle());
468
469 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
470}
471
472TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800473 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
474 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800475 mDispatcher->notifySwitch(&args);
476
477 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
478 args.policyFlags |= POLICY_FLAG_TRUSTED;
479 mFakePolicy->assertNotifySwitchWasCalled(args);
480}
481
Arthur Hungb92218b2018-08-14 12:00:21 +0800482// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800483static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
484static constexpr int32_t DISPATCHING_TIMEOUT = 100;
Arthur Hungb92218b2018-08-14 12:00:21 +0800485
486class FakeApplicationHandle : public InputApplicationHandle {
487public:
488 FakeApplicationHandle() {}
489 virtual ~FakeApplicationHandle() {}
490
491 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800492 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800493 return true;
494 }
495};
496
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800497class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800498public:
chaviwd1c23182019-12-20 18:44:56 -0800499 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
500 : mName(name) {
501 mConsumer = std::make_unique<InputConsumer>(clientChannel);
502 }
503
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800504 InputEvent* consume() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800505 uint32_t consumeSeq;
506 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800507
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800508 std::chrono::time_point start = std::chrono::steady_clock::now();
509 status_t status = WOULD_BLOCK;
510 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800511 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800512 &event);
513 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
514 if (elapsed > 100ms) {
515 break;
516 }
517 }
518
519 if (status == WOULD_BLOCK) {
520 // Just means there's no event available.
521 return nullptr;
522 }
523
524 if (status != OK) {
525 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
526 return nullptr;
527 }
528 if (event == nullptr) {
529 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
530 return nullptr;
531 }
532
chaviwd1c23182019-12-20 18:44:56 -0800533 status = mConsumer->sendFinishedSignal(consumeSeq, true);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800534 if (status != OK) {
535 ADD_FAILURE() << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
536 }
537 return event;
538 }
539
540 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
541 int32_t expectedFlags) {
542 InputEvent* event = consume();
543
544 ASSERT_NE(nullptr, event) << mName.c_str()
545 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800546 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800547 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
548 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800549
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800550 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800551
Tiger Huang8664f8c2018-10-11 19:14:35 +0800552 switch (expectedEventType) {
553 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800554 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
555 EXPECT_EQ(expectedAction, keyEvent.getAction());
556 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800557 break;
558 }
559 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800560 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
561 EXPECT_EQ(expectedAction, motionEvent.getAction());
562 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800563 break;
564 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100565 case AINPUT_EVENT_TYPE_FOCUS: {
566 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
567 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800568 default: {
569 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
570 }
571 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800572 }
573
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100574 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
575 InputEvent* event = consume();
576 ASSERT_NE(nullptr, event) << mName.c_str()
577 << ": consumer should have returned non-NULL event.";
578 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
579 << "Got " << inputEventTypeToString(event->getType())
580 << " event instead of FOCUS event";
581
582 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
583 << mName.c_str() << ": event displayId should always be NONE.";
584
585 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
586 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
587 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
588 }
589
chaviwd1c23182019-12-20 18:44:56 -0800590 void assertNoEvents() {
591 InputEvent* event = consume();
592 ASSERT_EQ(nullptr, event)
593 << mName.c_str()
594 << ": should not have received any events, so consume() should return NULL";
595 }
596
597 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
598
599protected:
600 std::unique_ptr<InputConsumer> mConsumer;
601 PreallocatedInputEventFactory mEventFactory;
602
603 std::string mName;
604};
605
606class FakeWindowHandle : public InputWindowHandle {
607public:
608 static const int32_t WIDTH = 600;
609 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800610
611 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
612 const sp<InputDispatcher>& dispatcher, const std::string name,
613 int32_t displayId, sp<IBinder> token = nullptr)
614 : mName(name) {
615 if (token == nullptr) {
616 sp<InputChannel> serverChannel, clientChannel;
617 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
618 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
619 dispatcher->registerInputChannel(serverChannel);
620 token = serverChannel->getConnectionToken();
621 }
622
623 inputApplicationHandle->updateInfo();
624 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
625
626 mInfo.token = token;
chaviwaf87b3e2019-10-01 16:59:28 -0700627 mInfo.id = 0;
chaviwd1c23182019-12-20 18:44:56 -0800628 mInfo.name = name;
629 mInfo.layoutParamsFlags = 0;
630 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
631 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
632 mInfo.frameLeft = 0;
633 mInfo.frameTop = 0;
634 mInfo.frameRight = WIDTH;
635 mInfo.frameBottom = HEIGHT;
636 mInfo.globalScaleFactor = 1.0;
637 mInfo.touchableRegion.clear();
638 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
639 mInfo.visible = true;
640 mInfo.canReceiveKeys = true;
641 mInfo.hasFocus = false;
642 mInfo.hasWallpaper = false;
643 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800644 mInfo.ownerPid = INJECTOR_PID;
645 mInfo.ownerUid = INJECTOR_UID;
646 mInfo.inputFeatures = 0;
647 mInfo.displayId = displayId;
648 }
649
650 virtual bool updateInfo() { return true; }
651
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100652 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800653
654 void setFrame(const Rect& frame) {
655 mInfo.frameLeft = frame.left;
656 mInfo.frameTop = frame.top;
657 mInfo.frameRight = frame.right;
658 mInfo.frameBottom = frame.bottom;
659 mInfo.touchableRegion.clear();
660 mInfo.addTouchableRegion(frame);
661 }
662
663 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
664
chaviwaf87b3e2019-10-01 16:59:28 -0700665 void setId(int32_t id) { mInfo.id = id; }
666
667 void setWindowScale(float xScale, float yScale) {
668 mInfo.windowXScale = xScale;
669 mInfo.windowYScale = yScale;
670 }
671
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800672 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
673 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
674 expectedFlags);
675 }
676
Svet Ganov5d3bc372020-01-26 23:11:07 -0800677 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
678 int32_t expectedFlags = 0) {
679 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
680 expectedFlags);
681 }
682
683 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
684 int32_t expectedFlags = 0) {
685 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
686 expectedFlags);
687 }
688
689 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
690 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800691 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
692 expectedFlags);
693 }
694
Svet Ganov5d3bc372020-01-26 23:11:07 -0800695 void consumeMotionPointerDown(int32_t pointerIdx,
696 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
697 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
698 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
699 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
700 }
701
702 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
703 int32_t expectedFlags = 0) {
704 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
705 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
706 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
707 }
708
709 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
710 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000711 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
712 expectedFlags);
713 }
714
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100715 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
716 ASSERT_NE(mInputReceiver, nullptr)
717 << "Cannot consume events from a window with no receiver";
718 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
719 }
720
chaviwd1c23182019-12-20 18:44:56 -0800721 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
722 int32_t expectedFlags) {
723 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
724 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
725 expectedFlags);
726 }
727
chaviwaf87b3e2019-10-01 16:59:28 -0700728 InputEvent* consume() {
729 if (mInputReceiver == nullptr) {
730 return nullptr;
731 }
732 return mInputReceiver->consume();
733 }
734
Arthur Hungb92218b2018-08-14 12:00:21 +0800735 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800736 ASSERT_NE(mInputReceiver, nullptr)
737 << "Call 'assertNoEvents' on a window with an InputReceiver";
738 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800739 }
740
chaviwaf87b3e2019-10-01 16:59:28 -0700741 sp<IBinder> getToken() { return mInfo.token; }
742
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100743 const std::string& getName() { return mName; }
744
chaviwd1c23182019-12-20 18:44:56 -0800745private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100746 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800747 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800748};
749
Tiger Huang721e26f2018-07-24 22:26:19 +0800750static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
751 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800752 KeyEvent event;
753 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
754
755 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
757 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
758 AMETA_NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600759 /* repeatCount */ 0, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800760
761 // Inject event until dispatch out.
762 return dispatcher->injectInputEvent(
763 &event,
764 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
765 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
766}
767
Garfield Tan00f511d2019-06-12 16:55:40 -0700768static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
769 int32_t source, int32_t displayId, int32_t x, int32_t y,
770 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
771 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800772 MotionEvent event;
773 PointerProperties pointerProperties[1];
774 PointerCoords pointerCoords[1];
775
776 pointerProperties[0].clear();
777 pointerProperties[0].id = 0;
778 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
779
780 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700781 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
782 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800783
784 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
785 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800786 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
787 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600788 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700789 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600790 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
791 /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition,
792 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700793 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800794
795 // Inject event until dispatch out.
796 return dispatcher->injectInputEvent(
797 &event,
798 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
799 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
800}
801
Garfield Tan00f511d2019-06-12 16:55:40 -0700802static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
803 int32_t displayId, int32_t x = 100, int32_t y = 200) {
804 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
805}
806
Michael Wright3a240c42019-12-10 20:53:41 +0000807static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
808 int32_t displayId, int32_t x = 100, int32_t y = 200) {
809 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
810}
811
Jackal Guof9696682018-10-05 12:23:23 +0800812static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
813 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
814 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800815 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
816 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
817 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800818
819 return args;
820}
821
chaviwd1c23182019-12-20 18:44:56 -0800822static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
823 const std::vector<PointF>& points) {
824 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700825 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
826 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
827 }
828
chaviwd1c23182019-12-20 18:44:56 -0800829 PointerProperties pointerProperties[pointerCount];
830 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800831
chaviwd1c23182019-12-20 18:44:56 -0800832 for (size_t i = 0; i < pointerCount; i++) {
833 pointerProperties[i].clear();
834 pointerProperties[i].id = i;
835 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800836
chaviwd1c23182019-12-20 18:44:56 -0800837 pointerCoords[i].clear();
838 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
839 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
840 }
Jackal Guof9696682018-10-05 12:23:23 +0800841
842 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
843 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800844 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700845 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
846 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800847 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
848 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700849 AMOTION_EVENT_INVALID_CURSOR_POSITION,
850 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800851
852 return args;
853}
854
chaviwd1c23182019-12-20 18:44:56 -0800855static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
856 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
857}
858
Arthur Hungb92218b2018-08-14 12:00:21 +0800859TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
860 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800861 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
862 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800863
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800864 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800865 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
866 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800867 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
868
869 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800870 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800871}
872
873// The foreground window should receive the first touch down event.
874TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
875 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800876 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
877 ADISPLAY_ID_DEFAULT);
878 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
879 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800880
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800881 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800882 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
883 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800884 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
885
886 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800887 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800888 windowSecond->assertNoEvents();
889}
890
891TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
892 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800893 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
894 ADISPLAY_ID_DEFAULT);
895 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
896 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800897
Arthur Hung7ab76b12019-01-09 19:17:20 +0800898 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800899 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800900
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100901 // Display should have only one focused window
902 windowSecond->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800903 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100904
905 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +0800906 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
907 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
908
909 // Focused window should receive event.
910 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800911 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800912}
913
Arthur Hung7ab76b12019-01-09 19:17:20 +0800914TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
915 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
916 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
917 ADISPLAY_ID_DEFAULT);
918 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
919 ADISPLAY_ID_DEFAULT);
920
921 // Set focused application.
922 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
923
924 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100925 windowTop->setFocus(true);
926 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800927
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800928 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100929 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800930 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
931 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
932
933 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800934 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800935 windowSecond->assertNoEvents();
936}
937
Arthur Hung3b413f22018-10-26 18:05:34 +0800938TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
939 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
940
941 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
942 ADISPLAY_ID_DEFAULT);
943 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
944 ADISPLAY_ID_DEFAULT);
945
Arthur Hung832bc4a2019-01-28 11:43:17 +0800946 // Set focused application.
947 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800948
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100949 windowTop->setFocus(true);
950 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800951 // Release channel for window is no longer valid.
952 windowTop->releaseChannel();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800953 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100954 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800955
Arthur Hung832bc4a2019-01-28 11:43:17 +0800956 // Test inject a key down, should dispatch to a valid window.
957 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
958 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800959
960 // Top window is invalid, so it should not receive any input event.
961 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800962 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800963}
964
Garfield Tan00f511d2019-06-12 16:55:40 -0700965TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
966 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
967
968 sp<FakeWindowHandle> windowLeft =
969 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
970 windowLeft->setFrame(Rect(0, 0, 600, 800));
971 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
972 sp<FakeWindowHandle> windowRight =
973 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
974 windowRight->setFrame(Rect(600, 0, 1200, 800));
975 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
976
977 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
978
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800979 mDispatcher->setInputWindows({windowLeft, windowRight}, ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700980
981 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
982 // left window. This event should be dispatched to the left window.
983 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
984 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
985 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800986 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700987 windowRight->assertNoEvents();
988}
989
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800990TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
991 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
992 sp<FakeWindowHandle> window =
993 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800995
996 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100997 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800998
999 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1000 mDispatcher->notifyKey(&keyArgs);
1001
1002 // Window should receive key down event.
1003 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1004
1005 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1006 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001007 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001008 mDispatcher->notifyDeviceReset(&args);
1009 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1010 AKEY_EVENT_FLAG_CANCELED);
1011}
1012
1013TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1014 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1015 sp<FakeWindowHandle> window =
1016 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1017
1018 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1019
1020 NotifyMotionArgs motionArgs =
1021 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1022 ADISPLAY_ID_DEFAULT);
1023 mDispatcher->notifyMotion(&motionArgs);
1024
1025 // Window should receive motion down event.
1026 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1027
1028 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1029 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001030 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001031 mDispatcher->notifyDeviceReset(&args);
1032 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1033 0 /*expectedFlags*/);
1034}
1035
Svet Ganov5d3bc372020-01-26 23:11:07 -08001036TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1037 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1038
1039 // Create a couple of windows
1040 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1041 "First Window", ADISPLAY_ID_DEFAULT);
1042 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1043 "Second Window", ADISPLAY_ID_DEFAULT);
1044
1045 // Add the windows to the dispatcher
1046 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1047
1048 // Send down to the first window
1049 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1050 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1051 mDispatcher->notifyMotion(&downMotionArgs);
1052 // Only the first window should get the down event
1053 firstWindow->consumeMotionDown();
1054 secondWindow->assertNoEvents();
1055
1056 // Transfer touch focus to the second window
1057 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1058 // The first window gets cancel and the second gets down
1059 firstWindow->consumeMotionCancel();
1060 secondWindow->consumeMotionDown();
1061
1062 // Send up event to the second window
1063 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1064 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1065 mDispatcher->notifyMotion(&upMotionArgs);
1066 // The first window gets no events and the second gets up
1067 firstWindow->assertNoEvents();
1068 secondWindow->consumeMotionUp();
1069}
1070
1071TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1072 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1073
1074 PointF touchPoint = {10, 10};
1075
1076 // Create a couple of windows
1077 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1078 "First Window", ADISPLAY_ID_DEFAULT);
1079 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1080 "Second Window", ADISPLAY_ID_DEFAULT);
1081
1082 // Add the windows to the dispatcher
1083 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1084
1085 // Send down to the first window
1086 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1087 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1088 mDispatcher->notifyMotion(&downMotionArgs);
1089 // Only the first window should get the down event
1090 firstWindow->consumeMotionDown();
1091 secondWindow->assertNoEvents();
1092
1093 // Send pointer down to the first window
1094 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1095 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1096 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1097 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1098 // Only the first window should get the pointer down event
1099 firstWindow->consumeMotionPointerDown(1);
1100 secondWindow->assertNoEvents();
1101
1102 // Transfer touch focus to the second window
1103 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1104 // The first window gets cancel and the second gets down and pointer down
1105 firstWindow->consumeMotionCancel();
1106 secondWindow->consumeMotionDown();
1107 secondWindow->consumeMotionPointerDown(1);
1108
1109 // Send pointer up to the second window
1110 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1111 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1112 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1113 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1114 // The first window gets nothing and the second gets pointer up
1115 firstWindow->assertNoEvents();
1116 secondWindow->consumeMotionPointerUp(1);
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 nothing and the second gets up
1123 firstWindow->assertNoEvents();
1124 secondWindow->consumeMotionUp();
1125}
1126
1127TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1128 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1129
1130 // Create a non touch modal window that supports split touch
1131 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1132 "First Window", ADISPLAY_ID_DEFAULT);
1133 firstWindow->setFrame(Rect(0, 0, 600, 400));
1134 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1135 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1136
1137 // Create a non touch modal window that supports split touch
1138 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1139 "Second Window", ADISPLAY_ID_DEFAULT);
1140 secondWindow->setFrame(Rect(0, 400, 600, 800));
1141 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1142 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1143
1144 // Add the windows to the dispatcher
1145 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1146
1147 PointF pointInFirst = {300, 200};
1148 PointF pointInSecond = {300, 600};
1149
1150 // Send down to the first window
1151 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1152 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1153 mDispatcher->notifyMotion(&firstDownMotionArgs);
1154 // Only the first window should get the down event
1155 firstWindow->consumeMotionDown();
1156 secondWindow->assertNoEvents();
1157
1158 // Send down to the second window
1159 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1160 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1161 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1162 mDispatcher->notifyMotion(&secondDownMotionArgs);
1163 // The first window gets a move and the second a down
1164 firstWindow->consumeMotionMove();
1165 secondWindow->consumeMotionDown();
1166
1167 // Transfer touch focus to the second window
1168 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1169 // The first window gets cancel and the new gets pointer down (it already saw down)
1170 firstWindow->consumeMotionCancel();
1171 secondWindow->consumeMotionPointerDown(1);
1172
1173 // Send pointer up to the second window
1174 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1175 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1176 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1177 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1178 // The first window gets nothing and the second gets pointer up
1179 firstWindow->assertNoEvents();
1180 secondWindow->consumeMotionPointerUp(1);
1181
1182 // Send up event to the second window
1183 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1184 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1185 mDispatcher->notifyMotion(&upMotionArgs);
1186 // The first window gets nothing and the second gets up
1187 firstWindow->assertNoEvents();
1188 secondWindow->consumeMotionUp();
1189}
1190
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001191TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1192 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1193 sp<FakeWindowHandle> window =
1194 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1195
1196 window->setFocus(true);
1197 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1198
1199 window->consumeFocusEvent(true);
1200
1201 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1202 mDispatcher->notifyKey(&keyArgs);
1203
1204 // Window should receive key down event.
1205 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1206}
1207
1208TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1209 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1210 sp<FakeWindowHandle> window =
1211 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1212
1213 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1214
1215 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1216 mDispatcher->notifyKey(&keyArgs);
1217 mDispatcher->waitForIdle();
1218
1219 window->assertNoEvents();
1220}
1221
1222// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1223TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1224 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1225 sp<FakeWindowHandle> window =
1226 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1227
1228 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1229
1230 // Send key
1231 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1232 mDispatcher->notifyKey(&keyArgs);
1233 // Send motion
1234 NotifyMotionArgs motionArgs =
1235 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1236 ADISPLAY_ID_DEFAULT);
1237 mDispatcher->notifyMotion(&motionArgs);
1238
1239 // Window should receive only the motion event
1240 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1241 window->assertNoEvents(); // Key event or focus event will not be received
1242}
1243
chaviwd1c23182019-12-20 18:44:56 -08001244class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001245public:
1246 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001247 int32_t displayId, bool isGestureMonitor = false) {
1248 sp<InputChannel> serverChannel, clientChannel;
1249 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1250 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1251 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001252 }
1253
chaviwd1c23182019-12-20 18:44:56 -08001254 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1255
1256 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1257 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1258 expectedDisplayId, expectedFlags);
1259 }
1260
1261 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1262 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1263 expectedDisplayId, expectedFlags);
1264 }
1265
1266 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1267 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1268 expectedDisplayId, expectedFlags);
1269 }
1270
1271 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1272
1273private:
1274 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001275};
1276
1277// Tests for gesture monitors
1278TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1279 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1280 sp<FakeWindowHandle> window =
1281 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1282 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1283
chaviwd1c23182019-12-20 18:44:56 -08001284 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1285 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001286
1287 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1288 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1289 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1290 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001291 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001292}
1293
1294TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1295 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1296 sp<FakeWindowHandle> window =
1297 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1298
1299 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001300 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001301
1302 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001303 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001304
chaviwd1c23182019-12-20 18:44:56 -08001305 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1306 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001307
1308 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1309 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1310 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001311 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001312}
1313
1314TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1315 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1316 sp<FakeWindowHandle> window =
1317 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1318 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1319
chaviwd1c23182019-12-20 18:44:56 -08001320 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1321 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001322
1323 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1324 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1325 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1326 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001327 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001328
1329 window->releaseChannel();
1330
chaviwd1c23182019-12-20 18:44:56 -08001331 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001332
1333 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1334 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1335 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001336 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001337}
1338
chaviw81e2bb92019-12-18 15:03:51 -08001339TEST_F(InputDispatcherTest, TestMoveEvent) {
1340 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1341 sp<FakeWindowHandle> window =
1342 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1343
1344 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1345
1346 NotifyMotionArgs motionArgs =
1347 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1348 ADISPLAY_ID_DEFAULT);
1349
1350 mDispatcher->notifyMotion(&motionArgs);
1351 // Window should receive motion down event.
1352 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1353
1354 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001355 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001356 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1357 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1358 motionArgs.pointerCoords[0].getX() - 10);
1359
1360 mDispatcher->notifyMotion(&motionArgs);
1361 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1362 0 /*expectedFlags*/);
1363}
1364
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001365/**
1366 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1367 * the device default right away. In the test scenario, we check both the default value,
1368 * and the action of enabling / disabling.
1369 */
1370TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1371 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1372 sp<FakeWindowHandle> window =
1373 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1374
1375 // Set focused application.
1376 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1377 window->setFocus(true);
1378
1379 SCOPED_TRACE("Check default value of touch mode");
1380 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1381 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1382
1383 SCOPED_TRACE("Remove the window to trigger focus loss");
1384 window->setFocus(false);
1385 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1386 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1387
1388 SCOPED_TRACE("Disable touch mode");
1389 mDispatcher->setInTouchMode(false);
1390 window->setFocus(true);
1391 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1392 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1393
1394 SCOPED_TRACE("Remove the window to trigger focus loss");
1395 window->setFocus(false);
1396 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1397 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1398
1399 SCOPED_TRACE("Enable touch mode again");
1400 mDispatcher->setInTouchMode(true);
1401 window->setFocus(true);
1402 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1403 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1404
1405 window->assertNoEvents();
1406}
1407
Gang Wange9087892020-01-07 12:17:14 -05001408TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1409 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1410 sp<FakeWindowHandle> window =
1411 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1412
1413 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1414 window->setFocus(true);
1415
1416 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1417 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1418
1419 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1420 mDispatcher->notifyKey(&keyArgs);
1421
1422 InputEvent* event = window->consume();
1423 ASSERT_NE(event, nullptr);
1424
1425 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1426 ASSERT_NE(verified, nullptr);
1427 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1428
1429 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1430 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1431 ASSERT_EQ(keyArgs.source, verified->source);
1432 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1433
1434 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1435
1436 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1437 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
1438 ASSERT_EQ(keyArgs.eventTime, verifiedKey.eventTimeNanos);
1439 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1440 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1441 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1442 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1443 ASSERT_EQ(0, verifiedKey.repeatCount);
1444}
1445
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001446/* Test InputDispatcher for MultiDisplay */
1447class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1448public:
1449 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001450 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001451 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001452
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001453 application1 = new FakeApplicationHandle();
1454 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1455 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001456
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001457 // Set focus window for primary display, but focused display would be second one.
1458 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001459 windowInPrimary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001460 mDispatcher->setInputWindows({windowInPrimary}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001461 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001462
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001463 application2 = new FakeApplicationHandle();
1464 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1465 SECOND_DISPLAY_ID);
1466 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001467 // Set focus display to second one.
1468 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1469 // Set focus window for second display.
1470 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001471 windowInSecondary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001472 mDispatcher->setInputWindows({windowInSecondary}, SECOND_DISPLAY_ID);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001473 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001474 }
1475
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001476 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001477 InputDispatcherTest::TearDown();
1478
1479 application1.clear();
1480 windowInPrimary.clear();
1481 application2.clear();
1482 windowInSecondary.clear();
1483 }
1484
1485protected:
1486 sp<FakeApplicationHandle> application1;
1487 sp<FakeWindowHandle> windowInPrimary;
1488 sp<FakeApplicationHandle> application2;
1489 sp<FakeWindowHandle> windowInSecondary;
1490};
1491
1492TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1493 // Test touch down on primary display.
1494 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1495 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001496 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001497 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001498 windowInSecondary->assertNoEvents();
1499
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001500 // Test touch down on second display.
1501 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1502 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001503 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1504 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001505 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001506}
1507
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001508TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001509 // Test inject a key down with display id specified.
1510 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1511 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001512 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001513 windowInSecondary->assertNoEvents();
1514
1515 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001516 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1517 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1518 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001519 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001520
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001521 // Remove all windows in secondary display.
1522 mDispatcher->setInputWindows({}, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001523
1524 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001525 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1526 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001527
1528 // Test inject a key down, should timeout because of no target window.
1529 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1530 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1531 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001532 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001533 windowInSecondary->assertNoEvents();
1534}
1535
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001536// Test per-display input monitors for motion event.
1537TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001538 FakeMonitorReceiver monitorInPrimary =
1539 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1540 FakeMonitorReceiver monitorInSecondary =
1541 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001542
1543 // Test touch down on primary display.
1544 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1545 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1546 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001547 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001548 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001549 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001550 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001551
1552 // Test touch down on second display.
1553 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1554 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1555 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1556 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001557 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001558 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001559 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001560
1561 // Test inject a non-pointer motion event.
1562 // If specific a display, it will dispatch to the focused window of particular display,
1563 // or it will dispatch to the focused window of focused display.
1564 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1565 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1566 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1567 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001568 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001569 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001570 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001571}
1572
1573// Test per-display input monitors for key event.
1574TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1575 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001576 FakeMonitorReceiver monitorInPrimary =
1577 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1578 FakeMonitorReceiver monitorInSecondary =
1579 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001580
1581 // Test inject a key down.
1582 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1583 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1584 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001585 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001586 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001587 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001588}
1589
Jackal Guof9696682018-10-05 12:23:23 +08001590class InputFilterTest : public InputDispatcherTest {
1591protected:
1592 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1593
1594 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1595 NotifyMotionArgs motionArgs;
1596
1597 motionArgs = generateMotionArgs(
1598 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1599 mDispatcher->notifyMotion(&motionArgs);
1600 motionArgs = generateMotionArgs(
1601 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1602 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001603 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001604 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001605 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001606 } else {
1607 mFakePolicy->assertFilterInputEventWasNotCalled();
1608 }
1609 }
1610
1611 void testNotifyKey(bool expectToBeFiltered) {
1612 NotifyKeyArgs keyArgs;
1613
1614 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1615 mDispatcher->notifyKey(&keyArgs);
1616 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1617 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001618 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001619
1620 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001621 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001622 } else {
1623 mFakePolicy->assertFilterInputEventWasNotCalled();
1624 }
1625 }
1626};
1627
1628// Test InputFilter for MotionEvent
1629TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1630 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1631 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1632 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1633
1634 // Enable InputFilter
1635 mDispatcher->setInputFilterEnabled(true);
1636 // Test touch on both primary and second display, and check if both events are filtered.
1637 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1638 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1639
1640 // Disable InputFilter
1641 mDispatcher->setInputFilterEnabled(false);
1642 // Test touch on both primary and second display, and check if both events aren't filtered.
1643 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1644 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1645}
1646
1647// Test InputFilter for KeyEvent
1648TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1649 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1650 testNotifyKey(/*expectToBeFiltered*/ false);
1651
1652 // Enable InputFilter
1653 mDispatcher->setInputFilterEnabled(true);
1654 // Send a key event, and check if it is filtered.
1655 testNotifyKey(/*expectToBeFiltered*/ true);
1656
1657 // Disable InputFilter
1658 mDispatcher->setInputFilterEnabled(false);
1659 // Send a key event, and check if it isn't filtered.
1660 testNotifyKey(/*expectToBeFiltered*/ false);
1661}
1662
chaviwfd6d3512019-03-25 13:23:49 -07001663class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001664 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001665 InputDispatcherTest::SetUp();
1666
1667 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1668 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1669 ADISPLAY_ID_DEFAULT);
1670 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1671 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1672 // window.
1673 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1674
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001675 mFocusedWindow =
1676 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1677 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1678 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1679 mFocusedWindowTouchPoint = 60;
chaviwfd6d3512019-03-25 13:23:49 -07001680
1681 // Set focused application.
1682 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001683 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001684
1685 // Expect one focus window exist in display.
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001686 mDispatcher->setInputWindows({mUnfocusedWindow, mFocusedWindow}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001687 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001688 }
1689
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001690 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001691 InputDispatcherTest::TearDown();
1692
1693 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001694 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001695 }
1696
1697protected:
1698 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001699 sp<FakeWindowHandle> mFocusedWindow;
1700 int32_t mFocusedWindowTouchPoint;
chaviwfd6d3512019-03-25 13:23:49 -07001701};
1702
1703// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1704// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1705// the onPointerDownOutsideFocus callback.
1706TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1707 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1708 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1709 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001710
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001711 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001712 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1713}
1714
1715// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1716// DOWN on the window that doesn't have focus. Ensure no window received the
1717// onPointerDownOutsideFocus callback.
1718TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1719 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1720 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1721 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001722
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001723 ASSERT_TRUE(mDispatcher->waitForIdle());
1724 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001725}
1726
1727// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1728// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1729TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1730 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1731 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001732
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001733 ASSERT_TRUE(mDispatcher->waitForIdle());
1734 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001735}
1736
1737// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1738// DOWN on the window that already has focus. Ensure no window received the
1739// onPointerDownOutsideFocus callback.
1740TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1741 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001742 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1743 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1744 mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
chaviwfd6d3512019-03-25 13:23:49 -07001745 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001746
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001747 ASSERT_TRUE(mDispatcher->waitForIdle());
1748 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001749}
1750
chaviwaf87b3e2019-10-01 16:59:28 -07001751// These tests ensures we can send touch events to a single client when there are multiple input
1752// windows that point to the same client token.
1753class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
1754 virtual void SetUp() override {
1755 InputDispatcherTest::SetUp();
1756
1757 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1758 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
1759 ADISPLAY_ID_DEFAULT);
1760 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
1761 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
1762 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1763 InputWindowInfo::FLAG_SPLIT_TOUCH);
1764 mWindow1->setId(0);
1765 mWindow1->setFrame(Rect(0, 0, 100, 100));
1766
1767 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
1768 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
1769 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1770 InputWindowInfo::FLAG_SPLIT_TOUCH);
1771 mWindow2->setId(1);
1772 mWindow2->setFrame(Rect(100, 100, 200, 200));
1773
1774 mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT);
1775 }
1776
1777protected:
1778 sp<FakeWindowHandle> mWindow1;
1779 sp<FakeWindowHandle> mWindow2;
1780
1781 // Helper function to convert the point from screen coordinates into the window's space
1782 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
1783 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
1784 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
1785 return {x, y};
1786 }
1787
1788 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
1789 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001790 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07001791 InputEvent* event = window->consume();
1792
1793 ASSERT_NE(nullptr, event) << name.c_str()
1794 << ": consumer should have returned non-NULL event.";
1795
1796 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
1797 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
1798 << " event, got " << inputEventTypeToString(event->getType()) << " event";
1799
1800 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
1801 EXPECT_EQ(expectedAction, motionEvent.getAction());
1802
1803 for (size_t i = 0; i < points.size(); i++) {
1804 float expectedX = points[i].x;
1805 float expectedY = points[i].y;
1806
1807 EXPECT_EQ(expectedX, motionEvent.getX(i))
1808 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
1809 << ", got " << motionEvent.getX(i);
1810 EXPECT_EQ(expectedY, motionEvent.getY(i))
1811 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
1812 << ", got " << motionEvent.getY(i);
1813 }
1814 }
1815};
1816
1817TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
1818 // Touch Window 1
1819 PointF touchedPoint = {10, 10};
1820 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1821
1822 NotifyMotionArgs motionArgs =
1823 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1824 ADISPLAY_ID_DEFAULT, {touchedPoint});
1825 mDispatcher->notifyMotion(&motionArgs);
1826 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1827
1828 // Release touch on Window 1
1829 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1830 ADISPLAY_ID_DEFAULT, {touchedPoint});
1831 mDispatcher->notifyMotion(&motionArgs);
1832 // consume the UP event
1833 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1834
1835 // Touch Window 2
1836 touchedPoint = {150, 150};
1837 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1838
1839 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1840 ADISPLAY_ID_DEFAULT, {touchedPoint});
1841 mDispatcher->notifyMotion(&motionArgs);
1842
1843 // Consuming from window1 since it's the window that has the InputReceiver
1844 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1845}
1846
1847TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
1848 mWindow2->setWindowScale(0.5f, 0.5f);
1849
1850 // Touch Window 1
1851 PointF touchedPoint = {10, 10};
1852 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1853
1854 NotifyMotionArgs motionArgs =
1855 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1856 ADISPLAY_ID_DEFAULT, {touchedPoint});
1857 mDispatcher->notifyMotion(&motionArgs);
1858 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1859
1860 // Release touch on Window 1
1861 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1862 ADISPLAY_ID_DEFAULT, {touchedPoint});
1863 mDispatcher->notifyMotion(&motionArgs);
1864 // consume the UP event
1865 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1866
1867 // Touch Window 2
1868 touchedPoint = {150, 150};
1869 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1870
1871 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1872 ADISPLAY_ID_DEFAULT, {touchedPoint});
1873 mDispatcher->notifyMotion(&motionArgs);
1874
1875 // Consuming from window1 since it's the window that has the InputReceiver
1876 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1877}
1878
Chavi Weingarten65f98b82020-01-16 18:56:50 +00001879TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
1880 mWindow2->setWindowScale(0.5f, 0.5f);
1881
1882 // Touch Window 1
1883 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1884 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1885
1886 NotifyMotionArgs motionArgs =
1887 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1888 ADISPLAY_ID_DEFAULT, touchedPoints);
1889 mDispatcher->notifyMotion(&motionArgs);
1890 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1891
1892 // Touch Window 2
1893 int32_t actionPointerDown =
1894 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1895 touchedPoints.emplace_back(PointF{150, 150});
1896 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1897
1898 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1899 ADISPLAY_ID_DEFAULT, touchedPoints);
1900 mDispatcher->notifyMotion(&motionArgs);
1901
1902 // Consuming from window1 since it's the window that has the InputReceiver
1903 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1904}
1905
1906TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
1907 mWindow2->setWindowScale(0.5f, 0.5f);
1908
1909 // Touch Window 1
1910 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1911 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1912
1913 NotifyMotionArgs motionArgs =
1914 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1915 ADISPLAY_ID_DEFAULT, touchedPoints);
1916 mDispatcher->notifyMotion(&motionArgs);
1917 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1918
1919 // Touch Window 2
1920 int32_t actionPointerDown =
1921 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1922 touchedPoints.emplace_back(PointF{150, 150});
1923 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1924
1925 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1926 ADISPLAY_ID_DEFAULT, touchedPoints);
1927 mDispatcher->notifyMotion(&motionArgs);
1928
1929 // Consuming from window1 since it's the window that has the InputReceiver
1930 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1931
1932 // Move both windows
1933 touchedPoints = {{20, 20}, {175, 175}};
1934 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1935 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1936
1937 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1938 ADISPLAY_ID_DEFAULT, touchedPoints);
1939 mDispatcher->notifyMotion(&motionArgs);
1940
1941 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1942}
1943
1944TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
1945 mWindow1->setWindowScale(0.5f, 0.5f);
1946
1947 // Touch Window 1
1948 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1949 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1950
1951 NotifyMotionArgs motionArgs =
1952 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1953 ADISPLAY_ID_DEFAULT, touchedPoints);
1954 mDispatcher->notifyMotion(&motionArgs);
1955 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1956
1957 // Touch Window 2
1958 int32_t actionPointerDown =
1959 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1960 touchedPoints.emplace_back(PointF{150, 150});
1961 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1962
1963 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1964 ADISPLAY_ID_DEFAULT, touchedPoints);
1965 mDispatcher->notifyMotion(&motionArgs);
1966
1967 // Consuming from window1 since it's the window that has the InputReceiver
1968 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1969
1970 // Move both windows
1971 touchedPoints = {{20, 20}, {175, 175}};
1972 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1973 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1974
1975 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1976 ADISPLAY_ID_DEFAULT, touchedPoints);
1977 mDispatcher->notifyMotion(&motionArgs);
1978
1979 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1980}
1981
Garfield Tane84e6f92019-08-29 17:28:41 -07001982} // namespace android::inputdispatcher