blob: 86c050366290e45ed3556245d99facbc6e429cb9 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan1c7bc862020-01-28 13:24:04 -080019#include <android-base/stringprintf.h>
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -070020#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -100023#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <linux/input.h>
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -100025
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <cinttypes>
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -070027#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080029#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031using android::base::StringPrintf;
32
Garfield Tane84e6f92019-08-29 17:28:41 -070033namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080034
35// An arbitrary time value.
36static const nsecs_t ARBITRARY_TIME = 1234;
37
38// An arbitrary device id.
39static const int32_t DEVICE_ID = 1;
40
Jeff Brownf086ddb2014-02-11 14:28:48 -080041// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080042static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080043
Michael Wrightd02c5b62014-02-10 15:10:22 -080044// An arbitrary injector pid / uid pair that has permission to inject events.
45static const int32_t INJECTOR_PID = 999;
46static const int32_t INJECTOR_UID = 1001;
47
chaviwd1c23182019-12-20 18:44:56 -080048struct PointF {
49 float x;
50 float y;
51};
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
Gang Wang342c9272020-01-13 13:15:04 -050053/**
54 * Return a DOWN key event with KEYCODE_A.
55 */
56static KeyEvent getTestKeyEvent() {
57 KeyEvent event;
58
Garfield Tanfbe732e2020-01-24 11:26:14 -080059 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
60 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
61 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050062 return event;
63}
64
Michael Wrightd02c5b62014-02-10 15:10:22 -080065// --- FakeInputDispatcherPolicy ---
66
67class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
68 InputDispatcherConfiguration mConfig;
69
70protected:
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -100071 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080072
73public:
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -100074 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080075
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080076 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080077 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
78 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080081 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080082 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
83 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080084 }
85
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070086 void assertFilterInputEventWasNotCalled() {
87 std::scoped_lock lock(mLock);
88 ASSERT_EQ(nullptr, mFilteredEvent);
89 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080090
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080091 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070092 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080093 ASSERT_TRUE(mConfigurationChangedTime)
94 << "Timed out waiting for configuration changed call";
95 ASSERT_EQ(*mConfigurationChangedTime, when);
96 mConfigurationChangedTime = std::nullopt;
97 }
98
99 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700100 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800101 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800102 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800103 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
104 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
105 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
106 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
107 mLastNotifySwitch = std::nullopt;
108 }
109
chaviwfd6d3512019-03-25 13:23:49 -0700110 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700111 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800112 ASSERT_EQ(touchedToken, mOnPointerDownToken);
113 mOnPointerDownToken.clear();
114 }
115
116 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700117 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800118 ASSERT_TRUE(mOnPointerDownToken == nullptr)
119 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700120 }
121
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700122 // This function must be called soon after the expected ANR timer starts,
123 // because we are also checking how much time has passed.
124 void assertNotifyAnrWasCalled(std::chrono::nanoseconds timeout,
125 const sp<InputApplicationHandle>& expectedApplication,
126 const sp<IBinder>& expectedToken) {
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700127 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData;
128 ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
129 ASSERT_EQ(expectedApplication, anrData.first);
130 ASSERT_EQ(expectedToken, anrData.second);
131 }
132
133 std::pair<sp<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
134 std::chrono::nanoseconds timeout) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700135 const std::chrono::time_point start = std::chrono::steady_clock::now();
136 std::unique_lock lock(mLock);
137 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
138 android::base::ScopedLockAssertion assumeLocked(mLock);
139
140 // If there is an ANR, Dispatcher won't be idle because there are still events
141 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
142 // before checking if ANR was called.
143 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
144 // it some time to act. 100ms seems reasonable.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700145 mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
146 return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
147 });
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700148 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700149 if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
150 ADD_FAILURE() << "Did not receive ANR callback";
151 }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700152 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
153 // the dispatcher started counting before this function was called
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700154 if (std::chrono::abs(timeout - waited) > 100ms) {
155 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
156 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
157 << "ms, but waited "
158 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
159 << "ms instead";
160 }
161 std::pair<sp<InputApplicationHandle>, sp<IBinder>> result =
162 std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
163 mAnrApplications.pop();
164 mAnrWindowTokens.pop();
165 return result;
166 }
167
168 void assertNotifyAnrWasNotCalled() {
169 std::scoped_lock lock(mLock);
170 ASSERT_TRUE(mAnrApplications.empty());
171 ASSERT_TRUE(mAnrWindowTokens.empty());
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700172 }
173
Garfield Tan1c7bc862020-01-28 13:24:04 -0800174 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
175 mConfig.keyRepeatTimeout = timeout;
176 mConfig.keyRepeatDelay = delay;
177 }
178
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700179 void setAnrTimeout(std::chrono::nanoseconds timeout) { mAnrTimeout = timeout; }
180
Michael Wrightd02c5b62014-02-10 15:10:22 -0800181private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700182 std::mutex mLock;
183 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
184 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
185 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
186 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800187
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700188 // ANR handling
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700189 std::queue<sp<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
190 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700191 std::condition_variable mNotifyAnr;
192 std::chrono::nanoseconds mAnrTimeout = 0ms;
193
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 virtual void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700195 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800196 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800197 }
198
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700199 virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& application,
200 const sp<IBinder>& windowToken, const std::string&) override {
201 std::scoped_lock lock(mLock);
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700202 mAnrApplications.push(application);
203 mAnrWindowTokens.push(windowToken);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700204 mNotifyAnr.notify_all();
205 return mAnrTimeout.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206 }
207
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700208 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700210 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700211
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700212 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213 *outConfig = mConfig;
214 }
215
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800216 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700217 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800218 switch (inputEvent->getType()) {
219 case AINPUT_EVENT_TYPE_KEY: {
220 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800221 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800222 break;
223 }
224
225 case AINPUT_EVENT_TYPE_MOTION: {
226 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800227 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800228 break;
229 }
230 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800231 return true;
232 }
233
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700234 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800235
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700236 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800237
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700238 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
239 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240 return 0;
241 }
242
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700243 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
244 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800245 return false;
246 }
247
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
249 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700250 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800251 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
252 * essentially a passthrough for notifySwitch.
253 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800254 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800255 }
256
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700257 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800258
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700259 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260 return false;
261 }
Jackal Guof9696682018-10-05 12:23:23 +0800262
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700263 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700264 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700265 mOnPointerDownToken = newToken;
266 }
267
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800268 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
269 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700270 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800271 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
272 ASSERT_EQ(mFilteredEvent->getType(), type);
273
274 if (type == AINPUT_EVENT_TYPE_KEY) {
275 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
276 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
277 EXPECT_EQ(keyEvent.getAction(), action);
278 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
279 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
280 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
281 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
282 EXPECT_EQ(motionEvent.getAction(), action);
283 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
284 } else {
285 FAIL() << "Unknown type: " << type;
286 }
287
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800288 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800289 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800290};
291
Gang Wang342c9272020-01-13 13:15:04 -0500292// --- HmacKeyManagerTest ---
293
294class HmacKeyManagerTest : public testing::Test {
295protected:
296 HmacKeyManager mHmacKeyManager;
297};
298
299/**
300 * Ensure that separate calls to sign the same data are generating the same key.
301 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
302 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
303 * tests.
304 */
305TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
306 KeyEvent event = getTestKeyEvent();
307 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
308
309 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
310 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
311 ASSERT_EQ(hmac1, hmac2);
312}
313
314/**
315 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
316 */
317TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
318 KeyEvent event = getTestKeyEvent();
319 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
320 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
321
322 verifiedEvent.deviceId += 1;
323 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
324
325 verifiedEvent.source += 1;
326 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
327
328 verifiedEvent.eventTimeNanos += 1;
329 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
330
331 verifiedEvent.displayId += 1;
332 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
333
334 verifiedEvent.action += 1;
335 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
336
337 verifiedEvent.downTimeNanos += 1;
338 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
339
340 verifiedEvent.flags += 1;
341 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
342
343 verifiedEvent.keyCode += 1;
344 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
345
346 verifiedEvent.scanCode += 1;
347 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
348
349 verifiedEvent.metaState += 1;
350 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
351
352 verifiedEvent.repeatCount += 1;
353 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
354}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800355
356// --- InputDispatcherTest ---
357
358class InputDispatcherTest : public testing::Test {
359protected:
360 sp<FakeInputDispatcherPolicy> mFakePolicy;
361 sp<InputDispatcher> mDispatcher;
362
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700363 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800364 mFakePolicy = new FakeInputDispatcherPolicy();
365 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800366 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000367 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700368 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800369 }
370
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700371 virtual void TearDown() override {
372 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800373 mFakePolicy.clear();
374 mDispatcher.clear();
375 }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700376
377 /**
378 * Used for debugging when writing the test
379 */
380 void dumpDispatcherState() {
381 std::string dump;
382 mDispatcher->dump(dump);
383 std::stringstream ss(dump);
384 std::string to;
385
386 while (std::getline(ss, to, '\n')) {
387 ALOGE("%s", to.c_str());
388 }
389 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800390};
391
Michael Wrightd02c5b62014-02-10 15:10:22 -0800392TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
393 KeyEvent event;
394
395 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800396 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
397 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600398 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
399 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700400 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
401 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
402 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800403 << "Should reject key events with undefined action.";
404
405 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800406 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
407 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600408 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700409 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
410 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
411 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800412 << "Should reject key events with ACTION_MULTIPLE.";
413}
414
415TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
416 MotionEvent event;
417 PointerProperties pointerProperties[MAX_POINTERS + 1];
418 PointerCoords pointerCoords[MAX_POINTERS + 1];
419 for (int i = 0; i <= MAX_POINTERS; i++) {
420 pointerProperties[i].clear();
421 pointerProperties[i].id = i;
422 pointerCoords[i].clear();
423 }
424
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800425 // Some constants commonly used below
426 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
427 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
428 constexpr int32_t metaState = AMETA_NONE;
429 constexpr MotionClassification classification = MotionClassification::NONE;
430
Michael Wrightd02c5b62014-02-10 15:10:22 -0800431 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800432 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600433 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
434 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
435 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700436 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700437 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
438 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
439 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800440 << "Should reject motion events with undefined action.";
441
442 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800443 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700444 AMOTION_EVENT_ACTION_POINTER_DOWN |
445 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600446 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
447 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
448 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700449 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700450 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
451 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
452 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800453 << "Should reject motion events with pointer down index too large.";
454
Garfield Tanfbe732e2020-01-24 11:26:14 -0800455 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700456 AMOTION_EVENT_ACTION_POINTER_DOWN |
457 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600458 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
459 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
460 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700461 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700462 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
463 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
464 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800465 << "Should reject motion events with pointer down index too small.";
466
467 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800468 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700469 AMOTION_EVENT_ACTION_POINTER_UP |
470 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600471 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
472 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
473 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700474 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700475 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
476 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
477 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800478 << "Should reject motion events with pointer up index too large.";
479
Garfield Tanfbe732e2020-01-24 11:26:14 -0800480 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700481 AMOTION_EVENT_ACTION_POINTER_UP |
482 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600483 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
484 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
485 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700486 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700487 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
488 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
489 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800490 << "Should reject motion events with pointer up index too small.";
491
492 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800493 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
494 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
495 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
496 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
497 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700498 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700499 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
500 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
501 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800502 << "Should reject motion events with 0 pointers.";
503
Garfield Tanfbe732e2020-01-24 11:26:14 -0800504 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
505 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
506 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
507 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
508 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700509 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700510 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
511 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
512 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800513 << "Should reject motion events with more than MAX_POINTERS pointers.";
514
515 // Rejects motion events with invalid pointer ids.
516 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800517 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
518 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
519 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
520 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
521 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700522 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700523 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
524 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
525 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800526 << "Should reject motion events with pointer ids less than 0.";
527
528 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800529 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
530 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
531 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
532 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
533 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700534 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700535 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
536 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
537 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800538 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
539
540 // Rejects motion events with duplicate pointer ids.
541 pointerProperties[0].id = 1;
542 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800543 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
544 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
545 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
546 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
547 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700548 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700549 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
550 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
551 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552 << "Should reject motion events with duplicate pointer ids.";
553}
554
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800555/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
556
557TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
558 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800559 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800560 mDispatcher->notifyConfigurationChanged(&args);
561 ASSERT_TRUE(mDispatcher->waitForIdle());
562
563 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
564}
565
566TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800567 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
568 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800569 mDispatcher->notifySwitch(&args);
570
571 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
572 args.policyFlags |= POLICY_FLAG_TRUSTED;
573 mFakePolicy->assertNotifySwitchWasCalled(args);
574}
575
Arthur Hungb92218b2018-08-14 12:00:21 +0800576// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700577static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700578static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800579
580class FakeApplicationHandle : public InputApplicationHandle {
581public:
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700582 FakeApplicationHandle() {
583 mInfo.name = "Fake Application";
584 mInfo.token = new BBinder();
585 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
586 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800587 virtual ~FakeApplicationHandle() {}
588
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000589 virtual bool updateInfo() override { return true; }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700590
591 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
592 mInfo.dispatchingTimeout = timeout.count();
593 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800594};
595
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800596class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800597public:
chaviwd1c23182019-12-20 18:44:56 -0800598 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
599 : mName(name) {
600 mConsumer = std::make_unique<InputConsumer>(clientChannel);
601 }
602
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800603 InputEvent* consume() {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700604 InputEvent* event;
605 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
606 if (!consumeSeq) {
607 return nullptr;
608 }
609 finishEvent(*consumeSeq);
610 return event;
611 }
612
613 /**
614 * Receive an event without acknowledging it.
615 * Return the sequence number that could later be used to send finished signal.
616 */
617 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800618 uint32_t consumeSeq;
619 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800620
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800621 std::chrono::time_point start = std::chrono::steady_clock::now();
622 status_t status = WOULD_BLOCK;
623 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800624 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800625 &event);
626 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
627 if (elapsed > 100ms) {
628 break;
629 }
630 }
631
632 if (status == WOULD_BLOCK) {
633 // Just means there's no event available.
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700634 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800635 }
636
637 if (status != OK) {
638 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700639 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800640 }
641 if (event == nullptr) {
642 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700643 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800644 }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700645 if (outEvent != nullptr) {
646 *outEvent = event;
647 }
648 return consumeSeq;
649 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800650
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700651 /**
652 * To be used together with "receiveEvent" to complete the consumption of an event.
653 */
654 void finishEvent(uint32_t consumeSeq) {
655 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
656 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800657 }
658
659 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
660 int32_t expectedFlags) {
661 InputEvent* event = consume();
662
663 ASSERT_NE(nullptr, event) << mName.c_str()
664 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800665 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700666 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800667 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800668
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800669 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800670
Tiger Huang8664f8c2018-10-11 19:14:35 +0800671 switch (expectedEventType) {
672 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800673 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
674 EXPECT_EQ(expectedAction, keyEvent.getAction());
675 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800676 break;
677 }
678 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800679 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
680 EXPECT_EQ(expectedAction, motionEvent.getAction());
681 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800682 break;
683 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100684 case AINPUT_EVENT_TYPE_FOCUS: {
685 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
686 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800687 default: {
688 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
689 }
690 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800691 }
692
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100693 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
694 InputEvent* event = consume();
695 ASSERT_NE(nullptr, event) << mName.c_str()
696 << ": consumer should have returned non-NULL event.";
697 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
698 << "Got " << inputEventTypeToString(event->getType())
699 << " event instead of FOCUS event";
700
701 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
702 << mName.c_str() << ": event displayId should always be NONE.";
703
704 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
705 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
706 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
707 }
708
chaviwd1c23182019-12-20 18:44:56 -0800709 void assertNoEvents() {
710 InputEvent* event = consume();
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700711 if (event == nullptr) {
712 return;
713 }
714 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
715 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
716 ADD_FAILURE() << "Received key event "
717 << KeyEvent::actionToString(keyEvent.getAction());
718 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
719 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
720 ADD_FAILURE() << "Received motion event "
721 << MotionEvent::actionToString(motionEvent.getAction());
722 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
723 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
724 ADD_FAILURE() << "Received focus event, hasFocus = "
725 << (focusEvent.getHasFocus() ? "true" : "false");
726 }
727 FAIL() << mName.c_str()
728 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800729 }
730
731 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
732
733protected:
734 std::unique_ptr<InputConsumer> mConsumer;
735 PreallocatedInputEventFactory mEventFactory;
736
737 std::string mName;
738};
739
740class FakeWindowHandle : public InputWindowHandle {
741public:
742 static const int32_t WIDTH = 600;
743 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800744
745 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
746 const sp<InputDispatcher>& dispatcher, const std::string name,
747 int32_t displayId, sp<IBinder> token = nullptr)
748 : mName(name) {
749 if (token == nullptr) {
750 sp<InputChannel> serverChannel, clientChannel;
751 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
752 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
753 dispatcher->registerInputChannel(serverChannel);
754 token = serverChannel->getConnectionToken();
755 }
756
757 inputApplicationHandle->updateInfo();
758 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
759
760 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700761 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800762 mInfo.name = name;
763 mInfo.layoutParamsFlags = 0;
764 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700765 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
chaviwd1c23182019-12-20 18:44:56 -0800766 mInfo.frameLeft = 0;
767 mInfo.frameTop = 0;
768 mInfo.frameRight = WIDTH;
769 mInfo.frameBottom = HEIGHT;
770 mInfo.globalScaleFactor = 1.0;
771 mInfo.touchableRegion.clear();
772 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
773 mInfo.visible = true;
774 mInfo.canReceiveKeys = true;
775 mInfo.hasFocus = false;
776 mInfo.hasWallpaper = false;
777 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800778 mInfo.ownerPid = INJECTOR_PID;
779 mInfo.ownerUid = INJECTOR_UID;
780 mInfo.inputFeatures = 0;
781 mInfo.displayId = displayId;
782 }
783
784 virtual bool updateInfo() { return true; }
785
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100786 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800787
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700788 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
789 mInfo.dispatchingTimeout = timeout.count();
790 }
791
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700792 void setPaused(bool paused) { mInfo.paused = paused; }
793
chaviwd1c23182019-12-20 18:44:56 -0800794 void setFrame(const Rect& frame) {
795 mInfo.frameLeft = frame.left;
796 mInfo.frameTop = frame.top;
797 mInfo.frameRight = frame.right;
798 mInfo.frameBottom = frame.bottom;
799 mInfo.touchableRegion.clear();
800 mInfo.addTouchableRegion(frame);
801 }
802
803 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
804
chaviwaf87b3e2019-10-01 16:59:28 -0700805 void setWindowScale(float xScale, float yScale) {
806 mInfo.windowXScale = xScale;
807 mInfo.windowYScale = yScale;
808 }
809
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800810 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
811 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
812 expectedFlags);
813 }
814
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700815 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
816 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
817 }
818
Svet Ganov5d3bc372020-01-26 23:11:07 -0800819 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000820 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800821 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
822 expectedFlags);
823 }
824
825 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000826 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800827 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
828 expectedFlags);
829 }
830
831 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000832 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800833 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
834 expectedFlags);
835 }
836
Svet Ganov5d3bc372020-01-26 23:11:07 -0800837 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000838 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
839 int32_t expectedFlags = 0) {
840 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
841 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800842 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
843 }
844
845 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000846 int32_t expectedFlags = 0) {
847 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
848 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800849 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
850 }
851
852 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000853 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000854 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
855 expectedFlags);
856 }
857
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100858 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
859 ASSERT_NE(mInputReceiver, nullptr)
860 << "Cannot consume events from a window with no receiver";
861 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
862 }
863
chaviwd1c23182019-12-20 18:44:56 -0800864 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
865 int32_t expectedFlags) {
866 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
867 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
868 expectedFlags);
869 }
870
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700871 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700872 if (mInputReceiver == nullptr) {
873 ADD_FAILURE() << "Invalid receive event on window with no receiver";
874 return std::nullopt;
875 }
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700876 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700877 }
878
879 void finishEvent(uint32_t sequenceNum) {
880 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
881 mInputReceiver->finishEvent(sequenceNum);
882 }
883
chaviwaf87b3e2019-10-01 16:59:28 -0700884 InputEvent* consume() {
885 if (mInputReceiver == nullptr) {
886 return nullptr;
887 }
888 return mInputReceiver->consume();
889 }
890
Arthur Hungb92218b2018-08-14 12:00:21 +0800891 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800892 ASSERT_NE(mInputReceiver, nullptr)
893 << "Call 'assertNoEvents' on a window with an InputReceiver";
894 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800895 }
896
chaviwaf87b3e2019-10-01 16:59:28 -0700897 sp<IBinder> getToken() { return mInfo.token; }
898
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100899 const std::string& getName() { return mName; }
900
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -1000901 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
902 mInfo.ownerPid = ownerPid;
903 mInfo.ownerUid = ownerUid;
904 }
905
chaviwd1c23182019-12-20 18:44:56 -0800906private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100907 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800908 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700909 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800910};
911
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700912std::atomic<int32_t> FakeWindowHandle::sId{1};
913
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700914static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700915 int32_t displayId = ADISPLAY_ID_NONE,
916 int32_t syncMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
917 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800918 KeyEvent event;
919 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
920
921 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800922 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700923 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
924 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800925
926 // Inject event until dispatch out.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700927 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
928 injectionTimeout,
929 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800930}
931
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700932static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
933 int32_t displayId = ADISPLAY_ID_NONE) {
934 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
935}
936
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700937static int32_t injectKeyUp(const sp<InputDispatcher>& dispatcher,
938 int32_t displayId = ADISPLAY_ID_NONE) {
939 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
940}
941
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700942static int32_t injectMotionEvent(
943 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
944 const PointF& position,
945 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700946 AMOTION_EVENT_INVALID_CURSOR_POSITION},
947 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
948 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
949 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800950 MotionEvent event;
951 PointerProperties pointerProperties[1];
952 PointerCoords pointerCoords[1];
953
954 pointerProperties[0].clear();
955 pointerProperties[0].id = 0;
956 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
957
958 pointerCoords[0].clear();
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700959 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
960 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800961
Arthur Hungb92218b2018-08-14 12:00:21 +0800962 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800963 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
964 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600965 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700966 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600967 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700968 /* xPrecision */ 0, /* yPrecision */ 0, cursorPosition.x, cursorPosition.y,
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700969 eventTime, eventTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700970 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800971
972 // Inject event until dispatch out.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700973 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
974 injectionTimeout,
975 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800976}
977
Garfield Tan00f511d2019-06-12 16:55:40 -0700978static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700979 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700980 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700981}
982
Michael Wright3a240c42019-12-10 20:53:41 +0000983static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700984 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700985 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000986}
987
Jackal Guof9696682018-10-05 12:23:23 +0800988static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
989 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
990 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800991 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
992 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
993 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800994
995 return args;
996}
997
chaviwd1c23182019-12-20 18:44:56 -0800998static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
999 const std::vector<PointF>& points) {
1000 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001001 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1002 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1003 }
1004
chaviwd1c23182019-12-20 18:44:56 -08001005 PointerProperties pointerProperties[pointerCount];
1006 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001007
chaviwd1c23182019-12-20 18:44:56 -08001008 for (size_t i = 0; i < pointerCount; i++) {
1009 pointerProperties[i].clear();
1010 pointerProperties[i].id = i;
1011 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001012
chaviwd1c23182019-12-20 18:44:56 -08001013 pointerCoords[i].clear();
1014 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1015 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1016 }
Jackal Guof9696682018-10-05 12:23:23 +08001017
1018 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1019 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001020 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001021 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1022 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001023 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1024 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001025 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1026 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001027
1028 return args;
1029}
1030
chaviwd1c23182019-12-20 18:44:56 -08001031static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1032 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1033}
1034
Arthur Hungb92218b2018-08-14 12:00:21 +08001035TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
1036 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001037 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1038 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001039
Arthur Hung72d8dc32020-03-28 00:48:39 +00001040 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001041 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1042 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001043 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1044
1045 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001046 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001047}
1048
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001049/**
1050 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1051 * To ensure that window receives only events that were directly inside of it, add
1052 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1053 * when finding touched windows.
1054 * This test serves as a sanity check for the next test, where setInputWindows is
1055 * called twice.
1056 */
1057TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
1058 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1059 sp<FakeWindowHandle> window =
1060 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1061 window->setFrame(Rect(0, 0, 100, 100));
1062 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1063
1064 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1065 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1066 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1067 {50, 50}))
1068 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1069
1070 // Window should receive motion event.
1071 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1072}
1073
1074/**
1075 * Calling setInputWindows twice, with the same info, should not cause any issues.
1076 * To ensure that window receives only events that were directly inside of it, add
1077 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1078 * when finding touched windows.
1079 */
1080TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
1081 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1082 sp<FakeWindowHandle> window =
1083 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1084 window->setFrame(Rect(0, 0, 100, 100));
1085 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1086
1087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1089 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1090 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1091 {50, 50}))
1092 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1093
1094 // Window should receive motion event.
1095 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1096}
1097
Arthur Hungb92218b2018-08-14 12:00:21 +08001098// The foreground window should receive the first touch down event.
1099TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
1100 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001101 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1102 ADISPLAY_ID_DEFAULT);
1103 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1104 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001105
Arthur Hung72d8dc32020-03-28 00:48:39 +00001106 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001107 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1108 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001109 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1110
1111 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001112 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001113 windowSecond->assertNoEvents();
1114}
1115
1116TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
1117 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001118 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1119 ADISPLAY_ID_DEFAULT);
1120 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1121 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001122
Arthur Hung7ab76b12019-01-09 19:17:20 +08001123 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001124 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001125
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001126 // Display should have only one focused window
1127 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001128 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001129
1130 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001131 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1132 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1133
1134 // Focused window should receive event.
1135 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001136 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001137}
1138
Arthur Hung7ab76b12019-01-09 19:17:20 +08001139TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
1140 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1141 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1142 ADISPLAY_ID_DEFAULT);
1143 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1144 ADISPLAY_ID_DEFAULT);
1145
1146 // Set focused application.
1147 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1148
1149 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001150 windowTop->setFocus(true);
1151 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001152
Arthur Hung72d8dc32020-03-28 00:48:39 +00001153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001154 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001155 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1156 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1157
1158 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001159 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001160 windowSecond->assertNoEvents();
1161}
1162
Arthur Hung3b413f22018-10-26 18:05:34 +08001163TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1164 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1165
1166 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1167 ADISPLAY_ID_DEFAULT);
1168 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1169 ADISPLAY_ID_DEFAULT);
1170
Arthur Hung832bc4a2019-01-28 11:43:17 +08001171 // Set focused application.
1172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001173
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001174 windowTop->setFocus(true);
1175 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001176 // Release channel for window is no longer valid.
1177 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001178 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001179 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001180
Arthur Hung832bc4a2019-01-28 11:43:17 +08001181 // Test inject a key down, should dispatch to a valid window.
1182 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1183 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001184
1185 // Top window is invalid, so it should not receive any input event.
1186 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001187 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001188}
1189
Garfield Tan00f511d2019-06-12 16:55:40 -07001190TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1191 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1192
1193 sp<FakeWindowHandle> windowLeft =
1194 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1195 windowLeft->setFrame(Rect(0, 0, 600, 800));
1196 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1197 sp<FakeWindowHandle> windowRight =
1198 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1199 windowRight->setFrame(Rect(600, 0, 1200, 800));
1200 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1201
1202 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1203
Arthur Hung72d8dc32020-03-28 00:48:39 +00001204 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001205
1206 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1207 // left window. This event should be dispatched to the left window.
1208 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1209 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07001210 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001211 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001212 windowRight->assertNoEvents();
1213}
1214
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001215TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1216 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1217 sp<FakeWindowHandle> window =
1218 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001219 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001220
Arthur Hung72d8dc32020-03-28 00:48:39 +00001221 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001222 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001223
1224 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1225 mDispatcher->notifyKey(&keyArgs);
1226
1227 // Window should receive key down event.
1228 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1229
1230 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1231 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001232 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001233 mDispatcher->notifyDeviceReset(&args);
1234 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1235 AKEY_EVENT_FLAG_CANCELED);
1236}
1237
1238TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1239 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1240 sp<FakeWindowHandle> window =
1241 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1242
Arthur Hung72d8dc32020-03-28 00:48:39 +00001243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001244
1245 NotifyMotionArgs motionArgs =
1246 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1247 ADISPLAY_ID_DEFAULT);
1248 mDispatcher->notifyMotion(&motionArgs);
1249
1250 // Window should receive motion down event.
1251 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1252
1253 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1254 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001255 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001256 mDispatcher->notifyDeviceReset(&args);
1257 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1258 0 /*expectedFlags*/);
1259}
1260
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1262 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1263
1264 // Create a couple of windows
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001265 sp<FakeWindowHandle> firstWindow =
1266 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1267 sp<FakeWindowHandle> secondWindow =
1268 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001269
1270 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001271 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001272
1273 // Send down to the first window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001274 NotifyMotionArgs downMotionArgs =
1275 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1276 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001277 mDispatcher->notifyMotion(&downMotionArgs);
1278 // Only the first window should get the down event
1279 firstWindow->consumeMotionDown();
1280 secondWindow->assertNoEvents();
1281
1282 // Transfer touch focus to the second window
1283 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1284 // The first window gets cancel and the second gets down
1285 firstWindow->consumeMotionCancel();
1286 secondWindow->consumeMotionDown();
1287
1288 // Send up event to the second window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001289 NotifyMotionArgs upMotionArgs =
1290 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1291 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001292 mDispatcher->notifyMotion(&upMotionArgs);
1293 // The first window gets no events and the second gets up
1294 firstWindow->assertNoEvents();
1295 secondWindow->consumeMotionUp();
1296}
1297
1298TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1299 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1300
1301 PointF touchPoint = {10, 10};
1302
1303 // Create a couple of windows
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001304 sp<FakeWindowHandle> firstWindow =
1305 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1306 sp<FakeWindowHandle> secondWindow =
1307 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001308
1309 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001310 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001311
1312 // Send down to the first window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001313 NotifyMotionArgs downMotionArgs =
1314 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1315 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001316 mDispatcher->notifyMotion(&downMotionArgs);
1317 // Only the first window should get the down event
1318 firstWindow->consumeMotionDown();
1319 secondWindow->assertNoEvents();
1320
1321 // Send pointer down to the first window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001322 NotifyMotionArgs pointerDownMotionArgs =
1323 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1324 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1325 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1326 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001327 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1328 // Only the first window should get the pointer down event
1329 firstWindow->consumeMotionPointerDown(1);
1330 secondWindow->assertNoEvents();
1331
1332 // Transfer touch focus to the second window
1333 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1334 // The first window gets cancel and the second gets down and pointer down
1335 firstWindow->consumeMotionCancel();
1336 secondWindow->consumeMotionDown();
1337 secondWindow->consumeMotionPointerDown(1);
1338
1339 // Send pointer up to the second window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001340 NotifyMotionArgs pointerUpMotionArgs =
1341 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1342 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1343 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1344 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001345 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1346 // The first window gets nothing and the second gets pointer up
1347 firstWindow->assertNoEvents();
1348 secondWindow->consumeMotionPointerUp(1);
1349
1350 // Send up event to the second window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001351 NotifyMotionArgs upMotionArgs =
1352 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1353 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001354 mDispatcher->notifyMotion(&upMotionArgs);
1355 // The first window gets nothing and the second gets up
1356 firstWindow->assertNoEvents();
1357 secondWindow->consumeMotionUp();
1358}
1359
1360TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1361 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1362
1363 // Create a non touch modal window that supports split touch
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001364 sp<FakeWindowHandle> firstWindow =
1365 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001366 firstWindow->setFrame(Rect(0, 0, 600, 400));
1367 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1368 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1369
1370 // Create a non touch modal window that supports split touch
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001371 sp<FakeWindowHandle> secondWindow =
1372 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001373 secondWindow->setFrame(Rect(0, 400, 600, 800));
1374 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1375 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1376
1377 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001378 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001379
1380 PointF pointInFirst = {300, 200};
1381 PointF pointInSecond = {300, 600};
1382
1383 // Send down to the first window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001384 NotifyMotionArgs firstDownMotionArgs =
1385 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1386 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001387 mDispatcher->notifyMotion(&firstDownMotionArgs);
1388 // Only the first window should get the down event
1389 firstWindow->consumeMotionDown();
1390 secondWindow->assertNoEvents();
1391
1392 // Send down to the second window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001393 NotifyMotionArgs secondDownMotionArgs =
1394 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1395 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1396 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1397 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001398 mDispatcher->notifyMotion(&secondDownMotionArgs);
1399 // The first window gets a move and the second a down
1400 firstWindow->consumeMotionMove();
1401 secondWindow->consumeMotionDown();
1402
1403 // Transfer touch focus to the second window
1404 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1405 // The first window gets cancel and the new gets pointer down (it already saw down)
1406 firstWindow->consumeMotionCancel();
1407 secondWindow->consumeMotionPointerDown(1);
1408
1409 // Send pointer up to the second window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001410 NotifyMotionArgs pointerUpMotionArgs =
1411 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1412 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1413 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1414 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001415 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1416 // The first window gets nothing and the second gets pointer up
1417 firstWindow->assertNoEvents();
1418 secondWindow->consumeMotionPointerUp(1);
1419
1420 // Send up event to the second window
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001421 NotifyMotionArgs upMotionArgs =
1422 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1423 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001424 mDispatcher->notifyMotion(&upMotionArgs);
1425 // The first window gets nothing and the second gets up
1426 firstWindow->assertNoEvents();
1427 secondWindow->consumeMotionUp();
1428}
1429
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001430TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1431 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1432 sp<FakeWindowHandle> window =
1433 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1434
1435 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001437
1438 window->consumeFocusEvent(true);
1439
1440 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1441 mDispatcher->notifyKey(&keyArgs);
1442
1443 // Window should receive key down event.
1444 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1445}
1446
1447TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1448 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1449 sp<FakeWindowHandle> window =
1450 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1451
Arthur Hung72d8dc32020-03-28 00:48:39 +00001452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001453
1454 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1455 mDispatcher->notifyKey(&keyArgs);
1456 mDispatcher->waitForIdle();
1457
1458 window->assertNoEvents();
1459}
1460
1461// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1462TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1463 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1464 sp<FakeWindowHandle> window =
1465 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1466
Arthur Hung72d8dc32020-03-28 00:48:39 +00001467 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001468
1469 // Send key
1470 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1471 mDispatcher->notifyKey(&keyArgs);
1472 // Send motion
1473 NotifyMotionArgs motionArgs =
1474 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1475 ADISPLAY_ID_DEFAULT);
1476 mDispatcher->notifyMotion(&motionArgs);
1477
1478 // Window should receive only the motion event
1479 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1480 window->assertNoEvents(); // Key event or focus event will not be received
1481}
1482
chaviwd1c23182019-12-20 18:44:56 -08001483class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001484public:
1485 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001486 int32_t displayId, bool isGestureMonitor = false) {
1487 sp<InputChannel> serverChannel, clientChannel;
1488 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1489 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1490 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001491 }
1492
chaviwd1c23182019-12-20 18:44:56 -08001493 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1494
1495 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1496 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1497 expectedDisplayId, expectedFlags);
1498 }
1499
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07001500 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1501
1502 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1503
chaviwd1c23182019-12-20 18:44:56 -08001504 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1505 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1506 expectedDisplayId, expectedFlags);
1507 }
1508
1509 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1510 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1511 expectedDisplayId, expectedFlags);
1512 }
1513
1514 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1515
1516private:
1517 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001518};
1519
1520// Tests for gesture monitors
1521TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1522 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1523 sp<FakeWindowHandle> window =
1524 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001526
chaviwd1c23182019-12-20 18:44:56 -08001527 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1528 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001529
1530 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1531 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1532 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1533 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001534 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001535}
1536
1537TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1538 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1539 sp<FakeWindowHandle> window =
1540 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1541
1542 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001543 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001544
Arthur Hung72d8dc32020-03-28 00:48:39 +00001545 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001546 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001547
chaviwd1c23182019-12-20 18:44:56 -08001548 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1549 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001550
1551 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1552 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1553 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001554 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001555}
1556
1557TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1558 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1559 sp<FakeWindowHandle> window =
1560 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001562
chaviwd1c23182019-12-20 18:44:56 -08001563 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1564 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001565
1566 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1567 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1568 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1569 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001570 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001571
1572 window->releaseChannel();
1573
chaviwd1c23182019-12-20 18:44:56 -08001574 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001575
1576 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1577 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1578 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001579 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001580}
1581
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07001582TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1583 FakeMonitorReceiver monitor =
1584 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1585 true /*isGestureMonitor*/);
1586
1587 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1588 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1589 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1590 ASSERT_TRUE(consumeSeq);
1591
1592 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1593 monitor.finishEvent(*consumeSeq);
1594 ASSERT_TRUE(mDispatcher->waitForIdle());
1595}
1596
chaviw81e2bb92019-12-18 15:03:51 -08001597TEST_F(InputDispatcherTest, TestMoveEvent) {
1598 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1599 sp<FakeWindowHandle> window =
1600 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1601
Arthur Hung72d8dc32020-03-28 00:48:39 +00001602 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001603
1604 NotifyMotionArgs motionArgs =
1605 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1606 ADISPLAY_ID_DEFAULT);
1607
1608 mDispatcher->notifyMotion(&motionArgs);
1609 // Window should receive motion down event.
1610 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1611
1612 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001613 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001614 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1615 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1616 motionArgs.pointerCoords[0].getX() - 10);
1617
1618 mDispatcher->notifyMotion(&motionArgs);
1619 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1620 0 /*expectedFlags*/);
1621}
1622
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001623/**
1624 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1625 * the device default right away. In the test scenario, we check both the default value,
1626 * and the action of enabling / disabling.
1627 */
1628TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1629 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1630 sp<FakeWindowHandle> window =
1631 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1632
1633 // Set focused application.
1634 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1635 window->setFocus(true);
1636
1637 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001639 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1640
1641 SCOPED_TRACE("Remove the window to trigger focus loss");
1642 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001643 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001644 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1645
1646 SCOPED_TRACE("Disable touch mode");
1647 mDispatcher->setInTouchMode(false);
1648 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001649 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001650 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1651
1652 SCOPED_TRACE("Remove the window to trigger focus loss");
1653 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001655 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1656
1657 SCOPED_TRACE("Enable touch mode again");
1658 mDispatcher->setInTouchMode(true);
1659 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001660 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001661 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1662
1663 window->assertNoEvents();
1664}
1665
Gang Wange9087892020-01-07 12:17:14 -05001666TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1667 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1668 sp<FakeWindowHandle> window =
1669 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1670
1671 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1672 window->setFocus(true);
1673
Arthur Hung72d8dc32020-03-28 00:48:39 +00001674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001675 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1676
1677 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1678 mDispatcher->notifyKey(&keyArgs);
1679
1680 InputEvent* event = window->consume();
1681 ASSERT_NE(event, nullptr);
1682
1683 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1684 ASSERT_NE(verified, nullptr);
1685 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1686
1687 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1688 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1689 ASSERT_EQ(keyArgs.source, verified->source);
1690 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1691
1692 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1693
1694 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1695 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001696 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1697 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1698 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1699 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1700 ASSERT_EQ(0, verifiedKey.repeatCount);
1701}
1702
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001703TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1704 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1705 sp<FakeWindowHandle> window =
1706 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1707
1708 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1709
Arthur Hung72d8dc32020-03-28 00:48:39 +00001710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001711
1712 NotifyMotionArgs motionArgs =
1713 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1714 ADISPLAY_ID_DEFAULT);
1715 mDispatcher->notifyMotion(&motionArgs);
1716
1717 InputEvent* event = window->consume();
1718 ASSERT_NE(event, nullptr);
1719
1720 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1721 ASSERT_NE(verified, nullptr);
1722 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1723
1724 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1725 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1726 EXPECT_EQ(motionArgs.source, verified->source);
1727 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1728
1729 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1730
1731 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1732 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1733 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1734 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1735 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1736 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1737 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1738}
1739
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10001740/**
1741 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
1742 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
1743 * of the 'slipperyEnterWindow'.
1744 *
1745 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
1746 * a way so that the touched location is no longer covered by the top window.
1747 *
1748 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
1749 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
1750 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
1751 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
1752 * with ACTION_DOWN).
1753 * Thus, the touch has been transferred from the top window into the bottom window, because the top
1754 * window moved itself away from the touched location and had Flag::SLIPPERY.
1755 *
1756 * Even though the top window moved away from the touched location, it is still obscuring the bottom
1757 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
1758 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
1759 *
1760 * In this test, we ensure that the event received by the bottom window has
1761 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
1762 */
1763TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
1764 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
1765 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
1766
1767 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1768 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1769
1770 sp<FakeWindowHandle> slipperyExitWindow =
1771 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1772 slipperyExitWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1773 InputWindowInfo::FLAG_SLIPPERY);
1774 // Make sure this one overlaps the bottom window
1775 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
1776 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
1777 // one. Windows with the same owner are not considered to be occluding each other.
1778 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
1779
1780 sp<FakeWindowHandle> slipperyEnterWindow =
1781 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1782 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
1783
1784 mDispatcher->setInputWindows(
1785 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
1786
1787 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
1788 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1789 ADISPLAY_ID_DEFAULT, {{50, 50}});
1790 mDispatcher->notifyMotion(&args);
1791 slipperyExitWindow->consumeMotionDown();
1792 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
1793 mDispatcher->setInputWindows(
1794 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
1795
1796 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1797 ADISPLAY_ID_DEFAULT, {{51, 51}});
1798 mDispatcher->notifyMotion(&args);
1799
1800 slipperyExitWindow->consumeMotionCancel();
1801
1802 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
1803 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
1804}
1805
Garfield Tan1c7bc862020-01-28 13:24:04 -08001806class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
1807protected:
1808 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
1809 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
1810
1811 sp<FakeApplicationHandle> mApp;
1812 sp<FakeWindowHandle> mWindow;
1813
1814 virtual void SetUp() override {
1815 mFakePolicy = new FakeInputDispatcherPolicy();
1816 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
1817 mDispatcher = new InputDispatcher(mFakePolicy);
1818 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
1819 ASSERT_EQ(OK, mDispatcher->start());
1820
1821 setUpWindow();
1822 }
1823
1824 void setUpWindow() {
1825 mApp = new FakeApplicationHandle();
1826 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1827
1828 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08001830
1831 mWindow->consumeFocusEvent(true);
1832 }
1833
1834 void sendAndConsumeKeyDown() {
1835 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1836 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
1837 mDispatcher->notifyKey(&keyArgs);
1838
1839 // Window should receive key down event.
1840 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1841 }
1842
1843 void expectKeyRepeatOnce(int32_t repeatCount) {
1844 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
1845 InputEvent* repeatEvent = mWindow->consume();
1846 ASSERT_NE(nullptr, repeatEvent);
1847
1848 uint32_t eventType = repeatEvent->getType();
1849 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
1850
1851 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
1852 uint32_t eventAction = repeatKeyEvent->getAction();
1853 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
1854 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
1855 }
1856
1857 void sendAndConsumeKeyUp() {
1858 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
1859 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
1860 mDispatcher->notifyKey(&keyArgs);
1861
1862 // Window should receive key down event.
1863 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1864 0 /*expectedFlags*/);
1865 }
1866};
1867
1868TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
1869 sendAndConsumeKeyDown();
1870 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1871 expectKeyRepeatOnce(repeatCount);
1872 }
1873}
1874
1875TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
1876 sendAndConsumeKeyDown();
1877 expectKeyRepeatOnce(1 /*repeatCount*/);
1878 sendAndConsumeKeyUp();
1879 mWindow->assertNoEvents();
1880}
1881
1882TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
1883 sendAndConsumeKeyDown();
1884 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1885 InputEvent* repeatEvent = mWindow->consume();
1886 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1887 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
1888 IdGenerator::getSource(repeatEvent->getId()));
1889 }
1890}
1891
1892TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
1893 sendAndConsumeKeyDown();
1894
1895 std::unordered_set<int32_t> idSet;
1896 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1897 InputEvent* repeatEvent = mWindow->consume();
1898 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1899 int32_t id = repeatEvent->getId();
1900 EXPECT_EQ(idSet.end(), idSet.find(id));
1901 idSet.insert(id);
1902 }
1903}
1904
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001905/* Test InputDispatcher for MultiDisplay */
1906class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1907public:
1908 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001909 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001910 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001911
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001912 application1 = new FakeApplicationHandle();
1913 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1914 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001915
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001916 // Set focus window for primary display, but focused display would be second one.
1917 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001918 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001920 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001921
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001922 application2 = new FakeApplicationHandle();
1923 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1924 SECOND_DISPLAY_ID);
1925 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001926 // Set focus display to second one.
1927 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1928 // Set focus window for second display.
1929 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001930 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001931 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001932 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001933 }
1934
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001935 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001936 InputDispatcherTest::TearDown();
1937
1938 application1.clear();
1939 windowInPrimary.clear();
1940 application2.clear();
1941 windowInSecondary.clear();
1942 }
1943
1944protected:
1945 sp<FakeApplicationHandle> application1;
1946 sp<FakeWindowHandle> windowInPrimary;
1947 sp<FakeApplicationHandle> application2;
1948 sp<FakeWindowHandle> windowInSecondary;
1949};
1950
1951TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1952 // Test touch down on primary display.
1953 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1954 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001955 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001956 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001957 windowInSecondary->assertNoEvents();
1958
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001959 // Test touch down on second display.
1960 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1961 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001962 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1963 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001964 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001965}
1966
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001967TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001968 // Test inject a key down with display id specified.
1969 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1970 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001971 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001972 windowInSecondary->assertNoEvents();
1973
1974 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001975 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1976 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1977 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001978 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001979
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001980 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001981 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08001982
1983 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001984 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1985 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001986
1987 // Test inject a key down, should timeout because of no target window.
1988 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1989 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1990 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001991 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001992 windowInSecondary->assertNoEvents();
1993}
1994
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001995// Test per-display input monitors for motion event.
1996TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001997 FakeMonitorReceiver monitorInPrimary =
1998 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1999 FakeMonitorReceiver monitorInSecondary =
2000 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002001
2002 // Test touch down on primary display.
2003 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2004 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2005 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002006 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002007 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002008 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002009 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002010
2011 // Test touch down on second display.
2012 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2013 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2014 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2015 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002016 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002017 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002018 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002019
2020 // Test inject a non-pointer motion event.
2021 // If specific a display, it will dispatch to the focused window of particular display,
2022 // or it will dispatch to the focused window of focused display.
2023 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2024 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2025 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2026 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002027 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002028 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002029 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002030}
2031
2032// Test per-display input monitors for key event.
2033TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10002034 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002035 FakeMonitorReceiver monitorInPrimary =
2036 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2037 FakeMonitorReceiver monitorInSecondary =
2038 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002039
2040 // Test inject a key down.
2041 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2042 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2043 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002044 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002045 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002046 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002047}
2048
Jackal Guof9696682018-10-05 12:23:23 +08002049class InputFilterTest : public InputDispatcherTest {
2050protected:
2051 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2052
2053 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2054 NotifyMotionArgs motionArgs;
2055
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10002056 motionArgs =
2057 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002058 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakoud8c6ef22020-12-09 08:07:46 -10002059 motionArgs =
2060 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002061 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002062 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002063 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002064 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002065 } else {
2066 mFakePolicy->assertFilterInputEventWasNotCalled();
2067 }
2068 }
2069
2070 void testNotifyKey(bool expectToBeFiltered) {
2071 NotifyKeyArgs keyArgs;
2072
2073 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2074 mDispatcher->notifyKey(&keyArgs);
2075 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2076 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002077 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002078
2079 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002080 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002081 } else {
2082 mFakePolicy->assertFilterInputEventWasNotCalled();
2083 }
2084 }
2085};
2086
2087// Test InputFilter for MotionEvent
2088TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2089 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2090 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2091 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2092
2093 // Enable InputFilter
2094 mDispatcher->setInputFilterEnabled(true);
2095 // Test touch on both primary and second display, and check if both events are filtered.
2096 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2097 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2098
2099 // Disable InputFilter
2100 mDispatcher->setInputFilterEnabled(false);
2101 // Test touch on both primary and second display, and check if both events aren't filtered.
2102 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2103 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2104}
2105
2106// Test InputFilter for KeyEvent
2107TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2108 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2109 testNotifyKey(/*expectToBeFiltered*/ false);
2110
2111 // Enable InputFilter
2112 mDispatcher->setInputFilterEnabled(true);
2113 // Send a key event, and check if it is filtered.
2114 testNotifyKey(/*expectToBeFiltered*/ true);
2115
2116 // Disable InputFilter
2117 mDispatcher->setInputFilterEnabled(false);
2118 // Send a key event, and check if it isn't filtered.
2119 testNotifyKey(/*expectToBeFiltered*/ false);
2120}
2121
chaviwfd6d3512019-03-25 13:23:49 -07002122class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002123 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002124 InputDispatcherTest::SetUp();
2125
2126 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2127 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2128 ADISPLAY_ID_DEFAULT);
2129 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2130 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2131 // window.
2132 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2133
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002134 mFocusedWindow =
2135 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2136 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
2137 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002138
2139 // Set focused application.
2140 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002141 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07002142
2143 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002144 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002145 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002146 }
2147
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002148 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002149 InputDispatcherTest::TearDown();
2150
2151 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002152 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002153 }
2154
2155protected:
2156 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002157 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002158 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002159};
2160
2161// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2162// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2163// the onPointerDownOutsideFocus callback.
2164TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002165 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2166 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2167 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002168 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002169 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002170
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002171 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002172 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2173}
2174
2175// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2176// DOWN on the window that doesn't have focus. Ensure no window received the
2177// onPointerDownOutsideFocus callback.
2178TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002179 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2180 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002181 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002182 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002183
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002184 ASSERT_TRUE(mDispatcher->waitForIdle());
2185 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002186}
2187
2188// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2189// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2190TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2191 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2192 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002193 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002195 ASSERT_TRUE(mDispatcher->waitForIdle());
2196 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002197}
2198
2199// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2200// DOWN on the window that already has focus. Ensure no window received the
2201// onPointerDownOutsideFocus callback.
2202TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2203 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002204 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2205 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002206 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002207 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002208 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002209
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002210 ASSERT_TRUE(mDispatcher->waitForIdle());
2211 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002212}
2213
chaviwaf87b3e2019-10-01 16:59:28 -07002214// These tests ensures we can send touch events to a single client when there are multiple input
2215// windows that point to the same client token.
2216class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2217 virtual void SetUp() override {
2218 InputDispatcherTest::SetUp();
2219
2220 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2221 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2222 ADISPLAY_ID_DEFAULT);
2223 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2224 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
2225 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2226 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002227 mWindow1->setFrame(Rect(0, 0, 100, 100));
2228
2229 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2230 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
2231 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2232 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002233 mWindow2->setFrame(Rect(100, 100, 200, 200));
2234
Arthur Hung72d8dc32020-03-28 00:48:39 +00002235 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002236 }
2237
2238protected:
2239 sp<FakeWindowHandle> mWindow1;
2240 sp<FakeWindowHandle> mWindow2;
2241
2242 // Helper function to convert the point from screen coordinates into the window's space
2243 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
2244 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
2245 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
2246 return {x, y};
2247 }
2248
2249 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2250 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002251 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002252 InputEvent* event = window->consume();
2253
2254 ASSERT_NE(nullptr, event) << name.c_str()
2255 << ": consumer should have returned non-NULL event.";
2256
2257 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2258 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2259 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2260
2261 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2262 EXPECT_EQ(expectedAction, motionEvent.getAction());
2263
2264 for (size_t i = 0; i < points.size(); i++) {
2265 float expectedX = points[i].x;
2266 float expectedY = points[i].y;
2267
2268 EXPECT_EQ(expectedX, motionEvent.getX(i))
2269 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2270 << ", got " << motionEvent.getX(i);
2271 EXPECT_EQ(expectedY, motionEvent.getY(i))
2272 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2273 << ", got " << motionEvent.getY(i);
2274 }
2275 }
2276};
2277
2278TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2279 // Touch Window 1
2280 PointF touchedPoint = {10, 10};
2281 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2282
2283 NotifyMotionArgs motionArgs =
2284 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2285 ADISPLAY_ID_DEFAULT, {touchedPoint});
2286 mDispatcher->notifyMotion(&motionArgs);
2287 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2288
2289 // Release touch on Window 1
2290 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2291 ADISPLAY_ID_DEFAULT, {touchedPoint});
2292 mDispatcher->notifyMotion(&motionArgs);
2293 // consume the UP event
2294 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2295
2296 // Touch Window 2
2297 touchedPoint = {150, 150};
2298 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2299
2300 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2301 ADISPLAY_ID_DEFAULT, {touchedPoint});
2302 mDispatcher->notifyMotion(&motionArgs);
2303
2304 // Consuming from window1 since it's the window that has the InputReceiver
2305 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2306}
2307
2308TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2309 mWindow2->setWindowScale(0.5f, 0.5f);
2310
2311 // Touch Window 1
2312 PointF touchedPoint = {10, 10};
2313 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2314
2315 NotifyMotionArgs motionArgs =
2316 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2317 ADISPLAY_ID_DEFAULT, {touchedPoint});
2318 mDispatcher->notifyMotion(&motionArgs);
2319 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2320
2321 // Release touch on Window 1
2322 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2323 ADISPLAY_ID_DEFAULT, {touchedPoint});
2324 mDispatcher->notifyMotion(&motionArgs);
2325 // consume the UP event
2326 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2327
2328 // Touch Window 2
2329 touchedPoint = {150, 150};
2330 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2331
2332 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2333 ADISPLAY_ID_DEFAULT, {touchedPoint});
2334 mDispatcher->notifyMotion(&motionArgs);
2335
2336 // Consuming from window1 since it's the window that has the InputReceiver
2337 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2338}
2339
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002340TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2341 mWindow2->setWindowScale(0.5f, 0.5f);
2342
2343 // Touch Window 1
2344 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2345 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2346
2347 NotifyMotionArgs motionArgs =
2348 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2349 ADISPLAY_ID_DEFAULT, touchedPoints);
2350 mDispatcher->notifyMotion(&motionArgs);
2351 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2352
2353 // Touch Window 2
2354 int32_t actionPointerDown =
2355 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2356 touchedPoints.emplace_back(PointF{150, 150});
2357 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2358
2359 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2360 ADISPLAY_ID_DEFAULT, touchedPoints);
2361 mDispatcher->notifyMotion(&motionArgs);
2362
2363 // Consuming from window1 since it's the window that has the InputReceiver
2364 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2365}
2366
2367TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2368 mWindow2->setWindowScale(0.5f, 0.5f);
2369
2370 // Touch Window 1
2371 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2372 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2373
2374 NotifyMotionArgs motionArgs =
2375 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2376 ADISPLAY_ID_DEFAULT, touchedPoints);
2377 mDispatcher->notifyMotion(&motionArgs);
2378 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2379
2380 // Touch Window 2
2381 int32_t actionPointerDown =
2382 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2383 touchedPoints.emplace_back(PointF{150, 150});
2384 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2385
2386 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2387 ADISPLAY_ID_DEFAULT, touchedPoints);
2388 mDispatcher->notifyMotion(&motionArgs);
2389
2390 // Consuming from window1 since it's the window that has the InputReceiver
2391 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2392
2393 // Move both windows
2394 touchedPoints = {{20, 20}, {175, 175}};
2395 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2396 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2397
2398 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2399 ADISPLAY_ID_DEFAULT, touchedPoints);
2400 mDispatcher->notifyMotion(&motionArgs);
2401
2402 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2403}
2404
2405TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2406 mWindow1->setWindowScale(0.5f, 0.5f);
2407
2408 // Touch Window 1
2409 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2410 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2411
2412 NotifyMotionArgs motionArgs =
2413 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2414 ADISPLAY_ID_DEFAULT, touchedPoints);
2415 mDispatcher->notifyMotion(&motionArgs);
2416 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2417
2418 // Touch Window 2
2419 int32_t actionPointerDown =
2420 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2421 touchedPoints.emplace_back(PointF{150, 150});
2422 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2423
2424 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2425 ADISPLAY_ID_DEFAULT, touchedPoints);
2426 mDispatcher->notifyMotion(&motionArgs);
2427
2428 // Consuming from window1 since it's the window that has the InputReceiver
2429 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2430
2431 // Move both windows
2432 touchedPoints = {{20, 20}, {175, 175}};
2433 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2434 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2435
2436 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2437 ADISPLAY_ID_DEFAULT, touchedPoints);
2438 mDispatcher->notifyMotion(&motionArgs);
2439
2440 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2441}
2442
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002443class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2444 virtual void SetUp() override {
2445 InputDispatcherTest::SetUp();
2446
2447 mApplication = new FakeApplicationHandle();
2448 mApplication->setDispatchingTimeout(20ms);
2449 mWindow =
2450 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2451 mWindow->setFrame(Rect(0, 0, 30, 30));
2452 mWindow->setDispatchingTimeout(10ms);
2453 mWindow->setFocus(true);
2454 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2455 // window.
2456 mWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2457
2458 // Set focused application.
2459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2460
2461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2462 mWindow->consumeFocusEvent(true);
2463 }
2464
2465 virtual void TearDown() override {
2466 InputDispatcherTest::TearDown();
2467 mWindow.clear();
2468 }
2469
2470protected:
2471 sp<FakeApplicationHandle> mApplication;
2472 sp<FakeWindowHandle> mWindow;
2473 static constexpr PointF WINDOW_LOCATION = {20, 20};
2474
2475 void tapOnWindow() {
2476 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2477 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2478 WINDOW_LOCATION));
2479 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2480 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2481 WINDOW_LOCATION));
2482 }
2483};
2484
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002485// Send a tap and respond, which should not cause an ANR.
2486TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2487 tapOnWindow();
2488 mWindow->consumeMotionDown();
2489 mWindow->consumeMotionUp();
2490 ASSERT_TRUE(mDispatcher->waitForIdle());
2491 mFakePolicy->assertNotifyAnrWasNotCalled();
2492}
2493
2494// Send a regular key and respond, which should not cause an ANR.
2495TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
2496 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2497 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2498 ASSERT_TRUE(mDispatcher->waitForIdle());
2499 mFakePolicy->assertNotifyAnrWasNotCalled();
2500}
2501
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002502// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002503// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2504// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002505TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2506 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2507 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2508 WINDOW_LOCATION));
2509
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002510 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2511 ASSERT_TRUE(sequenceNum);
2512 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2513 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002514
2515 // The remaining lines are not really needed for the test, but kept as a sanity check
2516 mWindow->finishEvent(*sequenceNum);
2517 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2518 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002519 ASSERT_TRUE(mDispatcher->waitForIdle());
2520}
2521
2522// Send a key to the app and have the app not respond right away.
2523TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2524 // Inject a key, and don't respond - expect that ANR is called.
2525 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2526 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2527 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002528 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002529 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002530 ASSERT_TRUE(mDispatcher->waitForIdle());
2531}
2532
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002533// We have a focused application, but no focused window
2534TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
2535 mWindow->setFocus(false);
2536 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2537 mWindow->consumeFocusEvent(false);
2538
2539 // taps on the window work as normal
2540 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2541 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2542 WINDOW_LOCATION));
2543 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2544 mDispatcher->waitForIdle();
2545 mFakePolicy->assertNotifyAnrWasNotCalled();
2546
2547 // Once a focused event arrives, we get an ANR for this application
2548 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2549 // injection times out (instead of failing).
2550 const int32_t result =
2551 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2552 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2553 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2554 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2555 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2556 ASSERT_TRUE(mDispatcher->waitForIdle());
2557}
2558
2559// We have a focused application, but no focused window
2560// If the policy wants to keep waiting on the focused window to be added, make sure
2561// that this timeout extension is honored and ANR is raised again.
2562TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
2563 mWindow->setFocus(false);
2564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2565 mWindow->consumeFocusEvent(false);
2566 const std::chrono::duration timeout = 5ms;
2567 mFakePolicy->setAnrTimeout(timeout);
2568
2569 // Once a focused event arrives, we get an ANR for this application
2570 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2571 // injection times out (instead of failing).
2572 const int32_t result =
2573 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2574 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2575 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2576 const std::chrono::duration appTimeout =
2577 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2578 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2579
2580 // After the extended time has passed, ANR should be raised again
2581 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2582
2583 // If we stop extending the timeout, dispatcher should go to idle.
2584 // Another ANR may be raised during this time
2585 mFakePolicy->setAnrTimeout(0ms);
2586 ASSERT_TRUE(mDispatcher->waitForIdle());
2587}
2588
2589// We have a focused application, but no focused window
2590TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
2591 mWindow->setFocus(false);
2592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2593 mWindow->consumeFocusEvent(false);
2594
2595 // Once a focused event arrives, we get an ANR for this application
2596 const int32_t result =
2597 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2598 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2599 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2600
2601 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2602 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2603
2604 // Future focused events get dropped right away
2605 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, injectKeyDown(mDispatcher));
2606 ASSERT_TRUE(mDispatcher->waitForIdle());
2607 mWindow->assertNoEvents();
2608}
2609
2610/**
2611 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2612 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2613 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2614 * the ANR mechanism should still work.
2615 *
2616 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2617 * DOWN event, while not responding on the second one.
2618 */
2619TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2620 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2621 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2622 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2623 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2624 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2625 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2626
2627 // Now send ACTION_UP, with identical timestamp
2628 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2629 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2630 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2631 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2632 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2633
2634 // We have now sent down and up. Let's consume first event and then ANR on the second.
2635 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2636 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2637 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2638}
2639
2640// If an app is not responding to a key event, gesture monitors should continue to receive
2641// new motion events
2642TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
2643 FakeMonitorReceiver monitor =
2644 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2645 true /*isGestureMonitor*/);
2646
2647 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
2648 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2649 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
2650
2651 // Stuck on the ACTION_UP
2652 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2653 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2654
2655 // New tap will go to the gesture monitor, but not to the window
2656 tapOnWindow();
2657 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2658 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2659
2660 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2661 mDispatcher->waitForIdle();
2662 mWindow->assertNoEvents();
2663 monitor.assertNoEvents();
2664}
2665
2666// If an app is not responding to a motion event, gesture monitors should continue to receive
2667// new motion events
2668TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
2669 FakeMonitorReceiver monitor =
2670 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2671 true /*isGestureMonitor*/);
2672
2673 tapOnWindow();
2674 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2675 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2676
2677 mWindow->consumeMotionDown();
2678 // Stuck on the ACTION_UP
2679 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2680 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2681
2682 // New tap will go to the gesture monitor, but not to the window
2683 tapOnWindow();
2684 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2685 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2686
2687 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2688 mDispatcher->waitForIdle();
2689 mWindow->assertNoEvents();
2690 monitor.assertNoEvents();
2691}
2692
2693// If a window is unresponsive, then you get anr. if the window later catches up and starts to
2694// process events, you don't get an anr. When the window later becomes unresponsive again, you
2695// get an ANR again.
2696// 1. tap -> block on ACTION_UP -> receive ANR
2697// 2. consume all pending events (= queue becomes healthy again)
2698// 3. tap again -> block on ACTION_UP again -> receive ANR second time
2699TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
2700 tapOnWindow();
2701
2702 mWindow->consumeMotionDown();
2703 // Block on ACTION_UP
2704 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2705 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2706 mWindow->consumeMotionUp(); // Now the connection should be healthy again
2707 mDispatcher->waitForIdle();
2708 mWindow->assertNoEvents();
2709
2710 tapOnWindow();
2711 mWindow->consumeMotionDown();
2712 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2713 mWindow->consumeMotionUp();
2714
2715 mDispatcher->waitForIdle();
2716 mWindow->assertNoEvents();
2717}
2718
2719// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
2720// is honored
2721TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
2722 const std::chrono::duration timeout = 5ms;
2723 mFakePolicy->setAnrTimeout(timeout);
2724
2725 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2726 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2727 WINDOW_LOCATION));
2728
2729 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2730 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
2731 mWindow->getToken());
2732
2733 // Since the policy wanted to extend ANR, make sure it is called again after the extension
2734 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2735 mFakePolicy->setAnrTimeout(0ms);
2736 std::this_thread::sleep_for(windowTimeout);
2737 // We are not checking if ANR has been called, because it may have been called again by the
2738 // time we set the timeout to 0
2739
2740 // When the policy finally says stop, we should get ACTION_CANCEL
2741 mWindow->consumeMotionDown();
2742 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2743 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2744 mWindow->assertNoEvents();
2745}
2746
2747/**
2748 * If a window is processing a motion event, and then a key event comes in, the key event should
2749 * not to to the focused window until the motion is processed.
2750 *
2751 * Warning!!!
2752 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2753 * and the injection timeout that we specify when injecting the key.
2754 * We must have the injection timeout (10ms) be smaller than
2755 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2756 *
2757 * If that value changes, this test should also change.
2758 */
2759TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
2760 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2762
2763 tapOnWindow();
2764 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2765 ASSERT_TRUE(downSequenceNum);
2766 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2767 ASSERT_TRUE(upSequenceNum);
2768 // Don't finish the events yet, and send a key
2769 // Injection will "succeed" because we will eventually give up and send the key to the focused
2770 // window even if motions are still being processed. But because the injection timeout is short,
2771 // we will receive INJECTION_TIMED_OUT as the result.
2772
2773 int32_t result =
2774 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2775 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2776 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2777 // Key will not be sent to the window, yet, because the window is still processing events
2778 // and the key remains pending, waiting for the touch events to be processed
2779 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2780 ASSERT_FALSE(keySequenceNum);
2781
2782 std::this_thread::sleep_for(500ms);
2783 // if we wait long enough though, dispatcher will give up, and still send the key
2784 // to the focused window, even though we have not yet finished the motion event
2785 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2786 mWindow->finishEvent(*downSequenceNum);
2787 mWindow->finishEvent(*upSequenceNum);
2788}
2789
2790/**
2791 * If a window is processing a motion event, and then a key event comes in, the key event should
2792 * not go to the focused window until the motion is processed.
2793 * If then a new motion comes in, then the pending key event should be going to the currently
2794 * focused window right away.
2795 */
2796TEST_F(InputDispatcherSingleWindowAnr,
2797 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
2798 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2800
2801 tapOnWindow();
2802 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2803 ASSERT_TRUE(downSequenceNum);
2804 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2805 ASSERT_TRUE(upSequenceNum);
2806 // Don't finish the events yet, and send a key
2807 // Injection is async, so it will succeed
2808 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2809 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
2810 ADISPLAY_ID_DEFAULT, INPUT_EVENT_INJECTION_SYNC_NONE));
2811 // At this point, key is still pending, and should not be sent to the application yet.
2812 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2813 ASSERT_FALSE(keySequenceNum);
2814
2815 // Now tap down again. It should cause the pending key to go to the focused window right away.
2816 tapOnWindow();
2817 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
2818 // the other events yet. We can finish events in any order.
2819 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
2820 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
2821 mWindow->consumeMotionDown();
2822 mWindow->consumeMotionUp();
2823 mWindow->assertNoEvents();
2824}
2825
2826class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
2827 virtual void SetUp() override {
2828 InputDispatcherTest::SetUp();
2829
2830 mApplication = new FakeApplicationHandle();
2831 mApplication->setDispatchingTimeout(10ms);
2832 mUnfocusedWindow =
2833 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
2834 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2835 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2836 // window.
2837 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
2838 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2839 InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH |
2840 InputWindowInfo::FLAG_SPLIT_TOUCH);
2841
2842 mFocusedWindow =
2843 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
2844 mFocusedWindow->setDispatchingTimeout(10ms);
2845 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
2846 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2847 InputWindowInfo::FLAG_SPLIT_TOUCH);
2848
2849 // Set focused application.
2850 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2851 mFocusedWindow->setFocus(true);
2852
2853 // Expect one focus window exist in display.
2854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2855 mFocusedWindow->consumeFocusEvent(true);
2856 }
2857
2858 virtual void TearDown() override {
2859 InputDispatcherTest::TearDown();
2860
2861 mUnfocusedWindow.clear();
2862 mFocusedWindow.clear();
2863 }
2864
2865protected:
2866 sp<FakeApplicationHandle> mApplication;
2867 sp<FakeWindowHandle> mUnfocusedWindow;
2868 sp<FakeWindowHandle> mFocusedWindow;
2869 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
2870 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
2871 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
2872
2873 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
2874
2875 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
2876
2877private:
2878 void tap(const PointF& location) {
2879 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2880 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2881 location));
2882 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2883 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2884 location));
2885 }
2886};
2887
2888// If we have 2 windows that are both unresponsive, the one with the shortest timeout
2889// should be ANR'd first.
2890TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
2891 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2892 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2893 FOCUSED_WINDOW_LOCATION))
2894 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2895 mFocusedWindow->consumeMotionDown();
2896 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2897 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2898 // We consumed all events, so no ANR
2899 ASSERT_TRUE(mDispatcher->waitForIdle());
2900 mFakePolicy->assertNotifyAnrWasNotCalled();
2901
2902 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2903 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2904 FOCUSED_WINDOW_LOCATION));
2905 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
2906 ASSERT_TRUE(unfocusedSequenceNum);
2907 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
2908 ASSERT_TRUE(focusedSequenceNum);
2909
2910 const std::chrono::duration timeout =
2911 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2912 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
2913 mFocusedWindow->getToken());
2914
2915 mFocusedWindow->finishEvent(*focusedSequenceNum);
2916 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
2917 ASSERT_TRUE(mDispatcher->waitForIdle());
2918}
2919
2920// If we have 2 windows with identical timeouts that are both unresponsive,
2921// it doesn't matter which order they should have ANR.
2922// But we should receive ANR for both.
2923TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
2924 // Set the timeout for unfocused window to match the focused window
2925 mUnfocusedWindow->setDispatchingTimeout(10ms);
2926 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2927
2928 tapOnFocusedWindow();
2929 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
2930 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData1 =
2931 mFakePolicy->getNotifyAnrData(10ms);
2932 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData2 =
2933 mFakePolicy->getNotifyAnrData(0ms);
2934
2935 // We don't know which window will ANR first. But both of them should happen eventually.
2936 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
2937 mFocusedWindow->getToken() == anrData2.second);
2938 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
2939 mUnfocusedWindow->getToken() == anrData2.second);
2940
2941 ASSERT_TRUE(mDispatcher->waitForIdle());
2942 mFakePolicy->assertNotifyAnrWasNotCalled();
2943}
2944
2945// If a window is already not responding, the second tap on the same window should be ignored.
2946// We should also log an error to account for the dropped event (not tested here).
2947// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
2948TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
2949 tapOnFocusedWindow();
2950 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2951 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2952 // Receive the events, but don't respond
2953 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
2954 ASSERT_TRUE(downEventSequenceNum);
2955 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
2956 ASSERT_TRUE(upEventSequenceNum);
2957 const std::chrono::duration timeout =
2958 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2959 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
2960 mFocusedWindow->getToken());
2961
2962 // Tap once again
2963 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
2964 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2965 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2966 FOCUSED_WINDOW_LOCATION));
2967 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2968 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2969 FOCUSED_WINDOW_LOCATION));
2970 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
2971 // valid touch target
2972 mUnfocusedWindow->assertNoEvents();
2973
2974 // Consume the first tap
2975 mFocusedWindow->finishEvent(*downEventSequenceNum);
2976 mFocusedWindow->finishEvent(*upEventSequenceNum);
2977 ASSERT_TRUE(mDispatcher->waitForIdle());
2978 // The second tap did not go to the focused window
2979 mFocusedWindow->assertNoEvents();
2980 // should not have another ANR after the window just became healthy again
2981 mFakePolicy->assertNotifyAnrWasNotCalled();
2982}
2983
2984// If you tap outside of all windows, there will not be ANR
2985TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
2986 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2987 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2988 LOCATION_OUTSIDE_ALL_WINDOWS));
2989 ASSERT_TRUE(mDispatcher->waitForIdle());
2990 mFakePolicy->assertNotifyAnrWasNotCalled();
2991}
2992
2993// Since the focused window is paused, tapping on it should not produce any events
2994TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
2995 mFocusedWindow->setPaused(true);
2996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2997
2998 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3000 FOCUSED_WINDOW_LOCATION));
3001
3002 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3003 ASSERT_TRUE(mDispatcher->waitForIdle());
3004 // Should not ANR because the window is paused, and touches shouldn't go to it
3005 mFakePolicy->assertNotifyAnrWasNotCalled();
3006
3007 mFocusedWindow->assertNoEvents();
3008 mUnfocusedWindow->assertNoEvents();
3009}
3010
3011/**
3012 * If a window is processing a motion event, and then a key event comes in, the key event should
3013 * not to to the focused window until the motion is processed.
3014 * If a different window becomes focused at this time, the key should go to that window instead.
3015 *
3016 * Warning!!!
3017 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3018 * and the injection timeout that we specify when injecting the key.
3019 * We must have the injection timeout (10ms) be smaller than
3020 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3021 *
3022 * If that value changes, this test should also change.
3023 */
3024TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3025 // Set a long ANR timeout to prevent it from triggering
3026 mFocusedWindow->setDispatchingTimeout(2s);
3027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3028
3029 tapOnUnfocusedWindow();
3030 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3031 ASSERT_TRUE(downSequenceNum);
3032 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3033 ASSERT_TRUE(upSequenceNum);
3034 // Don't finish the events yet, and send a key
3035 // Injection will succeed because we will eventually give up and send the key to the focused
3036 // window even if motions are still being processed.
3037
3038 int32_t result =
3039 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
3040 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
3041 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
3042 // Key will not be sent to the window, yet, because the window is still processing events
3043 // and the key remains pending, waiting for the touch events to be processed
3044 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3045 ASSERT_FALSE(keySequenceNum);
3046
3047 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
3048 mFocusedWindow->setFocus(false);
3049 mUnfocusedWindow->setFocus(true);
3050 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3051
3052 // Focus events should precede the key events
3053 mUnfocusedWindow->consumeFocusEvent(true);
3054 mFocusedWindow->consumeFocusEvent(false);
3055
3056 // Finish the tap events, which should unblock dispatcher
3057 mUnfocusedWindow->finishEvent(*downSequenceNum);
3058 mUnfocusedWindow->finishEvent(*upSequenceNum);
3059
3060 // Now that all queues are cleared and no backlog in the connections, the key event
3061 // can finally go to the newly focused "mUnfocusedWindow".
3062 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3063 mFocusedWindow->assertNoEvents();
3064 mUnfocusedWindow->assertNoEvents();
3065}
3066
3067// When the touch stream is split across 2 windows, and one of them does not respond,
3068// then ANR should be raised and the touch should be canceled for the unresponsive window.
3069// The other window should not be affected by that.
3070TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3071 // Touch Window 1
3072 NotifyMotionArgs motionArgs =
3073 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3074 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3075 mDispatcher->notifyMotion(&motionArgs);
3076 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3077 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3078
3079 // Touch Window 2
3080 int32_t actionPointerDown =
3081 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3082
3083 motionArgs =
3084 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3085 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3086 mDispatcher->notifyMotion(&motionArgs);
3087
3088 const std::chrono::duration timeout =
3089 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3090 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3091 mFocusedWindow->getToken());
3092
3093 mUnfocusedWindow->consumeMotionDown();
3094 mFocusedWindow->consumeMotionDown();
3095 // Focused window may or may not receive ACTION_MOVE
3096 // But it should definitely receive ACTION_CANCEL due to the ANR
3097 InputEvent* event;
3098 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3099 ASSERT_TRUE(moveOrCancelSequenceNum);
3100 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3101 ASSERT_NE(nullptr, event);
3102 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3103 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3104 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3105 mFocusedWindow->consumeMotionCancel();
3106 } else {
3107 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3108 }
3109
3110 ASSERT_TRUE(mDispatcher->waitForIdle());
3111 mUnfocusedWindow->assertNoEvents();
3112 mFocusedWindow->assertNoEvents();
3113}
3114
Garfield Tane84e6f92019-08-29 17:28:41 -07003115} // namespace android::inputdispatcher