blob: cc19cb104d7244bc62a3b30571de563508da4b3c [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 Vishniakou4cb50ca2020-05-26 21:43:02 -070020#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080022#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070023
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <gtest/gtest.h>
25#include <linux/input.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-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;
Michael Wright44753b12020-07-08 13:48:11 +010032using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080033
Garfield Tane84e6f92019-08-29 17:28:41 -070034namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080035
36// An arbitrary time value.
37static const nsecs_t ARBITRARY_TIME = 1234;
38
39// An arbitrary device id.
40static const int32_t DEVICE_ID = 1;
41
Jeff Brownf086ddb2014-02-11 14:28:48 -080042// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080043static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080044
Michael Wrightd02c5b62014-02-10 15:10:22 -080045// An arbitrary injector pid / uid pair that has permission to inject events.
46static const int32_t INJECTOR_PID = 999;
47static const int32_t INJECTOR_UID = 1001;
48
chaviwd1c23182019-12-20 18:44:56 -080049struct PointF {
50 float x;
51 float y;
52};
Michael Wrightd02c5b62014-02-10 15:10:22 -080053
Gang Wang342c9272020-01-13 13:15:04 -050054/**
55 * Return a DOWN key event with KEYCODE_A.
56 */
57static KeyEvent getTestKeyEvent() {
58 KeyEvent event;
59
Garfield Tanfbe732e2020-01-24 11:26:14 -080060 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
61 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
62 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050063 return event;
64}
65
Michael Wrightd02c5b62014-02-10 15:10:22 -080066// --- FakeInputDispatcherPolicy ---
67
68class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
69 InputDispatcherConfiguration mConfig;
70
71protected:
72 virtual ~FakeInputDispatcherPolicy() {
73 }
74
75public:
76 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080077 }
78
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080079 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080080 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
81 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080082 }
83
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080084 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080085 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
86 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080087 }
88
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070089 void assertFilterInputEventWasNotCalled() {
90 std::scoped_lock lock(mLock);
91 ASSERT_EQ(nullptr, mFilteredEvent);
92 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080093
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080094 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070095 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080096 ASSERT_TRUE(mConfigurationChangedTime)
97 << "Timed out waiting for configuration changed call";
98 ASSERT_EQ(*mConfigurationChangedTime, when);
99 mConfigurationChangedTime = std::nullopt;
100 }
101
102 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700103 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800104 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800105 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
107 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
108 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
109 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
110 mLastNotifySwitch = std::nullopt;
111 }
112
chaviwfd6d3512019-03-25 13:23:49 -0700113 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700114 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800115 ASSERT_EQ(touchedToken, mOnPointerDownToken);
116 mOnPointerDownToken.clear();
117 }
118
119 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700120 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800121 ASSERT_TRUE(mOnPointerDownToken == nullptr)
122 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700123 }
124
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700125 // This function must be called soon after the expected ANR timer starts,
126 // because we are also checking how much time has passed.
Chris Yea209fde2020-07-22 13:54:51 -0700127 void assertNotifyAnrWasCalled(
128 std::chrono::nanoseconds timeout,
129 const std::shared_ptr<InputApplicationHandle>& expectedApplication,
130 const sp<IBinder>& expectedToken) {
131 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700132 ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
133 ASSERT_EQ(expectedApplication, anrData.first);
134 ASSERT_EQ(expectedToken, anrData.second);
135 }
136
Chris Yea209fde2020-07-22 13:54:51 -0700137 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700138 std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700139 const std::chrono::time_point start = std::chrono::steady_clock::now();
140 std::unique_lock lock(mLock);
141 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
142 android::base::ScopedLockAssertion assumeLocked(mLock);
143
144 // If there is an ANR, Dispatcher won't be idle because there are still events
145 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
146 // before checking if ANR was called.
147 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
148 // it some time to act. 100ms seems reasonable.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700149 mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
150 return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
151 });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700152 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700153 if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
154 ADD_FAILURE() << "Did not receive ANR callback";
155 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700156 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
157 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700158 if (std::chrono::abs(timeout - waited) > 100ms) {
159 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
160 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
161 << "ms, but waited "
162 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
163 << "ms instead";
164 }
Chris Yea209fde2020-07-22 13:54:51 -0700165 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700166 std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
167 mAnrApplications.pop();
168 mAnrWindowTokens.pop();
169 return result;
170 }
171
172 void assertNotifyAnrWasNotCalled() {
173 std::scoped_lock lock(mLock);
174 ASSERT_TRUE(mAnrApplications.empty());
175 ASSERT_TRUE(mAnrWindowTokens.empty());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700176 }
177
Garfield Tan1c7bc862020-01-28 13:24:04 -0800178 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
179 mConfig.keyRepeatTimeout = timeout;
180 mConfig.keyRepeatDelay = delay;
181 }
182
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700183 void setAnrTimeout(std::chrono::nanoseconds timeout) { mAnrTimeout = timeout; }
184
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700186 std::mutex mLock;
187 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
188 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
189 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
190 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800191
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700192 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700193 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700194 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700195 std::condition_variable mNotifyAnr;
196 std::chrono::nanoseconds mAnrTimeout = 0ms;
197
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800198 virtual void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700199 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800200 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800201 }
202
Chris Yea209fde2020-07-22 13:54:51 -0700203 std::chrono::nanoseconds notifyAnr(const std::shared_ptr<InputApplicationHandle>& application,
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500204 const sp<IBinder>& windowToken,
205 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700206 std::scoped_lock lock(mLock);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700207 mAnrApplications.push(application);
208 mAnrWindowTokens.push(windowToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700209 mNotifyAnr.notify_all();
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500210 return mAnrTimeout;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800211 }
212
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700213 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800214
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700215 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700216
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700217 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800218 *outConfig = mConfig;
219 }
220
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800221 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700222 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800223 switch (inputEvent->getType()) {
224 case AINPUT_EVENT_TYPE_KEY: {
225 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800226 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800227 break;
228 }
229
230 case AINPUT_EVENT_TYPE_MOTION: {
231 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800232 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800233 break;
234 }
235 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800236 return true;
237 }
238
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700239 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700241 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800242
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700243 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
244 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800245 return 0;
246 }
247
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700248 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
249 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800250 return false;
251 }
252
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800253 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
254 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700255 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800256 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
257 * essentially a passthrough for notifySwitch.
258 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800259 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260 }
261
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700262 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800263
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700264 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800265 return false;
266 }
Jackal Guof9696682018-10-05 12:23:23 +0800267
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700268 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700270 mOnPointerDownToken = newToken;
271 }
272
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800273 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
274 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700275 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800276 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
277 ASSERT_EQ(mFilteredEvent->getType(), type);
278
279 if (type == AINPUT_EVENT_TYPE_KEY) {
280 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
281 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
282 EXPECT_EQ(keyEvent.getAction(), action);
283 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
284 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
285 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
286 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
287 EXPECT_EQ(motionEvent.getAction(), action);
288 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
289 } else {
290 FAIL() << "Unknown type: " << type;
291 }
292
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800293 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800294 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800295};
296
Gang Wang342c9272020-01-13 13:15:04 -0500297// --- HmacKeyManagerTest ---
298
299class HmacKeyManagerTest : public testing::Test {
300protected:
301 HmacKeyManager mHmacKeyManager;
302};
303
304/**
305 * Ensure that separate calls to sign the same data are generating the same key.
306 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
307 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
308 * tests.
309 */
310TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
311 KeyEvent event = getTestKeyEvent();
312 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
313
314 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
315 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
316 ASSERT_EQ(hmac1, hmac2);
317}
318
319/**
320 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
321 */
322TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
323 KeyEvent event = getTestKeyEvent();
324 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
325 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
326
327 verifiedEvent.deviceId += 1;
328 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
329
330 verifiedEvent.source += 1;
331 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
332
333 verifiedEvent.eventTimeNanos += 1;
334 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
335
336 verifiedEvent.displayId += 1;
337 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
338
339 verifiedEvent.action += 1;
340 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
341
342 verifiedEvent.downTimeNanos += 1;
343 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
344
345 verifiedEvent.flags += 1;
346 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
347
348 verifiedEvent.keyCode += 1;
349 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
350
351 verifiedEvent.scanCode += 1;
352 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
353
354 verifiedEvent.metaState += 1;
355 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
356
357 verifiedEvent.repeatCount += 1;
358 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
359}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800360
361// --- InputDispatcherTest ---
362
363class InputDispatcherTest : public testing::Test {
364protected:
365 sp<FakeInputDispatcherPolicy> mFakePolicy;
366 sp<InputDispatcher> mDispatcher;
367
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700368 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800369 mFakePolicy = new FakeInputDispatcherPolicy();
370 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800371 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
372 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700373 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800374 }
375
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700376 virtual void TearDown() override {
377 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800378 mFakePolicy.clear();
379 mDispatcher.clear();
380 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700381
382 /**
383 * Used for debugging when writing the test
384 */
385 void dumpDispatcherState() {
386 std::string dump;
387 mDispatcher->dump(dump);
388 std::stringstream ss(dump);
389 std::string to;
390
391 while (std::getline(ss, to, '\n')) {
392 ALOGE("%s", to.c_str());
393 }
394 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800395};
396
397
398TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
399 KeyEvent event;
400
401 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800402 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
403 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600404 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
405 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700406 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
407 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
408 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800409 << "Should reject key events with undefined action.";
410
411 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800412 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
413 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600414 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700415 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
416 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
417 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800418 << "Should reject key events with ACTION_MULTIPLE.";
419}
420
421TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
422 MotionEvent event;
423 PointerProperties pointerProperties[MAX_POINTERS + 1];
424 PointerCoords pointerCoords[MAX_POINTERS + 1];
425 for (int i = 0; i <= MAX_POINTERS; i++) {
426 pointerProperties[i].clear();
427 pointerProperties[i].id = i;
428 pointerCoords[i].clear();
429 }
430
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800431 // Some constants commonly used below
432 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
433 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
434 constexpr int32_t metaState = AMETA_NONE;
435 constexpr MotionClassification classification = MotionClassification::NONE;
436
chaviw9eaa22c2020-07-01 16:21:27 -0700437 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800438 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800439 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700440 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
441 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600442 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700443 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700444 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
445 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
446 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800447 << "Should reject motion events with undefined action.";
448
449 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800450 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700451 AMOTION_EVENT_ACTION_POINTER_DOWN |
452 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700453 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
454 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
455 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
456 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700457 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
458 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
459 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800460 << "Should reject motion events with pointer down index too large.";
461
Garfield Tanfbe732e2020-01-24 11:26:14 -0800462 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700463 AMOTION_EVENT_ACTION_POINTER_DOWN |
464 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700465 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
466 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
467 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
468 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700469 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
470 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
471 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800472 << "Should reject motion events with pointer down index too small.";
473
474 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800475 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700476 AMOTION_EVENT_ACTION_POINTER_UP |
477 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700478 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
479 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
480 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
481 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700482 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
483 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
484 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800485 << "Should reject motion events with pointer up index too large.";
486
Garfield Tanfbe732e2020-01-24 11:26:14 -0800487 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700488 AMOTION_EVENT_ACTION_POINTER_UP |
489 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700490 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
491 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
492 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
493 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700494 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
495 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
496 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800497 << "Should reject motion events with pointer up index too small.";
498
499 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800500 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
501 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700502 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
503 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700504 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700505 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
506 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
507 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800508 << "Should reject motion events with 0 pointers.";
509
Garfield Tanfbe732e2020-01-24 11:26:14 -0800510 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
511 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700512 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
513 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700514 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700515 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
516 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
517 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800518 << "Should reject motion events with more than MAX_POINTERS pointers.";
519
520 // Rejects motion events with invalid pointer ids.
521 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800522 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
523 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700524 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
525 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700526 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700527 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
528 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
529 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800530 << "Should reject motion events with pointer ids less than 0.";
531
532 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800533 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
534 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700535 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
536 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700537 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700538 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
539 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
540 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
542
543 // Rejects motion events with duplicate pointer ids.
544 pointerProperties[0].id = 1;
545 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800546 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
547 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700548 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
549 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700550 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700551 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
552 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
553 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554 << "Should reject motion events with duplicate pointer ids.";
555}
556
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800557/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
558
559TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
560 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800561 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800562 mDispatcher->notifyConfigurationChanged(&args);
563 ASSERT_TRUE(mDispatcher->waitForIdle());
564
565 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
566}
567
568TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800569 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
570 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800571 mDispatcher->notifySwitch(&args);
572
573 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
574 args.policyFlags |= POLICY_FLAG_TRUSTED;
575 mFakePolicy->assertNotifySwitchWasCalled(args);
576}
577
Arthur Hungb92218b2018-08-14 12:00:21 +0800578// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700579static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700580static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800581
582class FakeApplicationHandle : public InputApplicationHandle {
583public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700584 FakeApplicationHandle() {
585 mInfo.name = "Fake Application";
586 mInfo.token = new BBinder();
Chris Ye6c4243b2020-07-22 12:07:12 -0700587 mInfo.dispatchingTimeoutNanos = DISPATCHING_TIMEOUT.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700588 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800589 virtual ~FakeApplicationHandle() {}
590
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700591 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800592 return true;
593 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700594
595 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Chris Ye6c4243b2020-07-22 12:07:12 -0700596 mInfo.dispatchingTimeoutNanos = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700597 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800598};
599
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800600class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800601public:
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500602 explicit FakeInputReceiver(const std::shared_ptr<InputChannel>& clientChannel,
603 const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800604 : mName(name) {
605 mConsumer = std::make_unique<InputConsumer>(clientChannel);
606 }
607
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800608 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700609 InputEvent* event;
610 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
611 if (!consumeSeq) {
612 return nullptr;
613 }
614 finishEvent(*consumeSeq);
615 return event;
616 }
617
618 /**
619 * Receive an event without acknowledging it.
620 * Return the sequence number that could later be used to send finished signal.
621 */
622 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800623 uint32_t consumeSeq;
624 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800625
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800626 std::chrono::time_point start = std::chrono::steady_clock::now();
627 status_t status = WOULD_BLOCK;
628 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800629 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800630 &event);
631 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
632 if (elapsed > 100ms) {
633 break;
634 }
635 }
636
637 if (status == WOULD_BLOCK) {
638 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700639 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800640 }
641
642 if (status != OK) {
643 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700644 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800645 }
646 if (event == nullptr) {
647 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700648 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800649 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700650 if (outEvent != nullptr) {
651 *outEvent = event;
652 }
653 return consumeSeq;
654 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800655
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700656 /**
657 * To be used together with "receiveEvent" to complete the consumption of an event.
658 */
659 void finishEvent(uint32_t consumeSeq) {
660 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
661 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800662 }
663
664 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
665 int32_t expectedFlags) {
666 InputEvent* event = consume();
667
668 ASSERT_NE(nullptr, event) << mName.c_str()
669 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800670 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700671 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800672 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800673
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800674 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800675
Tiger Huang8664f8c2018-10-11 19:14:35 +0800676 switch (expectedEventType) {
677 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800678 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
679 EXPECT_EQ(expectedAction, keyEvent.getAction());
680 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800681 break;
682 }
683 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800684 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
685 EXPECT_EQ(expectedAction, motionEvent.getAction());
686 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800687 break;
688 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100689 case AINPUT_EVENT_TYPE_FOCUS: {
690 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
691 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800692 default: {
693 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
694 }
695 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800696 }
697
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100698 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
699 InputEvent* event = consume();
700 ASSERT_NE(nullptr, event) << mName.c_str()
701 << ": consumer should have returned non-NULL event.";
702 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
703 << "Got " << inputEventTypeToString(event->getType())
704 << " event instead of FOCUS event";
705
706 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
707 << mName.c_str() << ": event displayId should always be NONE.";
708
709 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
710 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
711 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
712 }
713
chaviwd1c23182019-12-20 18:44:56 -0800714 void assertNoEvents() {
715 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700716 if (event == nullptr) {
717 return;
718 }
719 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
720 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
721 ADD_FAILURE() << "Received key event "
722 << KeyEvent::actionToString(keyEvent.getAction());
723 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
724 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
725 ADD_FAILURE() << "Received motion event "
726 << MotionEvent::actionToString(motionEvent.getAction());
727 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
728 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
729 ADD_FAILURE() << "Received focus event, hasFocus = "
730 << (focusEvent.getHasFocus() ? "true" : "false");
731 }
732 FAIL() << mName.c_str()
733 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800734 }
735
736 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
737
738protected:
739 std::unique_ptr<InputConsumer> mConsumer;
740 PreallocatedInputEventFactory mEventFactory;
741
742 std::string mName;
743};
744
745class FakeWindowHandle : public InputWindowHandle {
746public:
747 static const int32_t WIDTH = 600;
748 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800749
Chris Yea209fde2020-07-22 13:54:51 -0700750 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800751 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500752 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800753 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500754 if (token == std::nullopt) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500755 std::unique_ptr<InputChannel> serverChannel, clientChannel;
chaviwd1c23182019-12-20 18:44:56 -0800756 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500757 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
chaviwd1c23182019-12-20 18:44:56 -0800758 token = serverChannel->getConnectionToken();
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500759 dispatcher->registerInputChannel(std::move(serverChannel));
chaviwd1c23182019-12-20 18:44:56 -0800760 }
761
762 inputApplicationHandle->updateInfo();
763 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
764
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500765 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700766 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800767 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100768 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500769 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800770 mInfo.frameLeft = 0;
771 mInfo.frameTop = 0;
772 mInfo.frameRight = WIDTH;
773 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700774 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800775 mInfo.globalScaleFactor = 1.0;
776 mInfo.touchableRegion.clear();
777 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
778 mInfo.visible = true;
779 mInfo.canReceiveKeys = true;
780 mInfo.hasFocus = false;
781 mInfo.hasWallpaper = false;
782 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800783 mInfo.ownerPid = INJECTOR_PID;
784 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800785 mInfo.displayId = displayId;
786 }
787
788 virtual bool updateInfo() { return true; }
789
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100790 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800791
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700792 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500793 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700794 }
795
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700796 void setPaused(bool paused) { mInfo.paused = paused; }
797
chaviwd1c23182019-12-20 18:44:56 -0800798 void setFrame(const Rect& frame) {
799 mInfo.frameLeft = frame.left;
800 mInfo.frameTop = frame.top;
801 mInfo.frameRight = frame.right;
802 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700803 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800804 mInfo.touchableRegion.clear();
805 mInfo.addTouchableRegion(frame);
806 }
807
Michael Wright44753b12020-07-08 13:48:11 +0100808 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800809
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500810 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
811
chaviw9eaa22c2020-07-01 16:21:27 -0700812 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
813 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
814 }
815
816 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700817
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800818 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
819 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
820 expectedFlags);
821 }
822
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700823 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
824 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
825 }
826
Svet Ganov5d3bc372020-01-26 23:11:07 -0800827 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
828 int32_t expectedFlags = 0) {
829 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
830 expectedFlags);
831 }
832
833 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
834 int32_t expectedFlags = 0) {
835 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
836 expectedFlags);
837 }
838
839 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
840 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800841 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
842 expectedFlags);
843 }
844
Svet Ganov5d3bc372020-01-26 23:11:07 -0800845 void consumeMotionPointerDown(int32_t pointerIdx,
846 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
847 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
848 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
849 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
850 }
851
852 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
853 int32_t expectedFlags = 0) {
854 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
855 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
856 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
857 }
858
859 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
860 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000861 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
862 expectedFlags);
863 }
864
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100865 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
866 ASSERT_NE(mInputReceiver, nullptr)
867 << "Cannot consume events from a window with no receiver";
868 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
869 }
870
chaviwd1c23182019-12-20 18:44:56 -0800871 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
872 int32_t expectedFlags) {
873 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
874 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
875 expectedFlags);
876 }
877
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700878 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700879 if (mInputReceiver == nullptr) {
880 ADD_FAILURE() << "Invalid receive event on window with no receiver";
881 return std::nullopt;
882 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700883 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 }
885
886 void finishEvent(uint32_t sequenceNum) {
887 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
888 mInputReceiver->finishEvent(sequenceNum);
889 }
890
chaviwaf87b3e2019-10-01 16:59:28 -0700891 InputEvent* consume() {
892 if (mInputReceiver == nullptr) {
893 return nullptr;
894 }
895 return mInputReceiver->consume();
896 }
897
Arthur Hungb92218b2018-08-14 12:00:21 +0800898 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500899 if (mInputReceiver == nullptr &&
900 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
901 return; // Can't receive events if the window does not have input channel
902 }
903 ASSERT_NE(nullptr, mInputReceiver)
904 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -0800905 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800906 }
907
chaviwaf87b3e2019-10-01 16:59:28 -0700908 sp<IBinder> getToken() { return mInfo.token; }
909
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100910 const std::string& getName() { return mName; }
911
chaviwd1c23182019-12-20 18:44:56 -0800912private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100913 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800914 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700915 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800916};
917
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700918std::atomic<int32_t> FakeWindowHandle::sId{1};
919
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700920static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700921 int32_t displayId = ADISPLAY_ID_NONE,
922 int32_t syncMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
923 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800924 KeyEvent event;
925 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
926
927 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800928 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700929 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
930 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800931
932 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700933 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
934 injectionTimeout,
935 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800936}
937
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
939 int32_t displayId = ADISPLAY_ID_NONE) {
940 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
941}
942
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700943static int32_t injectKeyUp(const sp<InputDispatcher>& dispatcher,
944 int32_t displayId = ADISPLAY_ID_NONE) {
945 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
946}
947
Garfield Tandf26e862020-07-01 20:18:19 -0700948class PointerBuilder {
949public:
950 PointerBuilder(int32_t id, int32_t toolType) {
951 mProperties.clear();
952 mProperties.id = id;
953 mProperties.toolType = toolType;
954 mCoords.clear();
955 }
956
957 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
958
959 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
960
961 PointerBuilder& axis(int32_t axis, float value) {
962 mCoords.setAxisValue(axis, value);
963 return *this;
964 }
965
966 PointerProperties buildProperties() const { return mProperties; }
967
968 PointerCoords buildCoords() const { return mCoords; }
969
970private:
971 PointerProperties mProperties;
972 PointerCoords mCoords;
973};
974
975class MotionEventBuilder {
976public:
977 MotionEventBuilder(int32_t action, int32_t source) {
978 mAction = action;
979 mSource = source;
980 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
981 }
982
983 MotionEventBuilder& eventTime(nsecs_t eventTime) {
984 mEventTime = eventTime;
985 return *this;
986 }
987
988 MotionEventBuilder& displayId(int32_t displayId) {
989 mDisplayId = displayId;
990 return *this;
991 }
992
993 MotionEventBuilder& actionButton(int32_t actionButton) {
994 mActionButton = actionButton;
995 return *this;
996 }
997
998 MotionEventBuilder& buttonState(int32_t actionButton) {
999 mActionButton = actionButton;
1000 return *this;
1001 }
1002
1003 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1004 mRawXCursorPosition = rawXCursorPosition;
1005 return *this;
1006 }
1007
1008 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1009 mRawYCursorPosition = rawYCursorPosition;
1010 return *this;
1011 }
1012
1013 MotionEventBuilder& pointer(PointerBuilder pointer) {
1014 mPointers.push_back(pointer);
1015 return *this;
1016 }
1017
1018 MotionEvent build() {
1019 std::vector<PointerProperties> pointerProperties;
1020 std::vector<PointerCoords> pointerCoords;
1021 for (const PointerBuilder& pointer : mPointers) {
1022 pointerProperties.push_back(pointer.buildProperties());
1023 pointerCoords.push_back(pointer.buildCoords());
1024 }
1025
1026 // Set mouse cursor position for the most common cases to avoid boilerplate.
1027 if (mSource == AINPUT_SOURCE_MOUSE &&
1028 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1029 mPointers.size() == 1) {
1030 mRawXCursorPosition = pointerCoords[0].getX();
1031 mRawYCursorPosition = pointerCoords[0].getY();
1032 }
1033
1034 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001035 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001036 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1037 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001038 mButtonState, MotionClassification::NONE, identityTransform,
1039 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1040 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1041 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001042
1043 return event;
1044 }
1045
1046private:
1047 int32_t mAction;
1048 int32_t mSource;
1049 nsecs_t mEventTime;
1050 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1051 int32_t mActionButton{0};
1052 int32_t mButtonState{0};
1053 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1054 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1055
1056 std::vector<PointerBuilder> mPointers;
1057};
1058
1059static int32_t injectMotionEvent(
1060 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1061 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1062 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT) {
1063 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1064 injectionTimeout,
1065 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1066}
1067
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001068static int32_t injectMotionEvent(
1069 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1070 const PointF& position,
1071 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001072 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1073 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1074 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
1075 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001076 MotionEvent event = MotionEventBuilder(action, source)
1077 .displayId(displayId)
1078 .eventTime(eventTime)
1079 .rawXCursorPosition(cursorPosition.x)
1080 .rawYCursorPosition(cursorPosition.y)
1081 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1082 .x(position.x)
1083 .y(position.y))
1084 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001085
1086 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001087 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001088}
1089
Garfield Tan00f511d2019-06-12 16:55:40 -07001090static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001091 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001092 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001093}
1094
Michael Wright3a240c42019-12-10 20:53:41 +00001095static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001096 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001097 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001098}
1099
Jackal Guof9696682018-10-05 12:23:23 +08001100static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1101 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1102 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001103 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1104 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1105 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001106
1107 return args;
1108}
1109
chaviwd1c23182019-12-20 18:44:56 -08001110static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1111 const std::vector<PointF>& points) {
1112 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001113 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1114 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1115 }
1116
chaviwd1c23182019-12-20 18:44:56 -08001117 PointerProperties pointerProperties[pointerCount];
1118 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001119
chaviwd1c23182019-12-20 18:44:56 -08001120 for (size_t i = 0; i < pointerCount; i++) {
1121 pointerProperties[i].clear();
1122 pointerProperties[i].id = i;
1123 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001124
chaviwd1c23182019-12-20 18:44:56 -08001125 pointerCoords[i].clear();
1126 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1127 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1128 }
Jackal Guof9696682018-10-05 12:23:23 +08001129
1130 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1131 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001132 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001133 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1134 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001135 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1136 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001137 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1138 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001139
1140 return args;
1141}
1142
chaviwd1c23182019-12-20 18:44:56 -08001143static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1144 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1145}
1146
Arthur Hungb92218b2018-08-14 12:00:21 +08001147TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001149 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1150 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001151
Arthur Hung72d8dc32020-03-28 00:48:39 +00001152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001153 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1154 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001155 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1156
1157 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001158 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001159}
1160
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001161/**
1162 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1163 * To ensure that window receives only events that were directly inside of it, add
1164 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1165 * when finding touched windows.
1166 * This test serves as a sanity check for the next test, where setInputWindows is
1167 * called twice.
1168 */
1169TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001171 sp<FakeWindowHandle> window =
1172 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1173 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001174 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001175
1176 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1177 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1178 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1179 {50, 50}))
1180 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1181
1182 // Window should receive motion event.
1183 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1184}
1185
1186/**
1187 * Calling setInputWindows twice, with the same info, should not cause any issues.
1188 * To ensure that window receives only events that were directly inside of it, add
1189 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1190 * when finding touched windows.
1191 */
1192TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001194 sp<FakeWindowHandle> window =
1195 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1196 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001197 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001198
1199 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1200 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1201 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1202 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1203 {50, 50}))
1204 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1205
1206 // Window should receive motion event.
1207 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1208}
1209
Arthur Hungb92218b2018-08-14 12:00:21 +08001210// The foreground window should receive the first touch down event.
1211TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001213 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1214 ADISPLAY_ID_DEFAULT);
1215 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1216 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001217
Arthur Hung72d8dc32020-03-28 00:48:39 +00001218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001219 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1220 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001221 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1222
1223 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001224 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001225 windowSecond->assertNoEvents();
1226}
1227
1228TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001230 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1231 ADISPLAY_ID_DEFAULT);
1232 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1233 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001234
Arthur Hung7ab76b12019-01-09 19:17:20 +08001235 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001236 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001237
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001238 // Display should have only one focused window
1239 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001240 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001241
1242 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001243 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1244 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1245
1246 // Focused window should receive event.
1247 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001248 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001249}
1250
Arthur Hung7ab76b12019-01-09 19:17:20 +08001251TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
Chris Yea209fde2020-07-22 13:54:51 -07001252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung7ab76b12019-01-09 19:17:20 +08001253 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1254 ADISPLAY_ID_DEFAULT);
1255 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1256 ADISPLAY_ID_DEFAULT);
1257
1258 // Set focused application.
1259 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1260
1261 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001262 windowTop->setFocus(true);
1263 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001264
Arthur Hung72d8dc32020-03-28 00:48:39 +00001265 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001266 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001267 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1268 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1269
1270 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001271 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001272 windowSecond->assertNoEvents();
1273}
1274
Arthur Hung3b413f22018-10-26 18:05:34 +08001275TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
Chris Yea209fde2020-07-22 13:54:51 -07001276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung3b413f22018-10-26 18:05:34 +08001277
1278 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1279 ADISPLAY_ID_DEFAULT);
1280 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1281 ADISPLAY_ID_DEFAULT);
1282
Arthur Hung832bc4a2019-01-28 11:43:17 +08001283 // Set focused application.
1284 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001285
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001286 windowTop->setFocus(true);
1287 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001288 // Release channel for window is no longer valid.
1289 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001291 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001292
Arthur Hung832bc4a2019-01-28 11:43:17 +08001293 // Test inject a key down, should dispatch to a valid window.
1294 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1295 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001296
1297 // Top window is invalid, so it should not receive any input event.
1298 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001299 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001300}
1301
Garfield Tandf26e862020-07-01 20:18:19 -07001302TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001303 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001304 sp<FakeWindowHandle> windowLeft =
1305 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1306 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001307 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001308 sp<FakeWindowHandle> windowRight =
1309 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1310 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001311 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001312
1313 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1314
1315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1316
1317 // Start cursor position in right window so that we can move the cursor to left window.
1318 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1319 injectMotionEvent(mDispatcher,
1320 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1321 AINPUT_SOURCE_MOUSE)
1322 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1323 .x(900)
1324 .y(400))
1325 .build()));
1326 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1327 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1328 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1329 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1330
1331 // Move cursor into left window
1332 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1333 injectMotionEvent(mDispatcher,
1334 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1335 AINPUT_SOURCE_MOUSE)
1336 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1337 .x(300)
1338 .y(400))
1339 .build()));
1340 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1341 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1342 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1343 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1344 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1345 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1346
1347 // Inject a series of mouse events for a mouse click
1348 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1349 injectMotionEvent(mDispatcher,
1350 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1351 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1352 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1353 .x(300)
1354 .y(400))
1355 .build()));
1356 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1357
1358 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1359 injectMotionEvent(mDispatcher,
1360 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1361 AINPUT_SOURCE_MOUSE)
1362 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1363 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1364 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1365 .x(300)
1366 .y(400))
1367 .build()));
1368 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1369 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1370
1371 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1372 injectMotionEvent(mDispatcher,
1373 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1374 AINPUT_SOURCE_MOUSE)
1375 .buttonState(0)
1376 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1377 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1378 .x(300)
1379 .y(400))
1380 .build()));
1381 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1382 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1383
1384 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1385 injectMotionEvent(mDispatcher,
1386 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1387 .buttonState(0)
1388 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1389 .x(300)
1390 .y(400))
1391 .build()));
1392 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1393
1394 // Move mouse cursor back to right window
1395 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1396 injectMotionEvent(mDispatcher,
1397 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1398 AINPUT_SOURCE_MOUSE)
1399 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1400 .x(900)
1401 .y(400))
1402 .build()));
1403 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1404 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1405 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1406 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1407 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1408 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1409}
1410
1411// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1412// directly in this test.
1413TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001415 sp<FakeWindowHandle> window =
1416 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1417 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001418 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001419
1420 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1421
1422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1423
1424 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1425 injectMotionEvent(mDispatcher,
1426 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1427 AINPUT_SOURCE_MOUSE)
1428 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1429 .x(300)
1430 .y(400))
1431 .build()));
1432 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1433 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1434
1435 // Inject a series of mouse events for a mouse click
1436 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1437 injectMotionEvent(mDispatcher,
1438 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1439 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1440 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1441 .x(300)
1442 .y(400))
1443 .build()));
1444 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1445
1446 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1447 injectMotionEvent(mDispatcher,
1448 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1449 AINPUT_SOURCE_MOUSE)
1450 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1451 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1452 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1453 .x(300)
1454 .y(400))
1455 .build()));
1456 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1457 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1458
1459 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1460 injectMotionEvent(mDispatcher,
1461 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1462 AINPUT_SOURCE_MOUSE)
1463 .buttonState(0)
1464 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1465 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1466 .x(300)
1467 .y(400))
1468 .build()));
1469 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1470 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1471
1472 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1473 injectMotionEvent(mDispatcher,
1474 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1475 .buttonState(0)
1476 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1477 .x(300)
1478 .y(400))
1479 .build()));
1480 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1481
1482 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1483 injectMotionEvent(mDispatcher,
1484 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1485 AINPUT_SOURCE_MOUSE)
1486 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1487 .x(300)
1488 .y(400))
1489 .build()));
1490 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1491 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1492}
1493
Garfield Tan00f511d2019-06-12 16:55:40 -07001494TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001496
1497 sp<FakeWindowHandle> windowLeft =
1498 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1499 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001500 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001501 sp<FakeWindowHandle> windowRight =
1502 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1503 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001504 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001505
1506 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1507
Arthur Hung72d8dc32020-03-28 00:48:39 +00001508 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001509
1510 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1511 // left window. This event should be dispatched to the left window.
1512 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1513 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001514 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001515 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001516 windowRight->assertNoEvents();
1517}
1518
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001519TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001521 sp<FakeWindowHandle> window =
1522 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001523 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001524
Arthur Hung72d8dc32020-03-28 00:48:39 +00001525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001526 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001527
1528 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1529 mDispatcher->notifyKey(&keyArgs);
1530
1531 // Window should receive key down event.
1532 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1533
1534 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1535 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001536 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001537 mDispatcher->notifyDeviceReset(&args);
1538 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1539 AKEY_EVENT_FLAG_CANCELED);
1540}
1541
1542TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001544 sp<FakeWindowHandle> window =
1545 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1546
Arthur Hung72d8dc32020-03-28 00:48:39 +00001547 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001548
1549 NotifyMotionArgs motionArgs =
1550 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1551 ADISPLAY_ID_DEFAULT);
1552 mDispatcher->notifyMotion(&motionArgs);
1553
1554 // Window should receive motion down event.
1555 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1556
1557 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1558 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001559 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001560 mDispatcher->notifyDeviceReset(&args);
1561 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1562 0 /*expectedFlags*/);
1563}
1564
Svet Ganov5d3bc372020-01-26 23:11:07 -08001565TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001567
1568 // Create a couple of windows
1569 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1570 "First Window", ADISPLAY_ID_DEFAULT);
1571 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1572 "Second Window", ADISPLAY_ID_DEFAULT);
1573
1574 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001575 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001576
1577 // Send down to the first window
1578 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1579 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1580 mDispatcher->notifyMotion(&downMotionArgs);
1581 // Only the first window should get the down event
1582 firstWindow->consumeMotionDown();
1583 secondWindow->assertNoEvents();
1584
1585 // Transfer touch focus to the second window
1586 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1587 // The first window gets cancel and the second gets down
1588 firstWindow->consumeMotionCancel();
1589 secondWindow->consumeMotionDown();
1590
1591 // Send up event to the second window
1592 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1593 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1594 mDispatcher->notifyMotion(&upMotionArgs);
1595 // The first window gets no events and the second gets up
1596 firstWindow->assertNoEvents();
1597 secondWindow->consumeMotionUp();
1598}
1599
1600TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001602
1603 PointF touchPoint = {10, 10};
1604
1605 // Create a couple of windows
1606 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1607 "First Window", ADISPLAY_ID_DEFAULT);
1608 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1609 "Second Window", ADISPLAY_ID_DEFAULT);
1610
1611 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001613
1614 // Send down to the first window
1615 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1616 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1617 mDispatcher->notifyMotion(&downMotionArgs);
1618 // Only the first window should get the down event
1619 firstWindow->consumeMotionDown();
1620 secondWindow->assertNoEvents();
1621
1622 // Send pointer down to the first window
1623 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1624 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1625 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1626 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1627 // Only the first window should get the pointer down event
1628 firstWindow->consumeMotionPointerDown(1);
1629 secondWindow->assertNoEvents();
1630
1631 // Transfer touch focus to the second window
1632 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1633 // The first window gets cancel and the second gets down and pointer down
1634 firstWindow->consumeMotionCancel();
1635 secondWindow->consumeMotionDown();
1636 secondWindow->consumeMotionPointerDown(1);
1637
1638 // Send pointer up to the second window
1639 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1640 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1641 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1642 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1643 // The first window gets nothing and the second gets pointer up
1644 firstWindow->assertNoEvents();
1645 secondWindow->consumeMotionPointerUp(1);
1646
1647 // Send up event to the second window
1648 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1649 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1650 mDispatcher->notifyMotion(&upMotionArgs);
1651 // The first window gets nothing and the second gets up
1652 firstWindow->assertNoEvents();
1653 secondWindow->consumeMotionUp();
1654}
1655
1656TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001658
1659 // Create a non touch modal window that supports split touch
1660 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1661 "First Window", ADISPLAY_ID_DEFAULT);
1662 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001663 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1664 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001665
1666 // Create a non touch modal window that supports split touch
1667 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1668 "Second Window", ADISPLAY_ID_DEFAULT);
1669 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001670 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1671 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001672
1673 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001675
1676 PointF pointInFirst = {300, 200};
1677 PointF pointInSecond = {300, 600};
1678
1679 // Send down to the first window
1680 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1681 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1682 mDispatcher->notifyMotion(&firstDownMotionArgs);
1683 // Only the first window should get the down event
1684 firstWindow->consumeMotionDown();
1685 secondWindow->assertNoEvents();
1686
1687 // Send down to the second window
1688 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1689 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1690 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1691 mDispatcher->notifyMotion(&secondDownMotionArgs);
1692 // The first window gets a move and the second a down
1693 firstWindow->consumeMotionMove();
1694 secondWindow->consumeMotionDown();
1695
1696 // Transfer touch focus to the second window
1697 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1698 // The first window gets cancel and the new gets pointer down (it already saw down)
1699 firstWindow->consumeMotionCancel();
1700 secondWindow->consumeMotionPointerDown(1);
1701
1702 // Send pointer up to the second window
1703 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1704 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1705 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1706 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1707 // The first window gets nothing and the second gets pointer up
1708 firstWindow->assertNoEvents();
1709 secondWindow->consumeMotionPointerUp(1);
1710
1711 // Send up event to the second window
1712 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1713 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1714 mDispatcher->notifyMotion(&upMotionArgs);
1715 // The first window gets nothing and the second gets up
1716 firstWindow->assertNoEvents();
1717 secondWindow->consumeMotionUp();
1718}
1719
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001720TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001722 sp<FakeWindowHandle> window =
1723 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1724
1725 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001727
1728 window->consumeFocusEvent(true);
1729
1730 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1731 mDispatcher->notifyKey(&keyArgs);
1732
1733 // Window should receive key down event.
1734 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1735}
1736
1737TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001739 sp<FakeWindowHandle> window =
1740 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1741
Arthur Hung72d8dc32020-03-28 00:48:39 +00001742 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001743
1744 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1745 mDispatcher->notifyKey(&keyArgs);
1746 mDispatcher->waitForIdle();
1747
1748 window->assertNoEvents();
1749}
1750
1751// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1752TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001754 sp<FakeWindowHandle> window =
1755 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1756
Arthur Hung72d8dc32020-03-28 00:48:39 +00001757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001758
1759 // Send key
1760 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1761 mDispatcher->notifyKey(&keyArgs);
1762 // Send motion
1763 NotifyMotionArgs motionArgs =
1764 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1765 ADISPLAY_ID_DEFAULT);
1766 mDispatcher->notifyMotion(&motionArgs);
1767
1768 // Window should receive only the motion event
1769 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1770 window->assertNoEvents(); // Key event or focus event will not be received
1771}
1772
chaviwd1c23182019-12-20 18:44:56 -08001773class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001774public:
1775 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001776 int32_t displayId, bool isGestureMonitor = false) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -05001777 std::unique_ptr<InputChannel> serverChannel, clientChannel;
chaviwd1c23182019-12-20 18:44:56 -08001778 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
Siarhei Vishniakoud2588272020-07-10 11:15:40 -05001779 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
1780 dispatcher->registerInputMonitor(std::move(serverChannel), displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001781 }
1782
chaviwd1c23182019-12-20 18:44:56 -08001783 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1784
1785 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1786 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1787 expectedDisplayId, expectedFlags);
1788 }
1789
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001790 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1791
1792 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1793
chaviwd1c23182019-12-20 18:44:56 -08001794 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1795 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1796 expectedDisplayId, expectedFlags);
1797 }
1798
1799 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1800 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1801 expectedDisplayId, expectedFlags);
1802 }
1803
1804 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1805
1806private:
1807 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001808};
1809
1810// Tests for gesture monitors
1811TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001813 sp<FakeWindowHandle> window =
1814 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001815 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001816
chaviwd1c23182019-12-20 18:44:56 -08001817 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1818 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001819
1820 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1821 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1822 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1823 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001824 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001825}
1826
1827TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001829 sp<FakeWindowHandle> window =
1830 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1831
1832 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001833 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001834
Arthur Hung72d8dc32020-03-28 00:48:39 +00001835 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001836 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001837
chaviwd1c23182019-12-20 18:44:56 -08001838 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1839 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001840
1841 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1842 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1843 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001844 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001845}
1846
1847TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001849 sp<FakeWindowHandle> window =
1850 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001851 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001852
chaviwd1c23182019-12-20 18:44:56 -08001853 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1854 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001855
1856 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1857 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1858 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1859 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001860 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001861
1862 window->releaseChannel();
1863
chaviwd1c23182019-12-20 18:44:56 -08001864 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001865
1866 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1867 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1868 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001869 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001870}
1871
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001872TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1873 FakeMonitorReceiver monitor =
1874 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1875 true /*isGestureMonitor*/);
1876
1877 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1878 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1879 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1880 ASSERT_TRUE(consumeSeq);
1881
1882 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1883 monitor.finishEvent(*consumeSeq);
1884 ASSERT_TRUE(mDispatcher->waitForIdle());
1885}
1886
chaviw81e2bb92019-12-18 15:03:51 -08001887TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08001889 sp<FakeWindowHandle> window =
1890 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1891
Arthur Hung72d8dc32020-03-28 00:48:39 +00001892 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001893
1894 NotifyMotionArgs motionArgs =
1895 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1896 ADISPLAY_ID_DEFAULT);
1897
1898 mDispatcher->notifyMotion(&motionArgs);
1899 // Window should receive motion down event.
1900 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1901
1902 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001903 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001904 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1905 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1906 motionArgs.pointerCoords[0].getX() - 10);
1907
1908 mDispatcher->notifyMotion(&motionArgs);
1909 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1910 0 /*expectedFlags*/);
1911}
1912
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001913/**
1914 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1915 * the device default right away. In the test scenario, we check both the default value,
1916 * and the action of enabling / disabling.
1917 */
1918TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07001919 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001920 sp<FakeWindowHandle> window =
1921 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1922
1923 // Set focused application.
1924 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1925 window->setFocus(true);
1926
1927 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001928 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001929 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1930
1931 SCOPED_TRACE("Remove the window to trigger focus loss");
1932 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001933 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001934 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1935
1936 SCOPED_TRACE("Disable touch mode");
1937 mDispatcher->setInTouchMode(false);
1938 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001939 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001940 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1941
1942 SCOPED_TRACE("Remove the window to trigger focus loss");
1943 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001945 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1946
1947 SCOPED_TRACE("Enable touch mode again");
1948 mDispatcher->setInTouchMode(true);
1949 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001951 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1952
1953 window->assertNoEvents();
1954}
1955
Gang Wange9087892020-01-07 12:17:14 -05001956TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05001958 sp<FakeWindowHandle> window =
1959 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1960
1961 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1962 window->setFocus(true);
1963
Arthur Hung72d8dc32020-03-28 00:48:39 +00001964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001965 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1966
1967 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1968 mDispatcher->notifyKey(&keyArgs);
1969
1970 InputEvent* event = window->consume();
1971 ASSERT_NE(event, nullptr);
1972
1973 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1974 ASSERT_NE(verified, nullptr);
1975 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1976
1977 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1978 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1979 ASSERT_EQ(keyArgs.source, verified->source);
1980 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1981
1982 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1983
1984 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1985 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001986 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1987 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1988 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1989 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1990 ASSERT_EQ(0, verifiedKey.repeatCount);
1991}
1992
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001993TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001995 sp<FakeWindowHandle> window =
1996 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1997
1998 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1999
Arthur Hung72d8dc32020-03-28 00:48:39 +00002000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002001
2002 NotifyMotionArgs motionArgs =
2003 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2004 ADISPLAY_ID_DEFAULT);
2005 mDispatcher->notifyMotion(&motionArgs);
2006
2007 InputEvent* event = window->consume();
2008 ASSERT_NE(event, nullptr);
2009
2010 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2011 ASSERT_NE(verified, nullptr);
2012 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2013
2014 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2015 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2016 EXPECT_EQ(motionArgs.source, verified->source);
2017 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2018
2019 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2020
2021 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2022 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2023 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2024 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2025 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2026 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2027 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2028}
2029
Garfield Tan1c7bc862020-01-28 13:24:04 -08002030class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2031protected:
2032 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2033 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2034
Chris Yea209fde2020-07-22 13:54:51 -07002035 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002036 sp<FakeWindowHandle> mWindow;
2037
2038 virtual void SetUp() override {
2039 mFakePolicy = new FakeInputDispatcherPolicy();
2040 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2041 mDispatcher = new InputDispatcher(mFakePolicy);
2042 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2043 ASSERT_EQ(OK, mDispatcher->start());
2044
2045 setUpWindow();
2046 }
2047
2048 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002049 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002050 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2051
2052 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08002054
2055 mWindow->consumeFocusEvent(true);
2056 }
2057
2058 void sendAndConsumeKeyDown() {
2059 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2060 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2061 mDispatcher->notifyKey(&keyArgs);
2062
2063 // Window should receive key down event.
2064 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2065 }
2066
2067 void expectKeyRepeatOnce(int32_t repeatCount) {
2068 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2069 InputEvent* repeatEvent = mWindow->consume();
2070 ASSERT_NE(nullptr, repeatEvent);
2071
2072 uint32_t eventType = repeatEvent->getType();
2073 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2074
2075 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2076 uint32_t eventAction = repeatKeyEvent->getAction();
2077 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2078 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2079 }
2080
2081 void sendAndConsumeKeyUp() {
2082 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2083 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2084 mDispatcher->notifyKey(&keyArgs);
2085
2086 // Window should receive key down event.
2087 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2088 0 /*expectedFlags*/);
2089 }
2090};
2091
2092TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
2093 sendAndConsumeKeyDown();
2094 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2095 expectKeyRepeatOnce(repeatCount);
2096 }
2097}
2098
2099TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
2100 sendAndConsumeKeyDown();
2101 expectKeyRepeatOnce(1 /*repeatCount*/);
2102 sendAndConsumeKeyUp();
2103 mWindow->assertNoEvents();
2104}
2105
2106TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
2107 sendAndConsumeKeyDown();
2108 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2109 InputEvent* repeatEvent = mWindow->consume();
2110 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2111 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2112 IdGenerator::getSource(repeatEvent->getId()));
2113 }
2114}
2115
2116TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
2117 sendAndConsumeKeyDown();
2118
2119 std::unordered_set<int32_t> idSet;
2120 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2121 InputEvent* repeatEvent = mWindow->consume();
2122 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2123 int32_t id = repeatEvent->getId();
2124 EXPECT_EQ(idSet.end(), idSet.find(id));
2125 idSet.insert(id);
2126 }
2127}
2128
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002129/* Test InputDispatcher for MultiDisplay */
2130class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2131public:
2132 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002133 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002134 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002135
Chris Yea209fde2020-07-22 13:54:51 -07002136 application1 = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002137 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
2138 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002139
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002140 // Set focus window for primary display, but focused display would be second one.
2141 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002142 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002144 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002145
Chris Yea209fde2020-07-22 13:54:51 -07002146 application2 = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002147 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
2148 SECOND_DISPLAY_ID);
2149 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002150 // Set focus display to second one.
2151 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2152 // Set focus window for second display.
2153 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002154 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002155 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002156 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002157 }
2158
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002159 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002160 InputDispatcherTest::TearDown();
2161
Chris Yea209fde2020-07-22 13:54:51 -07002162 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002163 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002164 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002165 windowInSecondary.clear();
2166 }
2167
2168protected:
Chris Yea209fde2020-07-22 13:54:51 -07002169 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002170 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002171 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002172 sp<FakeWindowHandle> windowInSecondary;
2173};
2174
2175TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2176 // Test touch down on primary display.
2177 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08002179 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002180 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002181 windowInSecondary->assertNoEvents();
2182
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002183 // Test touch down on second display.
2184 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2185 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08002186 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2187 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002188 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002189}
2190
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002191TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002192 // Test inject a key down with display id specified.
2193 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2194 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002195 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002196 windowInSecondary->assertNoEvents();
2197
2198 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08002199 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2200 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2201 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002202 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002203
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002204 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002205 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002206
2207 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002208 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2209 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002210
2211 // Test inject a key down, should timeout because of no target window.
2212 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
2213 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
2214 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002215 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002216 windowInSecondary->assertNoEvents();
2217}
2218
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002219// Test per-display input monitors for motion event.
2220TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002221 FakeMonitorReceiver monitorInPrimary =
2222 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2223 FakeMonitorReceiver monitorInSecondary =
2224 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002225
2226 // Test touch down on primary display.
2227 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2228 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2229 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002230 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002231 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002232 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002233 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002234
2235 // Test touch down on second display.
2236 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2237 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2238 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2239 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002240 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002241 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002242 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002243
2244 // Test inject a non-pointer motion event.
2245 // If specific a display, it will dispatch to the focused window of particular display,
2246 // or it will dispatch to the focused window of focused display.
2247 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2248 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2249 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2250 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002251 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002252 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002253 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002254}
2255
2256// Test per-display input monitors for key event.
2257TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
2258 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002259 FakeMonitorReceiver monitorInPrimary =
2260 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2261 FakeMonitorReceiver monitorInSecondary =
2262 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002263
2264 // Test inject a key down.
2265 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2266 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2267 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002268 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002269 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002270 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002271}
2272
Jackal Guof9696682018-10-05 12:23:23 +08002273class InputFilterTest : public InputDispatcherTest {
2274protected:
2275 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2276
2277 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2278 NotifyMotionArgs motionArgs;
2279
2280 motionArgs = generateMotionArgs(
2281 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2282 mDispatcher->notifyMotion(&motionArgs);
2283 motionArgs = generateMotionArgs(
2284 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2285 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002286 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002287 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002288 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002289 } else {
2290 mFakePolicy->assertFilterInputEventWasNotCalled();
2291 }
2292 }
2293
2294 void testNotifyKey(bool expectToBeFiltered) {
2295 NotifyKeyArgs keyArgs;
2296
2297 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2298 mDispatcher->notifyKey(&keyArgs);
2299 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2300 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002301 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002302
2303 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002304 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002305 } else {
2306 mFakePolicy->assertFilterInputEventWasNotCalled();
2307 }
2308 }
2309};
2310
2311// Test InputFilter for MotionEvent
2312TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2313 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2314 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2315 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2316
2317 // Enable InputFilter
2318 mDispatcher->setInputFilterEnabled(true);
2319 // Test touch on both primary and second display, and check if both events are filtered.
2320 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2321 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2322
2323 // Disable InputFilter
2324 mDispatcher->setInputFilterEnabled(false);
2325 // Test touch on both primary and second display, and check if both events aren't filtered.
2326 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2327 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2328}
2329
2330// Test InputFilter for KeyEvent
2331TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2332 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2333 testNotifyKey(/*expectToBeFiltered*/ false);
2334
2335 // Enable InputFilter
2336 mDispatcher->setInputFilterEnabled(true);
2337 // Send a key event, and check if it is filtered.
2338 testNotifyKey(/*expectToBeFiltered*/ true);
2339
2340 // Disable InputFilter
2341 mDispatcher->setInputFilterEnabled(false);
2342 // Send a key event, and check if it isn't filtered.
2343 testNotifyKey(/*expectToBeFiltered*/ false);
2344}
2345
chaviwfd6d3512019-03-25 13:23:49 -07002346class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002347 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002348 InputDispatcherTest::SetUp();
2349
Chris Yea209fde2020-07-22 13:54:51 -07002350 std::shared_ptr<FakeApplicationHandle> application =
2351 std::make_shared<FakeApplicationHandle>();
chaviwfd6d3512019-03-25 13:23:49 -07002352 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2353 ADISPLAY_ID_DEFAULT);
2354 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2355 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2356 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002357 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002358
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002359 mFocusedWindow =
2360 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2361 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002362 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002363
2364 // Set focused application.
2365 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002366 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07002367
2368 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002369 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002370 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002371 }
2372
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002373 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002374 InputDispatcherTest::TearDown();
2375
2376 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002377 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002378 }
2379
2380protected:
2381 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002382 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002383 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002384};
2385
2386// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2387// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2388// the onPointerDownOutsideFocus callback.
2389TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002390 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2391 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2392 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002393 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002394 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002395
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002396 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002397 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2398}
2399
2400// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2401// DOWN on the window that doesn't have focus. Ensure no window received the
2402// onPointerDownOutsideFocus callback.
2403TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002404 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2405 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002406 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002407 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002408
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002409 ASSERT_TRUE(mDispatcher->waitForIdle());
2410 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002411}
2412
2413// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2414// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2415TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2416 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2417 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002418 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002419
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002420 ASSERT_TRUE(mDispatcher->waitForIdle());
2421 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002422}
2423
2424// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2425// DOWN on the window that already has focus. Ensure no window received the
2426// onPointerDownOutsideFocus callback.
2427TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2428 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002429 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2430 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002431 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002432 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002433 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002434
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002435 ASSERT_TRUE(mDispatcher->waitForIdle());
2436 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002437}
2438
chaviwaf87b3e2019-10-01 16:59:28 -07002439// These tests ensures we can send touch events to a single client when there are multiple input
2440// windows that point to the same client token.
2441class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2442 virtual void SetUp() override {
2443 InputDispatcherTest::SetUp();
2444
Chris Yea209fde2020-07-22 13:54:51 -07002445 std::shared_ptr<FakeApplicationHandle> application =
2446 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002447 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2448 ADISPLAY_ID_DEFAULT);
2449 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2450 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
Michael Wright44753b12020-07-08 13:48:11 +01002451 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2452 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002453 mWindow1->setFrame(Rect(0, 0, 100, 100));
2454
2455 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2456 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002457 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2458 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002459 mWindow2->setFrame(Rect(100, 100, 200, 200));
2460
Arthur Hung72d8dc32020-03-28 00:48:39 +00002461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002462 }
2463
2464protected:
2465 sp<FakeWindowHandle> mWindow1;
2466 sp<FakeWindowHandle> mWindow2;
2467
2468 // Helper function to convert the point from screen coordinates into the window's space
2469 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002470 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2471 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002472 }
2473
2474 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2475 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002476 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002477 InputEvent* event = window->consume();
2478
2479 ASSERT_NE(nullptr, event) << name.c_str()
2480 << ": consumer should have returned non-NULL event.";
2481
2482 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2483 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2484 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2485
2486 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2487 EXPECT_EQ(expectedAction, motionEvent.getAction());
2488
2489 for (size_t i = 0; i < points.size(); i++) {
2490 float expectedX = points[i].x;
2491 float expectedY = points[i].y;
2492
2493 EXPECT_EQ(expectedX, motionEvent.getX(i))
2494 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2495 << ", got " << motionEvent.getX(i);
2496 EXPECT_EQ(expectedY, motionEvent.getY(i))
2497 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2498 << ", got " << motionEvent.getY(i);
2499 }
2500 }
chaviw9eaa22c2020-07-01 16:21:27 -07002501
2502 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
2503 std::vector<PointF> expectedPoints) {
2504 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
2505 ADISPLAY_ID_DEFAULT, touchedPoints);
2506 mDispatcher->notifyMotion(&motionArgs);
2507
2508 // Always consume from window1 since it's the window that has the InputReceiver
2509 consumeMotionEvent(mWindow1, action, expectedPoints);
2510 }
chaviwaf87b3e2019-10-01 16:59:28 -07002511};
2512
2513TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2514 // Touch Window 1
2515 PointF touchedPoint = {10, 10};
2516 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002517 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002518
2519 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002520 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002521
2522 // Touch Window 2
2523 touchedPoint = {150, 150};
2524 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002525 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002526}
2527
chaviw9eaa22c2020-07-01 16:21:27 -07002528TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
2529 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07002530 mWindow2->setWindowScale(0.5f, 0.5f);
2531
2532 // Touch Window 1
2533 PointF touchedPoint = {10, 10};
2534 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002535 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002536 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002537 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002538
2539 // Touch Window 2
2540 touchedPoint = {150, 150};
2541 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002542 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
2543 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002544
chaviw9eaa22c2020-07-01 16:21:27 -07002545 // Update the transform so rotation is set
2546 mWindow2->setWindowTransform(0, -1, 1, 0);
2547 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2548 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002549}
2550
chaviw9eaa22c2020-07-01 16:21:27 -07002551TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002552 mWindow2->setWindowScale(0.5f, 0.5f);
2553
2554 // Touch Window 1
2555 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2556 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002557 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002558
2559 // Touch Window 2
2560 int32_t actionPointerDown =
2561 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002562 touchedPoints.push_back(PointF{150, 150});
2563 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2564 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002565
chaviw9eaa22c2020-07-01 16:21:27 -07002566 // Release Window 2
2567 int32_t actionPointerUp =
2568 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2569 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2570 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002571
chaviw9eaa22c2020-07-01 16:21:27 -07002572 // Update the transform so rotation is set for Window 2
2573 mWindow2->setWindowTransform(0, -1, 1, 0);
2574 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2575 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002576}
2577
chaviw9eaa22c2020-07-01 16:21:27 -07002578TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002579 mWindow2->setWindowScale(0.5f, 0.5f);
2580
2581 // Touch Window 1
2582 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2583 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002584 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002585
2586 // Touch Window 2
2587 int32_t actionPointerDown =
2588 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002589 touchedPoints.push_back(PointF{150, 150});
2590 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002591
chaviw9eaa22c2020-07-01 16:21:27 -07002592 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002593
2594 // Move both windows
2595 touchedPoints = {{20, 20}, {175, 175}};
2596 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2597 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2598
chaviw9eaa22c2020-07-01 16:21:27 -07002599 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002600
chaviw9eaa22c2020-07-01 16:21:27 -07002601 // Release Window 2
2602 int32_t actionPointerUp =
2603 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2604 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2605 expectedPoints.pop_back();
2606
2607 // Touch Window 2
2608 mWindow2->setWindowTransform(0, -1, 1, 0);
2609 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2610 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
2611
2612 // Move both windows
2613 touchedPoints = {{20, 20}, {175, 175}};
2614 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2615 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2616
2617 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002618}
2619
2620TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2621 mWindow1->setWindowScale(0.5f, 0.5f);
2622
2623 // Touch Window 1
2624 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2625 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002626 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002627
2628 // Touch Window 2
2629 int32_t actionPointerDown =
2630 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002631 touchedPoints.push_back(PointF{150, 150});
2632 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002633
chaviw9eaa22c2020-07-01 16:21:27 -07002634 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002635
2636 // Move both windows
2637 touchedPoints = {{20, 20}, {175, 175}};
2638 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2639 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2640
chaviw9eaa22c2020-07-01 16:21:27 -07002641 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002642}
2643
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002644class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2645 virtual void SetUp() override {
2646 InputDispatcherTest::SetUp();
2647
Chris Yea209fde2020-07-22 13:54:51 -07002648 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002649 mApplication->setDispatchingTimeout(20ms);
2650 mWindow =
2651 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2652 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002653 mWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002654 mWindow->setFocus(true);
2655 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2656 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002657 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002658
2659 // Set focused application.
2660 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2661
2662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2663 mWindow->consumeFocusEvent(true);
2664 }
2665
2666 virtual void TearDown() override {
2667 InputDispatcherTest::TearDown();
2668 mWindow.clear();
2669 }
2670
2671protected:
Chris Yea209fde2020-07-22 13:54:51 -07002672 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002673 sp<FakeWindowHandle> mWindow;
2674 static constexpr PointF WINDOW_LOCATION = {20, 20};
2675
2676 void tapOnWindow() {
2677 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2678 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2679 WINDOW_LOCATION));
2680 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2681 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2682 WINDOW_LOCATION));
2683 }
2684};
2685
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002686// Send a tap and respond, which should not cause an ANR.
2687TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2688 tapOnWindow();
2689 mWindow->consumeMotionDown();
2690 mWindow->consumeMotionUp();
2691 ASSERT_TRUE(mDispatcher->waitForIdle());
2692 mFakePolicy->assertNotifyAnrWasNotCalled();
2693}
2694
2695// Send a regular key and respond, which should not cause an ANR.
2696TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
2697 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2698 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2699 ASSERT_TRUE(mDispatcher->waitForIdle());
2700 mFakePolicy->assertNotifyAnrWasNotCalled();
2701}
2702
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002703// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002704// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2705// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002706TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2707 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2708 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2709 WINDOW_LOCATION));
2710
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002711 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2712 ASSERT_TRUE(sequenceNum);
2713 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2714 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002715
2716 // The remaining lines are not really needed for the test, but kept as a sanity check
2717 mWindow->finishEvent(*sequenceNum);
2718 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2719 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002720 ASSERT_TRUE(mDispatcher->waitForIdle());
2721}
2722
2723// Send a key to the app and have the app not respond right away.
2724TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2725 // Inject a key, and don't respond - expect that ANR is called.
2726 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2727 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2728 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002729 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002730 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002731 ASSERT_TRUE(mDispatcher->waitForIdle());
2732}
2733
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002734// We have a focused application, but no focused window
2735TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
2736 mWindow->setFocus(false);
2737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2738 mWindow->consumeFocusEvent(false);
2739
2740 // taps on the window work as normal
2741 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2742 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2743 WINDOW_LOCATION));
2744 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2745 mDispatcher->waitForIdle();
2746 mFakePolicy->assertNotifyAnrWasNotCalled();
2747
2748 // Once a focused event arrives, we get an ANR for this application
2749 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2750 // injection times out (instead of failing).
2751 const int32_t result =
2752 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2753 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2754 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2755 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2756 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2757 ASSERT_TRUE(mDispatcher->waitForIdle());
2758}
2759
2760// We have a focused application, but no focused window
2761// If the policy wants to keep waiting on the focused window to be added, make sure
2762// that this timeout extension is honored and ANR is raised again.
2763TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
2764 mWindow->setFocus(false);
2765 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2766 mWindow->consumeFocusEvent(false);
2767 const std::chrono::duration timeout = 5ms;
2768 mFakePolicy->setAnrTimeout(timeout);
2769
2770 // Once a focused event arrives, we get an ANR for this application
2771 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2772 // injection times out (instead of failing).
2773 const 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 const std::chrono::duration appTimeout =
2778 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2779 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2780
2781 // After the extended time has passed, ANR should be raised again
2782 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2783
2784 // If we stop extending the timeout, dispatcher should go to idle.
2785 // Another ANR may be raised during this time
2786 mFakePolicy->setAnrTimeout(0ms);
2787 ASSERT_TRUE(mDispatcher->waitForIdle());
2788}
2789
2790// We have a focused application, but no focused window
2791TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
2792 mWindow->setFocus(false);
2793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2794 mWindow->consumeFocusEvent(false);
2795
2796 // Once a focused event arrives, we get an ANR for this application
2797 const int32_t result =
2798 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2799 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2800 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2801
2802 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2803 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2804
2805 // Future focused events get dropped right away
2806 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, injectKeyDown(mDispatcher));
2807 ASSERT_TRUE(mDispatcher->waitForIdle());
2808 mWindow->assertNoEvents();
2809}
2810
2811/**
2812 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2813 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2814 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2815 * the ANR mechanism should still work.
2816 *
2817 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2818 * DOWN event, while not responding on the second one.
2819 */
2820TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2821 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2822 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2823 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2824 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2825 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2826 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2827
2828 // Now send ACTION_UP, with identical timestamp
2829 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2830 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2831 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2832 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2833 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2834
2835 // We have now sent down and up. Let's consume first event and then ANR on the second.
2836 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2837 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2838 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2839}
2840
2841// If an app is not responding to a key event, gesture monitors should continue to receive
2842// new motion events
2843TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
2844 FakeMonitorReceiver monitor =
2845 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2846 true /*isGestureMonitor*/);
2847
2848 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
2849 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2850 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
2851
2852 // Stuck on the ACTION_UP
2853 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2854 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2855
2856 // New tap will go to the gesture monitor, but not to the window
2857 tapOnWindow();
2858 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2859 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2860
2861 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2862 mDispatcher->waitForIdle();
2863 mWindow->assertNoEvents();
2864 monitor.assertNoEvents();
2865}
2866
2867// If an app is not responding to a motion event, gesture monitors should continue to receive
2868// new motion events
2869TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
2870 FakeMonitorReceiver monitor =
2871 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2872 true /*isGestureMonitor*/);
2873
2874 tapOnWindow();
2875 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2876 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2877
2878 mWindow->consumeMotionDown();
2879 // Stuck on the ACTION_UP
2880 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2881 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2882
2883 // New tap will go to the gesture monitor, but not to the window
2884 tapOnWindow();
2885 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2886 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2887
2888 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2889 mDispatcher->waitForIdle();
2890 mWindow->assertNoEvents();
2891 monitor.assertNoEvents();
2892}
2893
2894// If a window is unresponsive, then you get anr. if the window later catches up and starts to
2895// process events, you don't get an anr. When the window later becomes unresponsive again, you
2896// get an ANR again.
2897// 1. tap -> block on ACTION_UP -> receive ANR
2898// 2. consume all pending events (= queue becomes healthy again)
2899// 3. tap again -> block on ACTION_UP again -> receive ANR second time
2900TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
2901 tapOnWindow();
2902
2903 mWindow->consumeMotionDown();
2904 // Block on ACTION_UP
2905 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2906 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2907 mWindow->consumeMotionUp(); // Now the connection should be healthy again
2908 mDispatcher->waitForIdle();
2909 mWindow->assertNoEvents();
2910
2911 tapOnWindow();
2912 mWindow->consumeMotionDown();
2913 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2914 mWindow->consumeMotionUp();
2915
2916 mDispatcher->waitForIdle();
2917 mWindow->assertNoEvents();
2918}
2919
2920// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
2921// is honored
2922TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
2923 const std::chrono::duration timeout = 5ms;
2924 mFakePolicy->setAnrTimeout(timeout);
2925
2926 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2927 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2928 WINDOW_LOCATION));
2929
2930 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2931 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
2932 mWindow->getToken());
2933
2934 // Since the policy wanted to extend ANR, make sure it is called again after the extension
2935 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2936 mFakePolicy->setAnrTimeout(0ms);
2937 std::this_thread::sleep_for(windowTimeout);
2938 // We are not checking if ANR has been called, because it may have been called again by the
2939 // time we set the timeout to 0
2940
2941 // When the policy finally says stop, we should get ACTION_CANCEL
2942 mWindow->consumeMotionDown();
2943 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2944 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2945 mWindow->assertNoEvents();
2946}
2947
2948/**
2949 * If a window is processing a motion event, and then a key event comes in, the key event should
2950 * not to to the focused window until the motion is processed.
2951 *
2952 * Warning!!!
2953 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2954 * and the injection timeout that we specify when injecting the key.
2955 * We must have the injection timeout (10ms) be smaller than
2956 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2957 *
2958 * If that value changes, this test should also change.
2959 */
2960TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
2961 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2963
2964 tapOnWindow();
2965 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2966 ASSERT_TRUE(downSequenceNum);
2967 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2968 ASSERT_TRUE(upSequenceNum);
2969 // Don't finish the events yet, and send a key
2970 // Injection will "succeed" because we will eventually give up and send the key to the focused
2971 // window even if motions are still being processed. But because the injection timeout is short,
2972 // we will receive INJECTION_TIMED_OUT as the result.
2973
2974 int32_t result =
2975 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2976 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2977 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2978 // Key will not be sent to the window, yet, because the window is still processing events
2979 // and the key remains pending, waiting for the touch events to be processed
2980 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2981 ASSERT_FALSE(keySequenceNum);
2982
2983 std::this_thread::sleep_for(500ms);
2984 // if we wait long enough though, dispatcher will give up, and still send the key
2985 // to the focused window, even though we have not yet finished the motion event
2986 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2987 mWindow->finishEvent(*downSequenceNum);
2988 mWindow->finishEvent(*upSequenceNum);
2989}
2990
2991/**
2992 * If a window is processing a motion event, and then a key event comes in, the key event should
2993 * not go to the focused window until the motion is processed.
2994 * If then a new motion comes in, then the pending key event should be going to the currently
2995 * focused window right away.
2996 */
2997TEST_F(InputDispatcherSingleWindowAnr,
2998 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
2999 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3001
3002 tapOnWindow();
3003 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3004 ASSERT_TRUE(downSequenceNum);
3005 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3006 ASSERT_TRUE(upSequenceNum);
3007 // Don't finish the events yet, and send a key
3008 // Injection is async, so it will succeed
3009 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3010 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
3011 ADISPLAY_ID_DEFAULT, INPUT_EVENT_INJECTION_SYNC_NONE));
3012 // At this point, key is still pending, and should not be sent to the application yet.
3013 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3014 ASSERT_FALSE(keySequenceNum);
3015
3016 // Now tap down again. It should cause the pending key to go to the focused window right away.
3017 tapOnWindow();
3018 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3019 // the other events yet. We can finish events in any order.
3020 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3021 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3022 mWindow->consumeMotionDown();
3023 mWindow->consumeMotionUp();
3024 mWindow->assertNoEvents();
3025}
3026
3027class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3028 virtual void SetUp() override {
3029 InputDispatcherTest::SetUp();
3030
Chris Yea209fde2020-07-22 13:54:51 -07003031 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003032 mApplication->setDispatchingTimeout(10ms);
3033 mUnfocusedWindow =
3034 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3035 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3036 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3037 // window.
3038 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003039 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3040 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3041 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003042
3043 mFocusedWindow =
3044 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003045 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003046 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003047 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3048 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003049
3050 // Set focused application.
3051 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3052 mFocusedWindow->setFocus(true);
3053
3054 // Expect one focus window exist in display.
3055 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3056 mFocusedWindow->consumeFocusEvent(true);
3057 }
3058
3059 virtual void TearDown() override {
3060 InputDispatcherTest::TearDown();
3061
3062 mUnfocusedWindow.clear();
3063 mFocusedWindow.clear();
3064 }
3065
3066protected:
Chris Yea209fde2020-07-22 13:54:51 -07003067 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003068 sp<FakeWindowHandle> mUnfocusedWindow;
3069 sp<FakeWindowHandle> mFocusedWindow;
3070 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3071 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3072 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3073
3074 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3075
3076 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3077
3078private:
3079 void tap(const PointF& location) {
3080 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3081 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3082 location));
3083 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3084 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3085 location));
3086 }
3087};
3088
3089// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3090// should be ANR'd first.
3091TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
3092 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3093 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3094 FOCUSED_WINDOW_LOCATION))
3095 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
3096 mFocusedWindow->consumeMotionDown();
3097 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3098 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3099 // We consumed all events, so no ANR
3100 ASSERT_TRUE(mDispatcher->waitForIdle());
3101 mFakePolicy->assertNotifyAnrWasNotCalled();
3102
3103 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3104 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3105 FOCUSED_WINDOW_LOCATION));
3106 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3107 ASSERT_TRUE(unfocusedSequenceNum);
3108 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
3109 ASSERT_TRUE(focusedSequenceNum);
3110
3111 const std::chrono::duration timeout =
3112 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3113 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3114 mFocusedWindow->getToken());
3115
3116 mFocusedWindow->finishEvent(*focusedSequenceNum);
3117 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
3118 ASSERT_TRUE(mDispatcher->waitForIdle());
3119}
3120
3121// If we have 2 windows with identical timeouts that are both unresponsive,
3122// it doesn't matter which order they should have ANR.
3123// But we should receive ANR for both.
3124TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3125 // Set the timeout for unfocused window to match the focused window
3126 mUnfocusedWindow->setDispatchingTimeout(10ms);
3127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3128
3129 tapOnFocusedWindow();
3130 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Chris Yea209fde2020-07-22 13:54:51 -07003131 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData1 =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003132 mFakePolicy->getNotifyAnrData(10ms);
Chris Yea209fde2020-07-22 13:54:51 -07003133 std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData2 =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003134 mFakePolicy->getNotifyAnrData(0ms);
3135
3136 // We don't know which window will ANR first. But both of them should happen eventually.
3137 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
3138 mFocusedWindow->getToken() == anrData2.second);
3139 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
3140 mUnfocusedWindow->getToken() == anrData2.second);
3141
3142 ASSERT_TRUE(mDispatcher->waitForIdle());
3143 mFakePolicy->assertNotifyAnrWasNotCalled();
3144}
3145
3146// If a window is already not responding, the second tap on the same window should be ignored.
3147// We should also log an error to account for the dropped event (not tested here).
3148// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3149TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3150 tapOnFocusedWindow();
3151 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3152 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3153 // Receive the events, but don't respond
3154 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3155 ASSERT_TRUE(downEventSequenceNum);
3156 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3157 ASSERT_TRUE(upEventSequenceNum);
3158 const std::chrono::duration timeout =
3159 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3160 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3161 mFocusedWindow->getToken());
3162
3163 // Tap once again
3164 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
3165 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3166 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3167 FOCUSED_WINDOW_LOCATION));
3168 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3169 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3170 FOCUSED_WINDOW_LOCATION));
3171 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3172 // valid touch target
3173 mUnfocusedWindow->assertNoEvents();
3174
3175 // Consume the first tap
3176 mFocusedWindow->finishEvent(*downEventSequenceNum);
3177 mFocusedWindow->finishEvent(*upEventSequenceNum);
3178 ASSERT_TRUE(mDispatcher->waitForIdle());
3179 // The second tap did not go to the focused window
3180 mFocusedWindow->assertNoEvents();
3181 // should not have another ANR after the window just became healthy again
3182 mFakePolicy->assertNotifyAnrWasNotCalled();
3183}
3184
3185// If you tap outside of all windows, there will not be ANR
3186TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
3187 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3188 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3189 LOCATION_OUTSIDE_ALL_WINDOWS));
3190 ASSERT_TRUE(mDispatcher->waitForIdle());
3191 mFakePolicy->assertNotifyAnrWasNotCalled();
3192}
3193
3194// Since the focused window is paused, tapping on it should not produce any events
3195TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3196 mFocusedWindow->setPaused(true);
3197 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3198
3199 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3200 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3201 FOCUSED_WINDOW_LOCATION));
3202
3203 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3204 ASSERT_TRUE(mDispatcher->waitForIdle());
3205 // Should not ANR because the window is paused, and touches shouldn't go to it
3206 mFakePolicy->assertNotifyAnrWasNotCalled();
3207
3208 mFocusedWindow->assertNoEvents();
3209 mUnfocusedWindow->assertNoEvents();
3210}
3211
3212/**
3213 * If a window is processing a motion event, and then a key event comes in, the key event should
3214 * not to to the focused window until the motion is processed.
3215 * If a different window becomes focused at this time, the key should go to that window instead.
3216 *
3217 * Warning!!!
3218 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3219 * and the injection timeout that we specify when injecting the key.
3220 * We must have the injection timeout (10ms) be smaller than
3221 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3222 *
3223 * If that value changes, this test should also change.
3224 */
3225TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3226 // Set a long ANR timeout to prevent it from triggering
3227 mFocusedWindow->setDispatchingTimeout(2s);
3228 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3229
3230 tapOnUnfocusedWindow();
3231 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3232 ASSERT_TRUE(downSequenceNum);
3233 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3234 ASSERT_TRUE(upSequenceNum);
3235 // Don't finish the events yet, and send a key
3236 // Injection will succeed because we will eventually give up and send the key to the focused
3237 // window even if motions are still being processed.
3238
3239 int32_t result =
3240 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
3241 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
3242 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
3243 // Key will not be sent to the window, yet, because the window is still processing events
3244 // and the key remains pending, waiting for the touch events to be processed
3245 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3246 ASSERT_FALSE(keySequenceNum);
3247
3248 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
3249 mFocusedWindow->setFocus(false);
3250 mUnfocusedWindow->setFocus(true);
3251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3252
3253 // Focus events should precede the key events
3254 mUnfocusedWindow->consumeFocusEvent(true);
3255 mFocusedWindow->consumeFocusEvent(false);
3256
3257 // Finish the tap events, which should unblock dispatcher
3258 mUnfocusedWindow->finishEvent(*downSequenceNum);
3259 mUnfocusedWindow->finishEvent(*upSequenceNum);
3260
3261 // Now that all queues are cleared and no backlog in the connections, the key event
3262 // can finally go to the newly focused "mUnfocusedWindow".
3263 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3264 mFocusedWindow->assertNoEvents();
3265 mUnfocusedWindow->assertNoEvents();
3266}
3267
3268// When the touch stream is split across 2 windows, and one of them does not respond,
3269// then ANR should be raised and the touch should be canceled for the unresponsive window.
3270// The other window should not be affected by that.
3271TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3272 // Touch Window 1
3273 NotifyMotionArgs motionArgs =
3274 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3275 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3276 mDispatcher->notifyMotion(&motionArgs);
3277 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3278 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3279
3280 // Touch Window 2
3281 int32_t actionPointerDown =
3282 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3283
3284 motionArgs =
3285 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3286 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3287 mDispatcher->notifyMotion(&motionArgs);
3288
3289 const std::chrono::duration timeout =
3290 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3291 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3292 mFocusedWindow->getToken());
3293
3294 mUnfocusedWindow->consumeMotionDown();
3295 mFocusedWindow->consumeMotionDown();
3296 // Focused window may or may not receive ACTION_MOVE
3297 // But it should definitely receive ACTION_CANCEL due to the ANR
3298 InputEvent* event;
3299 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3300 ASSERT_TRUE(moveOrCancelSequenceNum);
3301 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3302 ASSERT_NE(nullptr, event);
3303 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3304 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3305 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3306 mFocusedWindow->consumeMotionCancel();
3307 } else {
3308 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3309 }
3310
3311 ASSERT_TRUE(mDispatcher->waitForIdle());
3312 mUnfocusedWindow->assertNoEvents();
3313 mFocusedWindow->assertNoEvents();
3314}
3315
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003316// These tests ensure we cannot send touch events to a window that's positioned behind a window
3317// that has feature NO_INPUT_CHANNEL.
3318// Layout:
3319// Top (closest to user)
3320// mNoInputWindow (above all windows)
3321// mBottomWindow
3322// Bottom (furthest from user)
3323class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3324 virtual void SetUp() override {
3325 InputDispatcherTest::SetUp();
3326
3327 mApplication = std::make_shared<FakeApplicationHandle>();
3328 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3329 "Window without input channel", ADISPLAY_ID_DEFAULT,
3330 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3331
3332 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3333 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3334 // It's perfectly valid for this window to not have an associated input channel
3335
3336 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3337 ADISPLAY_ID_DEFAULT);
3338 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3339
3340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3341 }
3342
3343protected:
3344 std::shared_ptr<FakeApplicationHandle> mApplication;
3345 sp<FakeWindowHandle> mNoInputWindow;
3346 sp<FakeWindowHandle> mBottomWindow;
3347};
3348
3349TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3350 PointF touchedPoint = {10, 10};
3351
3352 NotifyMotionArgs motionArgs =
3353 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3354 ADISPLAY_ID_DEFAULT, {touchedPoint});
3355 mDispatcher->notifyMotion(&motionArgs);
3356
3357 mNoInputWindow->assertNoEvents();
3358 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
3359 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
3360 // and therefore should prevent mBottomWindow from receiving touches
3361 mBottomWindow->assertNoEvents();
3362}
3363
3364/**
3365 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
3366 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
3367 */
3368TEST_F(InputDispatcherMultiWindowOcclusionTests,
3369 NoInputChannelFeature_DropsTouchesWithValidChannel) {
3370 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3371 "Window with input channel and NO_INPUT_CHANNEL",
3372 ADISPLAY_ID_DEFAULT);
3373
3374 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3375 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3376 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3377
3378 PointF touchedPoint = {10, 10};
3379
3380 NotifyMotionArgs motionArgs =
3381 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3382 ADISPLAY_ID_DEFAULT, {touchedPoint});
3383 mDispatcher->notifyMotion(&motionArgs);
3384
3385 mNoInputWindow->assertNoEvents();
3386 mBottomWindow->assertNoEvents();
3387}
3388
Garfield Tane84e6f92019-08-29 17:28:41 -07003389} // namespace android::inputdispatcher