blob: 89314e141cdb027dc2c0a4ca927900c2c35806d8 [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.
127 void assertNotifyAnrWasCalled(std::chrono::nanoseconds timeout,
128 const sp<InputApplicationHandle>& expectedApplication,
129 const sp<IBinder>& expectedToken) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700130 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData;
131 ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
132 ASSERT_EQ(expectedApplication, anrData.first);
133 ASSERT_EQ(expectedToken, anrData.second);
134 }
135
136 std::pair<sp<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
137 std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700138 const std::chrono::time_point start = std::chrono::steady_clock::now();
139 std::unique_lock lock(mLock);
140 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
141 android::base::ScopedLockAssertion assumeLocked(mLock);
142
143 // If there is an ANR, Dispatcher won't be idle because there are still events
144 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
145 // before checking if ANR was called.
146 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
147 // it some time to act. 100ms seems reasonable.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700148 mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
149 return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
150 });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700151 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700152 if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
153 ADD_FAILURE() << "Did not receive ANR callback";
154 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700155 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
156 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700157 if (std::chrono::abs(timeout - waited) > 100ms) {
158 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
159 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
160 << "ms, but waited "
161 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
162 << "ms instead";
163 }
164 std::pair<sp<InputApplicationHandle>, sp<IBinder>> result =
165 std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
166 mAnrApplications.pop();
167 mAnrWindowTokens.pop();
168 return result;
169 }
170
171 void assertNotifyAnrWasNotCalled() {
172 std::scoped_lock lock(mLock);
173 ASSERT_TRUE(mAnrApplications.empty());
174 ASSERT_TRUE(mAnrWindowTokens.empty());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700175 }
176
Garfield Tan1c7bc862020-01-28 13:24:04 -0800177 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
178 mConfig.keyRepeatTimeout = timeout;
179 mConfig.keyRepeatDelay = delay;
180 }
181
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700182 void setAnrTimeout(std::chrono::nanoseconds timeout) { mAnrTimeout = timeout; }
183
Michael Wrightd02c5b62014-02-10 15:10:22 -0800184private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700185 std::mutex mLock;
186 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
187 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
188 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
189 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800190
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700191 // ANR handling
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700192 std::queue<sp<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
193 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700194 std::condition_variable mNotifyAnr;
195 std::chrono::nanoseconds mAnrTimeout = 0ms;
196
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 virtual void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700198 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800199 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800200 }
201
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500202 std::chrono::nanoseconds notifyAnr(const sp<InputApplicationHandle>& application,
203 const sp<IBinder>& windowToken,
204 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205 std::scoped_lock lock(mLock);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700206 mAnrApplications.push(application);
207 mAnrWindowTokens.push(windowToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700208 mNotifyAnr.notify_all();
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500209 return mAnrTimeout;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210 }
211
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700212 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700214 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700215
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700216 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217 *outConfig = mConfig;
218 }
219
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800220 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800222 switch (inputEvent->getType()) {
223 case AINPUT_EVENT_TYPE_KEY: {
224 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800225 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800226 break;
227 }
228
229 case AINPUT_EVENT_TYPE_MOTION: {
230 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800231 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800232 break;
233 }
234 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800235 return true;
236 }
237
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700238 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800239
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700240 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800241
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700242 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
243 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800244 return 0;
245 }
246
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700247 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
248 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249 return false;
250 }
251
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800252 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
253 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700254 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800255 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
256 * essentially a passthrough for notifySwitch.
257 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800258 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800259 }
260
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700261 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700263 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800264 return false;
265 }
Jackal Guof9696682018-10-05 12:23:23 +0800266
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700267 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700268 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700269 mOnPointerDownToken = newToken;
270 }
271
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800272 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
273 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700274 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800275 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
276 ASSERT_EQ(mFilteredEvent->getType(), type);
277
278 if (type == AINPUT_EVENT_TYPE_KEY) {
279 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
280 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
281 EXPECT_EQ(keyEvent.getAction(), action);
282 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
283 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
284 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
285 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
286 EXPECT_EQ(motionEvent.getAction(), action);
287 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
288 } else {
289 FAIL() << "Unknown type: " << type;
290 }
291
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800292 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800293 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800294};
295
Gang Wang342c9272020-01-13 13:15:04 -0500296// --- HmacKeyManagerTest ---
297
298class HmacKeyManagerTest : public testing::Test {
299protected:
300 HmacKeyManager mHmacKeyManager;
301};
302
303/**
304 * Ensure that separate calls to sign the same data are generating the same key.
305 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
306 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
307 * tests.
308 */
309TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
310 KeyEvent event = getTestKeyEvent();
311 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
312
313 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
314 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
315 ASSERT_EQ(hmac1, hmac2);
316}
317
318/**
319 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
320 */
321TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
322 KeyEvent event = getTestKeyEvent();
323 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
324 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
325
326 verifiedEvent.deviceId += 1;
327 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
328
329 verifiedEvent.source += 1;
330 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
331
332 verifiedEvent.eventTimeNanos += 1;
333 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
334
335 verifiedEvent.displayId += 1;
336 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
337
338 verifiedEvent.action += 1;
339 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
340
341 verifiedEvent.downTimeNanos += 1;
342 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
343
344 verifiedEvent.flags += 1;
345 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
346
347 verifiedEvent.keyCode += 1;
348 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
349
350 verifiedEvent.scanCode += 1;
351 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
352
353 verifiedEvent.metaState += 1;
354 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
355
356 verifiedEvent.repeatCount += 1;
357 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
358}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800359
360// --- InputDispatcherTest ---
361
362class InputDispatcherTest : public testing::Test {
363protected:
364 sp<FakeInputDispatcherPolicy> mFakePolicy;
365 sp<InputDispatcher> mDispatcher;
366
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700367 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368 mFakePolicy = new FakeInputDispatcherPolicy();
369 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800370 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
371 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700372 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800373 }
374
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700375 virtual void TearDown() override {
376 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800377 mFakePolicy.clear();
378 mDispatcher.clear();
379 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700380
381 /**
382 * Used for debugging when writing the test
383 */
384 void dumpDispatcherState() {
385 std::string dump;
386 mDispatcher->dump(dump);
387 std::stringstream ss(dump);
388 std::string to;
389
390 while (std::getline(ss, to, '\n')) {
391 ALOGE("%s", to.c_str());
392 }
393 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800394};
395
396
397TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
398 KeyEvent event;
399
400 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800401 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
402 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600403 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
404 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700405 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
406 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
407 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800408 << "Should reject key events with undefined action.";
409
410 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800411 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
412 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600413 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700414 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
415 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
416 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800417 << "Should reject key events with ACTION_MULTIPLE.";
418}
419
420TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
421 MotionEvent event;
422 PointerProperties pointerProperties[MAX_POINTERS + 1];
423 PointerCoords pointerCoords[MAX_POINTERS + 1];
424 for (int i = 0; i <= MAX_POINTERS; i++) {
425 pointerProperties[i].clear();
426 pointerProperties[i].id = i;
427 pointerCoords[i].clear();
428 }
429
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800430 // Some constants commonly used below
431 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
432 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
433 constexpr int32_t metaState = AMETA_NONE;
434 constexpr MotionClassification classification = MotionClassification::NONE;
435
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800437 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600438 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
439 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
440 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700441 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700442 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
443 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
444 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800445 << "Should reject motion events with undefined action.";
446
447 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800448 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700449 AMOTION_EVENT_ACTION_POINTER_DOWN |
450 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600451 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
452 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
453 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700454 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700455 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
456 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
457 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800458 << "Should reject motion events with pointer down index too large.";
459
Garfield Tanfbe732e2020-01-24 11:26:14 -0800460 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700461 AMOTION_EVENT_ACTION_POINTER_DOWN |
462 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600463 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
464 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
465 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700466 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700467 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
468 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
469 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800470 << "Should reject motion events with pointer down index too small.";
471
472 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800473 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700474 AMOTION_EVENT_ACTION_POINTER_UP |
475 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600476 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
477 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
478 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700479 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700480 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
481 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
482 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800483 << "Should reject motion events with pointer up index too large.";
484
Garfield Tanfbe732e2020-01-24 11:26:14 -0800485 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700486 AMOTION_EVENT_ACTION_POINTER_UP |
487 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600488 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
489 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
490 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700491 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700492 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
493 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
494 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800495 << "Should reject motion events with pointer up index too small.";
496
497 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800498 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
499 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
500 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
501 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
502 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700503 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700504 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
505 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
506 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800507 << "Should reject motion events with 0 pointers.";
508
Garfield Tanfbe732e2020-01-24 11:26:14 -0800509 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
510 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
511 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
512 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
513 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,
524 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
525 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
526 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700527 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700528 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
529 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
530 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800531 << "Should reject motion events with pointer ids less than 0.";
532
533 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800534 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
535 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
536 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
537 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
538 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700539 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700540 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
541 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
542 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
544
545 // Rejects motion events with duplicate pointer ids.
546 pointerProperties[0].id = 1;
547 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800548 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
549 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
550 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
551 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
552 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700553 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700554 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
555 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
556 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800557 << "Should reject motion events with duplicate pointer ids.";
558}
559
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800560/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
561
562TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
563 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800564 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800565 mDispatcher->notifyConfigurationChanged(&args);
566 ASSERT_TRUE(mDispatcher->waitForIdle());
567
568 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
569}
570
571TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800572 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
573 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800574 mDispatcher->notifySwitch(&args);
575
576 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
577 args.policyFlags |= POLICY_FLAG_TRUSTED;
578 mFakePolicy->assertNotifySwitchWasCalled(args);
579}
580
Arthur Hungb92218b2018-08-14 12:00:21 +0800581// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700582static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700583static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800584
585class FakeApplicationHandle : public InputApplicationHandle {
586public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700587 FakeApplicationHandle() {
588 mInfo.name = "Fake Application";
589 mInfo.token = new BBinder();
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500590 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700591 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800592 virtual ~FakeApplicationHandle() {}
593
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700594 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800595 return true;
596 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700597
598 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500599 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700600 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800601};
602
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800603class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800604public:
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500605 explicit FakeInputReceiver(const std::shared_ptr<InputChannel>& clientChannel,
606 const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800607 : mName(name) {
608 mConsumer = std::make_unique<InputConsumer>(clientChannel);
609 }
610
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800611 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700612 InputEvent* event;
613 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
614 if (!consumeSeq) {
615 return nullptr;
616 }
617 finishEvent(*consumeSeq);
618 return event;
619 }
620
621 /**
622 * Receive an event without acknowledging it.
623 * Return the sequence number that could later be used to send finished signal.
624 */
625 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800626 uint32_t consumeSeq;
627 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800628
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800629 std::chrono::time_point start = std::chrono::steady_clock::now();
630 status_t status = WOULD_BLOCK;
631 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800632 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800633 &event);
634 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
635 if (elapsed > 100ms) {
636 break;
637 }
638 }
639
640 if (status == WOULD_BLOCK) {
641 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700642 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800643 }
644
645 if (status != OK) {
646 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700647 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800648 }
649 if (event == nullptr) {
650 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700651 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800652 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700653 if (outEvent != nullptr) {
654 *outEvent = event;
655 }
656 return consumeSeq;
657 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800658
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700659 /**
660 * To be used together with "receiveEvent" to complete the consumption of an event.
661 */
662 void finishEvent(uint32_t consumeSeq) {
663 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
664 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800665 }
666
667 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
668 int32_t expectedFlags) {
669 InputEvent* event = consume();
670
671 ASSERT_NE(nullptr, event) << mName.c_str()
672 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800673 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700674 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800675 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800676
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800677 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800678
Tiger Huang8664f8c2018-10-11 19:14:35 +0800679 switch (expectedEventType) {
680 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800681 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
682 EXPECT_EQ(expectedAction, keyEvent.getAction());
683 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800684 break;
685 }
686 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800687 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
688 EXPECT_EQ(expectedAction, motionEvent.getAction());
689 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800690 break;
691 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100692 case AINPUT_EVENT_TYPE_FOCUS: {
693 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
694 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800695 default: {
696 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
697 }
698 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800699 }
700
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100701 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
702 InputEvent* event = consume();
703 ASSERT_NE(nullptr, event) << mName.c_str()
704 << ": consumer should have returned non-NULL event.";
705 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
706 << "Got " << inputEventTypeToString(event->getType())
707 << " event instead of FOCUS event";
708
709 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
710 << mName.c_str() << ": event displayId should always be NONE.";
711
712 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
713 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
714 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
715 }
716
chaviwd1c23182019-12-20 18:44:56 -0800717 void assertNoEvents() {
718 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700719 if (event == nullptr) {
720 return;
721 }
722 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
723 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
724 ADD_FAILURE() << "Received key event "
725 << KeyEvent::actionToString(keyEvent.getAction());
726 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
727 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
728 ADD_FAILURE() << "Received motion event "
729 << MotionEvent::actionToString(motionEvent.getAction());
730 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
731 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
732 ADD_FAILURE() << "Received focus event, hasFocus = "
733 << (focusEvent.getHasFocus() ? "true" : "false");
734 }
735 FAIL() << mName.c_str()
736 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800737 }
738
739 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
740
741protected:
742 std::unique_ptr<InputConsumer> mConsumer;
743 PreallocatedInputEventFactory mEventFactory;
744
745 std::string mName;
746};
747
748class FakeWindowHandle : public InputWindowHandle {
749public:
750 static const int32_t WIDTH = 600;
751 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800752
753 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
754 const sp<InputDispatcher>& dispatcher, const std::string name,
755 int32_t displayId, sp<IBinder> token = nullptr)
756 : mName(name) {
757 if (token == nullptr) {
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500758 std::shared_ptr<InputChannel> serverChannel, clientChannel;
chaviwd1c23182019-12-20 18:44:56 -0800759 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
760 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
761 dispatcher->registerInputChannel(serverChannel);
762 token = serverChannel->getConnectionToken();
763 }
764
765 inputApplicationHandle->updateInfo();
766 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
767
768 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700769 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800770 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100771 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500772 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800773 mInfo.frameLeft = 0;
774 mInfo.frameTop = 0;
775 mInfo.frameRight = WIDTH;
776 mInfo.frameBottom = HEIGHT;
777 mInfo.globalScaleFactor = 1.0;
778 mInfo.touchableRegion.clear();
779 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
780 mInfo.visible = true;
781 mInfo.canReceiveKeys = true;
782 mInfo.hasFocus = false;
783 mInfo.hasWallpaper = false;
784 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800785 mInfo.ownerPid = INJECTOR_PID;
786 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800787 mInfo.displayId = displayId;
788 }
789
790 virtual bool updateInfo() { return true; }
791
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100792 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800793
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700794 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500795 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700796 }
797
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700798 void setPaused(bool paused) { mInfo.paused = paused; }
799
chaviwd1c23182019-12-20 18:44:56 -0800800 void setFrame(const Rect& frame) {
801 mInfo.frameLeft = frame.left;
802 mInfo.frameTop = frame.top;
803 mInfo.frameRight = frame.right;
804 mInfo.frameBottom = frame.bottom;
805 mInfo.touchableRegion.clear();
806 mInfo.addTouchableRegion(frame);
807 }
808
Michael Wright44753b12020-07-08 13:48:11 +0100809 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800810
chaviwaf87b3e2019-10-01 16:59:28 -0700811 void setWindowScale(float xScale, float yScale) {
812 mInfo.windowXScale = xScale;
813 mInfo.windowYScale = yScale;
814 }
815
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800816 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
817 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
818 expectedFlags);
819 }
820
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700821 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
822 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
823 }
824
Svet Ganov5d3bc372020-01-26 23:11:07 -0800825 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
826 int32_t expectedFlags = 0) {
827 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
828 expectedFlags);
829 }
830
831 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
832 int32_t expectedFlags = 0) {
833 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
834 expectedFlags);
835 }
836
837 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
838 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800839 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
840 expectedFlags);
841 }
842
Svet Ganov5d3bc372020-01-26 23:11:07 -0800843 void consumeMotionPointerDown(int32_t pointerIdx,
844 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
845 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
846 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
847 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
848 }
849
850 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
851 int32_t expectedFlags = 0) {
852 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
853 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
854 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
855 }
856
857 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
858 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000859 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
860 expectedFlags);
861 }
862
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100863 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
864 ASSERT_NE(mInputReceiver, nullptr)
865 << "Cannot consume events from a window with no receiver";
866 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
867 }
868
chaviwd1c23182019-12-20 18:44:56 -0800869 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
870 int32_t expectedFlags) {
871 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
872 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
873 expectedFlags);
874 }
875
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700876 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700877 if (mInputReceiver == nullptr) {
878 ADD_FAILURE() << "Invalid receive event on window with no receiver";
879 return std::nullopt;
880 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700881 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882 }
883
884 void finishEvent(uint32_t sequenceNum) {
885 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
886 mInputReceiver->finishEvent(sequenceNum);
887 }
888
chaviwaf87b3e2019-10-01 16:59:28 -0700889 InputEvent* consume() {
890 if (mInputReceiver == nullptr) {
891 return nullptr;
892 }
893 return mInputReceiver->consume();
894 }
895
Arthur Hungb92218b2018-08-14 12:00:21 +0800896 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800897 ASSERT_NE(mInputReceiver, nullptr)
898 << "Call 'assertNoEvents' on a window with an InputReceiver";
899 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800900 }
901
chaviwaf87b3e2019-10-01 16:59:28 -0700902 sp<IBinder> getToken() { return mInfo.token; }
903
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100904 const std::string& getName() { return mName; }
905
chaviwd1c23182019-12-20 18:44:56 -0800906private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100907 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800908 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700909 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800910};
911
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700912std::atomic<int32_t> FakeWindowHandle::sId{1};
913
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700915 int32_t displayId = ADISPLAY_ID_NONE,
916 int32_t syncMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
917 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800918 KeyEvent event;
919 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
920
921 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800922 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700923 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
924 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800925
926 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700927 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
928 injectionTimeout,
929 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800930}
931
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700932static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
933 int32_t displayId = ADISPLAY_ID_NONE) {
934 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
935}
936
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700937static int32_t injectKeyUp(const sp<InputDispatcher>& dispatcher,
938 int32_t displayId = ADISPLAY_ID_NONE) {
939 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
940}
941
Garfield Tandf26e862020-07-01 20:18:19 -0700942class PointerBuilder {
943public:
944 PointerBuilder(int32_t id, int32_t toolType) {
945 mProperties.clear();
946 mProperties.id = id;
947 mProperties.toolType = toolType;
948 mCoords.clear();
949 }
950
951 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
952
953 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
954
955 PointerBuilder& axis(int32_t axis, float value) {
956 mCoords.setAxisValue(axis, value);
957 return *this;
958 }
959
960 PointerProperties buildProperties() const { return mProperties; }
961
962 PointerCoords buildCoords() const { return mCoords; }
963
964private:
965 PointerProperties mProperties;
966 PointerCoords mCoords;
967};
968
969class MotionEventBuilder {
970public:
971 MotionEventBuilder(int32_t action, int32_t source) {
972 mAction = action;
973 mSource = source;
974 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
975 }
976
977 MotionEventBuilder& eventTime(nsecs_t eventTime) {
978 mEventTime = eventTime;
979 return *this;
980 }
981
982 MotionEventBuilder& displayId(int32_t displayId) {
983 mDisplayId = displayId;
984 return *this;
985 }
986
987 MotionEventBuilder& actionButton(int32_t actionButton) {
988 mActionButton = actionButton;
989 return *this;
990 }
991
992 MotionEventBuilder& buttonState(int32_t actionButton) {
993 mActionButton = actionButton;
994 return *this;
995 }
996
997 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
998 mRawXCursorPosition = rawXCursorPosition;
999 return *this;
1000 }
1001
1002 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1003 mRawYCursorPosition = rawYCursorPosition;
1004 return *this;
1005 }
1006
1007 MotionEventBuilder& pointer(PointerBuilder pointer) {
1008 mPointers.push_back(pointer);
1009 return *this;
1010 }
1011
1012 MotionEvent build() {
1013 std::vector<PointerProperties> pointerProperties;
1014 std::vector<PointerCoords> pointerCoords;
1015 for (const PointerBuilder& pointer : mPointers) {
1016 pointerProperties.push_back(pointer.buildProperties());
1017 pointerCoords.push_back(pointer.buildCoords());
1018 }
1019
1020 // Set mouse cursor position for the most common cases to avoid boilerplate.
1021 if (mSource == AINPUT_SOURCE_MOUSE &&
1022 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1023 mPointers.size() == 1) {
1024 mRawXCursorPosition = pointerCoords[0].getX();
1025 mRawYCursorPosition = pointerCoords[0].getY();
1026 }
1027
1028 MotionEvent event;
1029 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1030 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
1031 mButtonState, MotionClassification::NONE, /* xScale */ 1, /* yScale */ 1,
1032 /* xOffset */ 0,
1033 /* yOffset */ 0, /* xPrecision */ 0, /* yPrecision */ 0,
1034 mRawXCursorPosition, mRawYCursorPosition, mEventTime, mEventTime,
1035 mPointers.size(), pointerProperties.data(), pointerCoords.data());
1036
1037 return event;
1038 }
1039
1040private:
1041 int32_t mAction;
1042 int32_t mSource;
1043 nsecs_t mEventTime;
1044 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1045 int32_t mActionButton{0};
1046 int32_t mButtonState{0};
1047 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1048 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1049
1050 std::vector<PointerBuilder> mPointers;
1051};
1052
1053static int32_t injectMotionEvent(
1054 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1055 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1056 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT) {
1057 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1058 injectionTimeout,
1059 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1060}
1061
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001062static int32_t injectMotionEvent(
1063 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1064 const PointF& position,
1065 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001066 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1067 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1068 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
1069 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001070 MotionEvent event = MotionEventBuilder(action, source)
1071 .displayId(displayId)
1072 .eventTime(eventTime)
1073 .rawXCursorPosition(cursorPosition.x)
1074 .rawYCursorPosition(cursorPosition.y)
1075 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1076 .x(position.x)
1077 .y(position.y))
1078 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001079
1080 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001081 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001082}
1083
Garfield Tan00f511d2019-06-12 16:55:40 -07001084static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001085 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001086 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001087}
1088
Michael Wright3a240c42019-12-10 20:53:41 +00001089static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001090 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001091 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001092}
1093
Jackal Guof9696682018-10-05 12:23:23 +08001094static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1095 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1096 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001097 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1098 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1099 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001100
1101 return args;
1102}
1103
chaviwd1c23182019-12-20 18:44:56 -08001104static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1105 const std::vector<PointF>& points) {
1106 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001107 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1108 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1109 }
1110
chaviwd1c23182019-12-20 18:44:56 -08001111 PointerProperties pointerProperties[pointerCount];
1112 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001113
chaviwd1c23182019-12-20 18:44:56 -08001114 for (size_t i = 0; i < pointerCount; i++) {
1115 pointerProperties[i].clear();
1116 pointerProperties[i].id = i;
1117 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001118
chaviwd1c23182019-12-20 18:44:56 -08001119 pointerCoords[i].clear();
1120 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1121 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1122 }
Jackal Guof9696682018-10-05 12:23:23 +08001123
1124 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1125 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001126 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001127 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1128 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001129 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1130 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001131 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1132 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001133
1134 return args;
1135}
1136
chaviwd1c23182019-12-20 18:44:56 -08001137static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1138 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1139}
1140
Arthur Hungb92218b2018-08-14 12:00:21 +08001141TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
1142 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001143 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1144 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001145
Arthur Hung72d8dc32020-03-28 00:48:39 +00001146 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001147 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1148 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001149 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1150
1151 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001152 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001153}
1154
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001155/**
1156 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1157 * To ensure that window receives only events that were directly inside of it, add
1158 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1159 * when finding touched windows.
1160 * This test serves as a sanity check for the next test, where setInputWindows is
1161 * called twice.
1162 */
1163TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
1164 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1165 sp<FakeWindowHandle> window =
1166 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1167 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001168 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001169
1170 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1171 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1172 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1173 {50, 50}))
1174 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1175
1176 // Window should receive motion event.
1177 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1178}
1179
1180/**
1181 * Calling setInputWindows twice, with the same info, should not cause any issues.
1182 * To ensure that window receives only events that were directly inside of it, add
1183 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1184 * when finding touched windows.
1185 */
1186TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
1187 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1188 sp<FakeWindowHandle> window =
1189 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1190 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001191 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001192
1193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1195 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1196 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1197 {50, 50}))
1198 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1199
1200 // Window should receive motion event.
1201 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1202}
1203
Arthur Hungb92218b2018-08-14 12:00:21 +08001204// The foreground window should receive the first touch down event.
1205TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
1206 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001207 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1208 ADISPLAY_ID_DEFAULT);
1209 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1210 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001211
Arthur Hung72d8dc32020-03-28 00:48:39 +00001212 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001213 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1214 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001215 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1216
1217 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001218 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001219 windowSecond->assertNoEvents();
1220}
1221
1222TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
1223 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001224 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1225 ADISPLAY_ID_DEFAULT);
1226 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1227 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001228
Arthur Hung7ab76b12019-01-09 19:17:20 +08001229 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001230 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001231
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001232 // Display should have only one focused window
1233 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001234 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001235
1236 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001237 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1238 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1239
1240 // Focused window should receive event.
1241 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001242 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001243}
1244
Arthur Hung7ab76b12019-01-09 19:17:20 +08001245TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
1246 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1247 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1248 ADISPLAY_ID_DEFAULT);
1249 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1250 ADISPLAY_ID_DEFAULT);
1251
1252 // Set focused application.
1253 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1254
1255 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001256 windowTop->setFocus(true);
1257 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001258
Arthur Hung72d8dc32020-03-28 00:48:39 +00001259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001260 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001261 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1262 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1263
1264 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001265 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001266 windowSecond->assertNoEvents();
1267}
1268
Arthur Hung3b413f22018-10-26 18:05:34 +08001269TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1270 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1271
1272 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1273 ADISPLAY_ID_DEFAULT);
1274 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1275 ADISPLAY_ID_DEFAULT);
1276
Arthur Hung832bc4a2019-01-28 11:43:17 +08001277 // Set focused application.
1278 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001279
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001280 windowTop->setFocus(true);
1281 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001282 // Release channel for window is no longer valid.
1283 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001284 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001285 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001286
Arthur Hung832bc4a2019-01-28 11:43:17 +08001287 // Test inject a key down, should dispatch to a valid window.
1288 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1289 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001290
1291 // Top window is invalid, so it should not receive any input event.
1292 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001293 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001294}
1295
Garfield Tandf26e862020-07-01 20:18:19 -07001296TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
1297 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1298 sp<FakeWindowHandle> windowLeft =
1299 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1300 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001301 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001302 sp<FakeWindowHandle> windowRight =
1303 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1304 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001305 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001306
1307 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1308
1309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1310
1311 // Start cursor position in right window so that we can move the cursor to left window.
1312 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1313 injectMotionEvent(mDispatcher,
1314 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1315 AINPUT_SOURCE_MOUSE)
1316 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1317 .x(900)
1318 .y(400))
1319 .build()));
1320 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1321 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1322 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1323 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1324
1325 // Move cursor into left window
1326 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1327 injectMotionEvent(mDispatcher,
1328 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1329 AINPUT_SOURCE_MOUSE)
1330 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1331 .x(300)
1332 .y(400))
1333 .build()));
1334 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1335 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1336 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1337 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1338 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1339 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1340
1341 // Inject a series of mouse events for a mouse click
1342 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1343 injectMotionEvent(mDispatcher,
1344 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1345 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1346 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1347 .x(300)
1348 .y(400))
1349 .build()));
1350 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1351
1352 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1353 injectMotionEvent(mDispatcher,
1354 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1355 AINPUT_SOURCE_MOUSE)
1356 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1357 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1358 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1359 .x(300)
1360 .y(400))
1361 .build()));
1362 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1363 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1364
1365 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1366 injectMotionEvent(mDispatcher,
1367 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1368 AINPUT_SOURCE_MOUSE)
1369 .buttonState(0)
1370 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1371 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1372 .x(300)
1373 .y(400))
1374 .build()));
1375 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1376 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1377
1378 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1379 injectMotionEvent(mDispatcher,
1380 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1381 .buttonState(0)
1382 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1383 .x(300)
1384 .y(400))
1385 .build()));
1386 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1387
1388 // Move mouse cursor back to right window
1389 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1390 injectMotionEvent(mDispatcher,
1391 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1392 AINPUT_SOURCE_MOUSE)
1393 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1394 .x(900)
1395 .y(400))
1396 .build()));
1397 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1398 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1399 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1400 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1401 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1402 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1403}
1404
1405// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1406// directly in this test.
1407TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
1408 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1409 sp<FakeWindowHandle> window =
1410 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1411 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001412 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001413
1414 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1415
1416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1417
1418 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1419 injectMotionEvent(mDispatcher,
1420 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1421 AINPUT_SOURCE_MOUSE)
1422 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1423 .x(300)
1424 .y(400))
1425 .build()));
1426 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1427 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1428
1429 // Inject a series of mouse events for a mouse click
1430 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1431 injectMotionEvent(mDispatcher,
1432 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1433 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1434 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1435 .x(300)
1436 .y(400))
1437 .build()));
1438 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1439
1440 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1441 injectMotionEvent(mDispatcher,
1442 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1443 AINPUT_SOURCE_MOUSE)
1444 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1445 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1446 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1447 .x(300)
1448 .y(400))
1449 .build()));
1450 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1451 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1452
1453 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1454 injectMotionEvent(mDispatcher,
1455 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1456 AINPUT_SOURCE_MOUSE)
1457 .buttonState(0)
1458 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1459 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1460 .x(300)
1461 .y(400))
1462 .build()));
1463 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1464 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1465
1466 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1467 injectMotionEvent(mDispatcher,
1468 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1469 .buttonState(0)
1470 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1471 .x(300)
1472 .y(400))
1473 .build()));
1474 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1475
1476 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1477 injectMotionEvent(mDispatcher,
1478 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1479 AINPUT_SOURCE_MOUSE)
1480 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1481 .x(300)
1482 .y(400))
1483 .build()));
1484 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1485 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1486}
1487
Garfield Tan00f511d2019-06-12 16:55:40 -07001488TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1489 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1490
1491 sp<FakeWindowHandle> windowLeft =
1492 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1493 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001494 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001495 sp<FakeWindowHandle> windowRight =
1496 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1497 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001498 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001499
1500 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1501
Arthur Hung72d8dc32020-03-28 00:48:39 +00001502 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001503
1504 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1505 // left window. This event should be dispatched to the left window.
1506 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1507 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001508 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001509 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001510 windowRight->assertNoEvents();
1511}
1512
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001513TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1514 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1515 sp<FakeWindowHandle> window =
1516 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001517 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001518
Arthur Hung72d8dc32020-03-28 00:48:39 +00001519 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001520 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001521
1522 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1523 mDispatcher->notifyKey(&keyArgs);
1524
1525 // Window should receive key down event.
1526 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1527
1528 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1529 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001530 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001531 mDispatcher->notifyDeviceReset(&args);
1532 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1533 AKEY_EVENT_FLAG_CANCELED);
1534}
1535
1536TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1537 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1538 sp<FakeWindowHandle> window =
1539 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1540
Arthur Hung72d8dc32020-03-28 00:48:39 +00001541 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001542
1543 NotifyMotionArgs motionArgs =
1544 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1545 ADISPLAY_ID_DEFAULT);
1546 mDispatcher->notifyMotion(&motionArgs);
1547
1548 // Window should receive motion down event.
1549 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1550
1551 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1552 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001553 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001554 mDispatcher->notifyDeviceReset(&args);
1555 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1556 0 /*expectedFlags*/);
1557}
1558
Svet Ganov5d3bc372020-01-26 23:11:07 -08001559TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1560 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1561
1562 // Create a couple of windows
1563 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1564 "First Window", ADISPLAY_ID_DEFAULT);
1565 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1566 "Second Window", ADISPLAY_ID_DEFAULT);
1567
1568 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001569 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001570
1571 // Send down to the first window
1572 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1573 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1574 mDispatcher->notifyMotion(&downMotionArgs);
1575 // Only the first window should get the down event
1576 firstWindow->consumeMotionDown();
1577 secondWindow->assertNoEvents();
1578
1579 // Transfer touch focus to the second window
1580 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1581 // The first window gets cancel and the second gets down
1582 firstWindow->consumeMotionCancel();
1583 secondWindow->consumeMotionDown();
1584
1585 // Send up event to the second window
1586 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1587 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1588 mDispatcher->notifyMotion(&upMotionArgs);
1589 // The first window gets no events and the second gets up
1590 firstWindow->assertNoEvents();
1591 secondWindow->consumeMotionUp();
1592}
1593
1594TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1595 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1596
1597 PointF touchPoint = {10, 10};
1598
1599 // Create a couple of windows
1600 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1601 "First Window", ADISPLAY_ID_DEFAULT);
1602 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1603 "Second Window", ADISPLAY_ID_DEFAULT);
1604
1605 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001606 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001607
1608 // Send down to the first window
1609 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1610 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1611 mDispatcher->notifyMotion(&downMotionArgs);
1612 // Only the first window should get the down event
1613 firstWindow->consumeMotionDown();
1614 secondWindow->assertNoEvents();
1615
1616 // Send pointer down to the first window
1617 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1618 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1619 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1620 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1621 // Only the first window should get the pointer down event
1622 firstWindow->consumeMotionPointerDown(1);
1623 secondWindow->assertNoEvents();
1624
1625 // Transfer touch focus to the second window
1626 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1627 // The first window gets cancel and the second gets down and pointer down
1628 firstWindow->consumeMotionCancel();
1629 secondWindow->consumeMotionDown();
1630 secondWindow->consumeMotionPointerDown(1);
1631
1632 // Send pointer up to the second window
1633 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1634 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1635 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1636 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1637 // The first window gets nothing and the second gets pointer up
1638 firstWindow->assertNoEvents();
1639 secondWindow->consumeMotionPointerUp(1);
1640
1641 // Send up event to the second window
1642 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1643 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1644 mDispatcher->notifyMotion(&upMotionArgs);
1645 // The first window gets nothing and the second gets up
1646 firstWindow->assertNoEvents();
1647 secondWindow->consumeMotionUp();
1648}
1649
1650TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1651 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1652
1653 // Create a non touch modal window that supports split touch
1654 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1655 "First Window", ADISPLAY_ID_DEFAULT);
1656 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001657 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1658 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001659
1660 // Create a non touch modal window that supports split touch
1661 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1662 "Second Window", ADISPLAY_ID_DEFAULT);
1663 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001664 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1665 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001666
1667 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001668 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001669
1670 PointF pointInFirst = {300, 200};
1671 PointF pointInSecond = {300, 600};
1672
1673 // Send down to the first window
1674 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1675 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1676 mDispatcher->notifyMotion(&firstDownMotionArgs);
1677 // Only the first window should get the down event
1678 firstWindow->consumeMotionDown();
1679 secondWindow->assertNoEvents();
1680
1681 // Send down to the second window
1682 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1683 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1684 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1685 mDispatcher->notifyMotion(&secondDownMotionArgs);
1686 // The first window gets a move and the second a down
1687 firstWindow->consumeMotionMove();
1688 secondWindow->consumeMotionDown();
1689
1690 // Transfer touch focus to the second window
1691 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1692 // The first window gets cancel and the new gets pointer down (it already saw down)
1693 firstWindow->consumeMotionCancel();
1694 secondWindow->consumeMotionPointerDown(1);
1695
1696 // Send pointer up to the second window
1697 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1698 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1699 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1700 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1701 // The first window gets nothing and the second gets pointer up
1702 firstWindow->assertNoEvents();
1703 secondWindow->consumeMotionPointerUp(1);
1704
1705 // Send up event to the second window
1706 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1707 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1708 mDispatcher->notifyMotion(&upMotionArgs);
1709 // The first window gets nothing and the second gets up
1710 firstWindow->assertNoEvents();
1711 secondWindow->consumeMotionUp();
1712}
1713
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001714TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1715 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1716 sp<FakeWindowHandle> window =
1717 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1718
1719 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001720 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001721
1722 window->consumeFocusEvent(true);
1723
1724 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1725 mDispatcher->notifyKey(&keyArgs);
1726
1727 // Window should receive key down event.
1728 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1729}
1730
1731TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1732 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1733 sp<FakeWindowHandle> window =
1734 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1735
Arthur Hung72d8dc32020-03-28 00:48:39 +00001736 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001737
1738 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1739 mDispatcher->notifyKey(&keyArgs);
1740 mDispatcher->waitForIdle();
1741
1742 window->assertNoEvents();
1743}
1744
1745// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1746TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1747 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1748 sp<FakeWindowHandle> window =
1749 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1750
Arthur Hung72d8dc32020-03-28 00:48:39 +00001751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001752
1753 // Send key
1754 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1755 mDispatcher->notifyKey(&keyArgs);
1756 // Send motion
1757 NotifyMotionArgs motionArgs =
1758 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1759 ADISPLAY_ID_DEFAULT);
1760 mDispatcher->notifyMotion(&motionArgs);
1761
1762 // Window should receive only the motion event
1763 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1764 window->assertNoEvents(); // Key event or focus event will not be received
1765}
1766
chaviwd1c23182019-12-20 18:44:56 -08001767class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001768public:
1769 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001770 int32_t displayId, bool isGestureMonitor = false) {
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -05001771 std::shared_ptr<InputChannel> serverChannel, clientChannel;
chaviwd1c23182019-12-20 18:44:56 -08001772 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1773 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1774 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001775 }
1776
chaviwd1c23182019-12-20 18:44:56 -08001777 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1778
1779 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1780 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1781 expectedDisplayId, expectedFlags);
1782 }
1783
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001784 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1785
1786 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1787
chaviwd1c23182019-12-20 18:44:56 -08001788 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1789 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1790 expectedDisplayId, expectedFlags);
1791 }
1792
1793 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1794 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1795 expectedDisplayId, expectedFlags);
1796 }
1797
1798 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1799
1800private:
1801 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001802};
1803
1804// Tests for gesture monitors
1805TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1806 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1807 sp<FakeWindowHandle> window =
1808 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001809 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001810
chaviwd1c23182019-12-20 18:44:56 -08001811 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1812 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001813
1814 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1815 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1816 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1817 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001818 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001819}
1820
1821TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1822 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1823 sp<FakeWindowHandle> window =
1824 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1825
1826 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001827 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001828
Arthur Hung72d8dc32020-03-28 00:48:39 +00001829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001830 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001831
chaviwd1c23182019-12-20 18:44:56 -08001832 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1833 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001834
1835 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1836 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1837 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001838 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001839}
1840
1841TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1842 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1843 sp<FakeWindowHandle> window =
1844 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001846
chaviwd1c23182019-12-20 18:44:56 -08001847 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1848 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001849
1850 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1851 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1852 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1853 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001854 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001855
1856 window->releaseChannel();
1857
chaviwd1c23182019-12-20 18:44:56 -08001858 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001859
1860 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1861 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1862 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001863 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001864}
1865
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001866TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1867 FakeMonitorReceiver monitor =
1868 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1869 true /*isGestureMonitor*/);
1870
1871 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1872 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1873 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1874 ASSERT_TRUE(consumeSeq);
1875
1876 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1877 monitor.finishEvent(*consumeSeq);
1878 ASSERT_TRUE(mDispatcher->waitForIdle());
1879}
1880
chaviw81e2bb92019-12-18 15:03:51 -08001881TEST_F(InputDispatcherTest, TestMoveEvent) {
1882 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1883 sp<FakeWindowHandle> window =
1884 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1885
Arthur Hung72d8dc32020-03-28 00:48:39 +00001886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001887
1888 NotifyMotionArgs motionArgs =
1889 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1890 ADISPLAY_ID_DEFAULT);
1891
1892 mDispatcher->notifyMotion(&motionArgs);
1893 // Window should receive motion down event.
1894 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1895
1896 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001897 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001898 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1899 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1900 motionArgs.pointerCoords[0].getX() - 10);
1901
1902 mDispatcher->notifyMotion(&motionArgs);
1903 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1904 0 /*expectedFlags*/);
1905}
1906
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001907/**
1908 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1909 * the device default right away. In the test scenario, we check both the default value,
1910 * and the action of enabling / disabling.
1911 */
1912TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1913 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1914 sp<FakeWindowHandle> window =
1915 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1916
1917 // Set focused application.
1918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1919 window->setFocus(true);
1920
1921 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001923 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1924
1925 SCOPED_TRACE("Remove the window to trigger focus loss");
1926 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001927 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001928 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1929
1930 SCOPED_TRACE("Disable touch mode");
1931 mDispatcher->setInTouchMode(false);
1932 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001933 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001934 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1935
1936 SCOPED_TRACE("Remove the window to trigger focus loss");
1937 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001939 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1940
1941 SCOPED_TRACE("Enable touch mode again");
1942 mDispatcher->setInTouchMode(true);
1943 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001945 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1946
1947 window->assertNoEvents();
1948}
1949
Gang Wange9087892020-01-07 12:17:14 -05001950TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1951 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1952 sp<FakeWindowHandle> window =
1953 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1954
1955 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1956 window->setFocus(true);
1957
Arthur Hung72d8dc32020-03-28 00:48:39 +00001958 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001959 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1960
1961 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1962 mDispatcher->notifyKey(&keyArgs);
1963
1964 InputEvent* event = window->consume();
1965 ASSERT_NE(event, nullptr);
1966
1967 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1968 ASSERT_NE(verified, nullptr);
1969 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1970
1971 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1972 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1973 ASSERT_EQ(keyArgs.source, verified->source);
1974 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1975
1976 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1977
1978 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1979 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001980 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1981 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1982 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1983 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1984 ASSERT_EQ(0, verifiedKey.repeatCount);
1985}
1986
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001987TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1988 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1989 sp<FakeWindowHandle> window =
1990 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1991
1992 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1993
Arthur Hung72d8dc32020-03-28 00:48:39 +00001994 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001995
1996 NotifyMotionArgs motionArgs =
1997 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1998 ADISPLAY_ID_DEFAULT);
1999 mDispatcher->notifyMotion(&motionArgs);
2000
2001 InputEvent* event = window->consume();
2002 ASSERT_NE(event, nullptr);
2003
2004 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2005 ASSERT_NE(verified, nullptr);
2006 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2007
2008 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2009 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2010 EXPECT_EQ(motionArgs.source, verified->source);
2011 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2012
2013 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2014
2015 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2016 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2017 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2018 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2019 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2020 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2021 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2022}
2023
Garfield Tan1c7bc862020-01-28 13:24:04 -08002024class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2025protected:
2026 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2027 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2028
2029 sp<FakeApplicationHandle> mApp;
2030 sp<FakeWindowHandle> mWindow;
2031
2032 virtual void SetUp() override {
2033 mFakePolicy = new FakeInputDispatcherPolicy();
2034 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2035 mDispatcher = new InputDispatcher(mFakePolicy);
2036 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2037 ASSERT_EQ(OK, mDispatcher->start());
2038
2039 setUpWindow();
2040 }
2041
2042 void setUpWindow() {
2043 mApp = new FakeApplicationHandle();
2044 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2045
2046 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002047 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08002048
2049 mWindow->consumeFocusEvent(true);
2050 }
2051
2052 void sendAndConsumeKeyDown() {
2053 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2054 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2055 mDispatcher->notifyKey(&keyArgs);
2056
2057 // Window should receive key down event.
2058 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2059 }
2060
2061 void expectKeyRepeatOnce(int32_t repeatCount) {
2062 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2063 InputEvent* repeatEvent = mWindow->consume();
2064 ASSERT_NE(nullptr, repeatEvent);
2065
2066 uint32_t eventType = repeatEvent->getType();
2067 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2068
2069 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2070 uint32_t eventAction = repeatKeyEvent->getAction();
2071 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2072 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2073 }
2074
2075 void sendAndConsumeKeyUp() {
2076 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2077 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2078 mDispatcher->notifyKey(&keyArgs);
2079
2080 // Window should receive key down event.
2081 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2082 0 /*expectedFlags*/);
2083 }
2084};
2085
2086TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
2087 sendAndConsumeKeyDown();
2088 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2089 expectKeyRepeatOnce(repeatCount);
2090 }
2091}
2092
2093TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
2094 sendAndConsumeKeyDown();
2095 expectKeyRepeatOnce(1 /*repeatCount*/);
2096 sendAndConsumeKeyUp();
2097 mWindow->assertNoEvents();
2098}
2099
2100TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
2101 sendAndConsumeKeyDown();
2102 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2103 InputEvent* repeatEvent = mWindow->consume();
2104 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2105 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2106 IdGenerator::getSource(repeatEvent->getId()));
2107 }
2108}
2109
2110TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
2111 sendAndConsumeKeyDown();
2112
2113 std::unordered_set<int32_t> idSet;
2114 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2115 InputEvent* repeatEvent = mWindow->consume();
2116 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2117 int32_t id = repeatEvent->getId();
2118 EXPECT_EQ(idSet.end(), idSet.find(id));
2119 idSet.insert(id);
2120 }
2121}
2122
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002123/* Test InputDispatcher for MultiDisplay */
2124class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2125public:
2126 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002127 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002128 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002129
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002130 application1 = new FakeApplicationHandle();
2131 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
2132 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002133
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002134 // Set focus window for primary display, but focused display would be second one.
2135 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002136 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002137 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002138 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002139
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002140 application2 = new FakeApplicationHandle();
2141 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
2142 SECOND_DISPLAY_ID);
2143 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002144 // Set focus display to second one.
2145 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2146 // Set focus window for second display.
2147 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002148 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002149 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002150 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002151 }
2152
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002153 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002154 InputDispatcherTest::TearDown();
2155
2156 application1.clear();
2157 windowInPrimary.clear();
2158 application2.clear();
2159 windowInSecondary.clear();
2160 }
2161
2162protected:
2163 sp<FakeApplicationHandle> application1;
2164 sp<FakeWindowHandle> windowInPrimary;
2165 sp<FakeApplicationHandle> application2;
2166 sp<FakeWindowHandle> windowInSecondary;
2167};
2168
2169TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2170 // Test touch down on primary display.
2171 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2172 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08002173 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002174 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002175 windowInSecondary->assertNoEvents();
2176
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002177 // Test touch down on second display.
2178 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2179 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08002180 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2181 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002182 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002183}
2184
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002185TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002186 // Test inject a key down with display id specified.
2187 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2188 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002189 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002190 windowInSecondary->assertNoEvents();
2191
2192 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08002193 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2194 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2195 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002196 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002197
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002198 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002199 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002200
2201 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002202 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2203 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002204
2205 // Test inject a key down, should timeout because of no target window.
2206 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
2207 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
2208 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002209 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002210 windowInSecondary->assertNoEvents();
2211}
2212
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002213// Test per-display input monitors for motion event.
2214TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002215 FakeMonitorReceiver monitorInPrimary =
2216 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2217 FakeMonitorReceiver monitorInSecondary =
2218 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002219
2220 // Test touch down on primary display.
2221 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2222 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2223 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002224 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002225 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002226 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002227 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002228
2229 // Test touch down on second display.
2230 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2231 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2232 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2233 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002234 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002235 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002236 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002237
2238 // Test inject a non-pointer motion event.
2239 // If specific a display, it will dispatch to the focused window of particular display,
2240 // or it will dispatch to the focused window of focused display.
2241 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2242 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2243 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2244 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002245 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002246 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002247 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002248}
2249
2250// Test per-display input monitors for key event.
2251TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
2252 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002253 FakeMonitorReceiver monitorInPrimary =
2254 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2255 FakeMonitorReceiver monitorInSecondary =
2256 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002257
2258 // Test inject a key down.
2259 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2260 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2261 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002262 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002263 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002264 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002265}
2266
Jackal Guof9696682018-10-05 12:23:23 +08002267class InputFilterTest : public InputDispatcherTest {
2268protected:
2269 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2270
2271 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2272 NotifyMotionArgs motionArgs;
2273
2274 motionArgs = generateMotionArgs(
2275 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2276 mDispatcher->notifyMotion(&motionArgs);
2277 motionArgs = generateMotionArgs(
2278 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2279 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002280 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002281 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002282 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002283 } else {
2284 mFakePolicy->assertFilterInputEventWasNotCalled();
2285 }
2286 }
2287
2288 void testNotifyKey(bool expectToBeFiltered) {
2289 NotifyKeyArgs keyArgs;
2290
2291 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2292 mDispatcher->notifyKey(&keyArgs);
2293 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2294 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002295 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002296
2297 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002298 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002299 } else {
2300 mFakePolicy->assertFilterInputEventWasNotCalled();
2301 }
2302 }
2303};
2304
2305// Test InputFilter for MotionEvent
2306TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2307 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2308 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2309 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2310
2311 // Enable InputFilter
2312 mDispatcher->setInputFilterEnabled(true);
2313 // Test touch on both primary and second display, and check if both events are filtered.
2314 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2315 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2316
2317 // Disable InputFilter
2318 mDispatcher->setInputFilterEnabled(false);
2319 // Test touch on both primary and second display, and check if both events aren't filtered.
2320 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2321 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2322}
2323
2324// Test InputFilter for KeyEvent
2325TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2326 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2327 testNotifyKey(/*expectToBeFiltered*/ false);
2328
2329 // Enable InputFilter
2330 mDispatcher->setInputFilterEnabled(true);
2331 // Send a key event, and check if it is filtered.
2332 testNotifyKey(/*expectToBeFiltered*/ true);
2333
2334 // Disable InputFilter
2335 mDispatcher->setInputFilterEnabled(false);
2336 // Send a key event, and check if it isn't filtered.
2337 testNotifyKey(/*expectToBeFiltered*/ false);
2338}
2339
chaviwfd6d3512019-03-25 13:23:49 -07002340class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002341 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002342 InputDispatcherTest::SetUp();
2343
2344 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2345 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2346 ADISPLAY_ID_DEFAULT);
2347 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2348 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2349 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002350 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002351
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002352 mFocusedWindow =
2353 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2354 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002355 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002356
2357 // Set focused application.
2358 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002359 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07002360
2361 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002362 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002363 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002364 }
2365
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002366 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002367 InputDispatcherTest::TearDown();
2368
2369 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002370 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002371 }
2372
2373protected:
2374 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002375 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002376 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002377};
2378
2379// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2380// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2381// the onPointerDownOutsideFocus callback.
2382TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002383 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2384 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2385 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002386 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002387 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002388
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002389 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002390 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2391}
2392
2393// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2394// DOWN on the window that doesn't have focus. Ensure no window received the
2395// onPointerDownOutsideFocus callback.
2396TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002397 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2398 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002399 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002400 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002401
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002402 ASSERT_TRUE(mDispatcher->waitForIdle());
2403 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002404}
2405
2406// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2407// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2408TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2409 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2410 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002411 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002412
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002413 ASSERT_TRUE(mDispatcher->waitForIdle());
2414 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002415}
2416
2417// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2418// DOWN on the window that already has focus. Ensure no window received the
2419// onPointerDownOutsideFocus callback.
2420TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2421 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002422 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2423 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002424 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002425 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002426 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002427
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002428 ASSERT_TRUE(mDispatcher->waitForIdle());
2429 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002430}
2431
chaviwaf87b3e2019-10-01 16:59:28 -07002432// These tests ensures we can send touch events to a single client when there are multiple input
2433// windows that point to the same client token.
2434class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2435 virtual void SetUp() override {
2436 InputDispatcherTest::SetUp();
2437
2438 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2439 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2440 ADISPLAY_ID_DEFAULT);
2441 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2442 // 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 +01002443 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2444 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002445 mWindow1->setFrame(Rect(0, 0, 100, 100));
2446
2447 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2448 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002449 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2450 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002451 mWindow2->setFrame(Rect(100, 100, 200, 200));
2452
Arthur Hung72d8dc32020-03-28 00:48:39 +00002453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002454 }
2455
2456protected:
2457 sp<FakeWindowHandle> mWindow1;
2458 sp<FakeWindowHandle> mWindow2;
2459
2460 // Helper function to convert the point from screen coordinates into the window's space
2461 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
2462 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
2463 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
2464 return {x, y};
2465 }
2466
2467 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2468 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002469 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002470 InputEvent* event = window->consume();
2471
2472 ASSERT_NE(nullptr, event) << name.c_str()
2473 << ": consumer should have returned non-NULL event.";
2474
2475 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2476 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2477 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2478
2479 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2480 EXPECT_EQ(expectedAction, motionEvent.getAction());
2481
2482 for (size_t i = 0; i < points.size(); i++) {
2483 float expectedX = points[i].x;
2484 float expectedY = points[i].y;
2485
2486 EXPECT_EQ(expectedX, motionEvent.getX(i))
2487 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2488 << ", got " << motionEvent.getX(i);
2489 EXPECT_EQ(expectedY, motionEvent.getY(i))
2490 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2491 << ", got " << motionEvent.getY(i);
2492 }
2493 }
2494};
2495
2496TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2497 // Touch Window 1
2498 PointF touchedPoint = {10, 10};
2499 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2500
2501 NotifyMotionArgs motionArgs =
2502 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2503 ADISPLAY_ID_DEFAULT, {touchedPoint});
2504 mDispatcher->notifyMotion(&motionArgs);
2505 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2506
2507 // Release touch on Window 1
2508 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2509 ADISPLAY_ID_DEFAULT, {touchedPoint});
2510 mDispatcher->notifyMotion(&motionArgs);
2511 // consume the UP event
2512 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2513
2514 // Touch Window 2
2515 touchedPoint = {150, 150};
2516 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2517
2518 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2519 ADISPLAY_ID_DEFAULT, {touchedPoint});
2520 mDispatcher->notifyMotion(&motionArgs);
2521
2522 // Consuming from window1 since it's the window that has the InputReceiver
2523 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2524}
2525
2526TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2527 mWindow2->setWindowScale(0.5f, 0.5f);
2528
2529 // Touch Window 1
2530 PointF touchedPoint = {10, 10};
2531 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2532
2533 NotifyMotionArgs motionArgs =
2534 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2535 ADISPLAY_ID_DEFAULT, {touchedPoint});
2536 mDispatcher->notifyMotion(&motionArgs);
2537 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2538
2539 // Release touch on Window 1
2540 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2541 ADISPLAY_ID_DEFAULT, {touchedPoint});
2542 mDispatcher->notifyMotion(&motionArgs);
2543 // consume the UP event
2544 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2545
2546 // Touch Window 2
2547 touchedPoint = {150, 150};
2548 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2549
2550 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2551 ADISPLAY_ID_DEFAULT, {touchedPoint});
2552 mDispatcher->notifyMotion(&motionArgs);
2553
2554 // Consuming from window1 since it's the window that has the InputReceiver
2555 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2556}
2557
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002558TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2559 mWindow2->setWindowScale(0.5f, 0.5f);
2560
2561 // Touch Window 1
2562 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2563 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2564
2565 NotifyMotionArgs motionArgs =
2566 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2567 ADISPLAY_ID_DEFAULT, touchedPoints);
2568 mDispatcher->notifyMotion(&motionArgs);
2569 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2570
2571 // Touch Window 2
2572 int32_t actionPointerDown =
2573 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2574 touchedPoints.emplace_back(PointF{150, 150});
2575 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2576
2577 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2578 ADISPLAY_ID_DEFAULT, touchedPoints);
2579 mDispatcher->notifyMotion(&motionArgs);
2580
2581 // Consuming from window1 since it's the window that has the InputReceiver
2582 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2583}
2584
2585TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2586 mWindow2->setWindowScale(0.5f, 0.5f);
2587
2588 // Touch Window 1
2589 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2590 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2591
2592 NotifyMotionArgs motionArgs =
2593 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2594 ADISPLAY_ID_DEFAULT, touchedPoints);
2595 mDispatcher->notifyMotion(&motionArgs);
2596 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2597
2598 // Touch Window 2
2599 int32_t actionPointerDown =
2600 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2601 touchedPoints.emplace_back(PointF{150, 150});
2602 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2603
2604 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2605 ADISPLAY_ID_DEFAULT, touchedPoints);
2606 mDispatcher->notifyMotion(&motionArgs);
2607
2608 // Consuming from window1 since it's the window that has the InputReceiver
2609 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2610
2611 // Move both windows
2612 touchedPoints = {{20, 20}, {175, 175}};
2613 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2614 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2615
2616 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2617 ADISPLAY_ID_DEFAULT, touchedPoints);
2618 mDispatcher->notifyMotion(&motionArgs);
2619
2620 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2621}
2622
2623TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2624 mWindow1->setWindowScale(0.5f, 0.5f);
2625
2626 // Touch Window 1
2627 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2628 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2629
2630 NotifyMotionArgs motionArgs =
2631 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2632 ADISPLAY_ID_DEFAULT, touchedPoints);
2633 mDispatcher->notifyMotion(&motionArgs);
2634 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2635
2636 // Touch Window 2
2637 int32_t actionPointerDown =
2638 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2639 touchedPoints.emplace_back(PointF{150, 150});
2640 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2641
2642 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2643 ADISPLAY_ID_DEFAULT, touchedPoints);
2644 mDispatcher->notifyMotion(&motionArgs);
2645
2646 // Consuming from window1 since it's the window that has the InputReceiver
2647 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2648
2649 // Move both windows
2650 touchedPoints = {{20, 20}, {175, 175}};
2651 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2652 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2653
2654 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2655 ADISPLAY_ID_DEFAULT, touchedPoints);
2656 mDispatcher->notifyMotion(&motionArgs);
2657
2658 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2659}
2660
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002661class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2662 virtual void SetUp() override {
2663 InputDispatcherTest::SetUp();
2664
2665 mApplication = new FakeApplicationHandle();
2666 mApplication->setDispatchingTimeout(20ms);
2667 mWindow =
2668 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2669 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002670 mWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002671 mWindow->setFocus(true);
2672 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2673 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002674 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002675
2676 // Set focused application.
2677 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2678
2679 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2680 mWindow->consumeFocusEvent(true);
2681 }
2682
2683 virtual void TearDown() override {
2684 InputDispatcherTest::TearDown();
2685 mWindow.clear();
2686 }
2687
2688protected:
2689 sp<FakeApplicationHandle> mApplication;
2690 sp<FakeWindowHandle> mWindow;
2691 static constexpr PointF WINDOW_LOCATION = {20, 20};
2692
2693 void tapOnWindow() {
2694 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2695 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2696 WINDOW_LOCATION));
2697 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2698 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2699 WINDOW_LOCATION));
2700 }
2701};
2702
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002703// Send a tap and respond, which should not cause an ANR.
2704TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2705 tapOnWindow();
2706 mWindow->consumeMotionDown();
2707 mWindow->consumeMotionUp();
2708 ASSERT_TRUE(mDispatcher->waitForIdle());
2709 mFakePolicy->assertNotifyAnrWasNotCalled();
2710}
2711
2712// Send a regular key and respond, which should not cause an ANR.
2713TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
2714 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2715 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2716 ASSERT_TRUE(mDispatcher->waitForIdle());
2717 mFakePolicy->assertNotifyAnrWasNotCalled();
2718}
2719
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002720// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002721// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2722// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002723TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2724 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2725 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2726 WINDOW_LOCATION));
2727
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002728 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2729 ASSERT_TRUE(sequenceNum);
2730 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2731 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002732
2733 // The remaining lines are not really needed for the test, but kept as a sanity check
2734 mWindow->finishEvent(*sequenceNum);
2735 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2736 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002737 ASSERT_TRUE(mDispatcher->waitForIdle());
2738}
2739
2740// Send a key to the app and have the app not respond right away.
2741TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2742 // Inject a key, and don't respond - expect that ANR is called.
2743 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2744 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2745 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002746 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002747 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002748 ASSERT_TRUE(mDispatcher->waitForIdle());
2749}
2750
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002751// We have a focused application, but no focused window
2752TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
2753 mWindow->setFocus(false);
2754 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2755 mWindow->consumeFocusEvent(false);
2756
2757 // taps on the window work as normal
2758 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2759 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2760 WINDOW_LOCATION));
2761 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2762 mDispatcher->waitForIdle();
2763 mFakePolicy->assertNotifyAnrWasNotCalled();
2764
2765 // Once a focused event arrives, we get an ANR for this application
2766 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2767 // injection times out (instead of failing).
2768 const int32_t result =
2769 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2770 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2771 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2772 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2773 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2774 ASSERT_TRUE(mDispatcher->waitForIdle());
2775}
2776
2777// We have a focused application, but no focused window
2778// If the policy wants to keep waiting on the focused window to be added, make sure
2779// that this timeout extension is honored and ANR is raised again.
2780TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
2781 mWindow->setFocus(false);
2782 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2783 mWindow->consumeFocusEvent(false);
2784 const std::chrono::duration timeout = 5ms;
2785 mFakePolicy->setAnrTimeout(timeout);
2786
2787 // Once a focused event arrives, we get an ANR for this application
2788 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2789 // injection times out (instead of failing).
2790 const int32_t result =
2791 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2792 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2793 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2794 const std::chrono::duration appTimeout =
2795 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2796 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2797
2798 // After the extended time has passed, ANR should be raised again
2799 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2800
2801 // If we stop extending the timeout, dispatcher should go to idle.
2802 // Another ANR may be raised during this time
2803 mFakePolicy->setAnrTimeout(0ms);
2804 ASSERT_TRUE(mDispatcher->waitForIdle());
2805}
2806
2807// We have a focused application, but no focused window
2808TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
2809 mWindow->setFocus(false);
2810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2811 mWindow->consumeFocusEvent(false);
2812
2813 // Once a focused event arrives, we get an ANR for this application
2814 const int32_t result =
2815 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2816 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2817 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2818
2819 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2820 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2821
2822 // Future focused events get dropped right away
2823 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, injectKeyDown(mDispatcher));
2824 ASSERT_TRUE(mDispatcher->waitForIdle());
2825 mWindow->assertNoEvents();
2826}
2827
2828/**
2829 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2830 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2831 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2832 * the ANR mechanism should still work.
2833 *
2834 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2835 * DOWN event, while not responding on the second one.
2836 */
2837TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2838 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2839 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2840 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2841 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2842 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2843 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2844
2845 // Now send ACTION_UP, with identical timestamp
2846 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2847 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2848 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2849 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2850 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2851
2852 // We have now sent down and up. Let's consume first event and then ANR on the second.
2853 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2854 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2855 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2856}
2857
2858// If an app is not responding to a key event, gesture monitors should continue to receive
2859// new motion events
2860TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
2861 FakeMonitorReceiver monitor =
2862 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2863 true /*isGestureMonitor*/);
2864
2865 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
2866 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2867 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
2868
2869 // Stuck on the ACTION_UP
2870 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2871 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2872
2873 // New tap will go to the gesture monitor, but not to the window
2874 tapOnWindow();
2875 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2876 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2877
2878 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2879 mDispatcher->waitForIdle();
2880 mWindow->assertNoEvents();
2881 monitor.assertNoEvents();
2882}
2883
2884// If an app is not responding to a motion event, gesture monitors should continue to receive
2885// new motion events
2886TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
2887 FakeMonitorReceiver monitor =
2888 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2889 true /*isGestureMonitor*/);
2890
2891 tapOnWindow();
2892 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2893 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2894
2895 mWindow->consumeMotionDown();
2896 // Stuck on the ACTION_UP
2897 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2898 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2899
2900 // New tap will go to the gesture monitor, but not to the window
2901 tapOnWindow();
2902 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2903 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2904
2905 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2906 mDispatcher->waitForIdle();
2907 mWindow->assertNoEvents();
2908 monitor.assertNoEvents();
2909}
2910
2911// If a window is unresponsive, then you get anr. if the window later catches up and starts to
2912// process events, you don't get an anr. When the window later becomes unresponsive again, you
2913// get an ANR again.
2914// 1. tap -> block on ACTION_UP -> receive ANR
2915// 2. consume all pending events (= queue becomes healthy again)
2916// 3. tap again -> block on ACTION_UP again -> receive ANR second time
2917TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
2918 tapOnWindow();
2919
2920 mWindow->consumeMotionDown();
2921 // Block on ACTION_UP
2922 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2923 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2924 mWindow->consumeMotionUp(); // Now the connection should be healthy again
2925 mDispatcher->waitForIdle();
2926 mWindow->assertNoEvents();
2927
2928 tapOnWindow();
2929 mWindow->consumeMotionDown();
2930 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2931 mWindow->consumeMotionUp();
2932
2933 mDispatcher->waitForIdle();
2934 mWindow->assertNoEvents();
2935}
2936
2937// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
2938// is honored
2939TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
2940 const std::chrono::duration timeout = 5ms;
2941 mFakePolicy->setAnrTimeout(timeout);
2942
2943 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2944 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2945 WINDOW_LOCATION));
2946
2947 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2948 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
2949 mWindow->getToken());
2950
2951 // Since the policy wanted to extend ANR, make sure it is called again after the extension
2952 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2953 mFakePolicy->setAnrTimeout(0ms);
2954 std::this_thread::sleep_for(windowTimeout);
2955 // We are not checking if ANR has been called, because it may have been called again by the
2956 // time we set the timeout to 0
2957
2958 // When the policy finally says stop, we should get ACTION_CANCEL
2959 mWindow->consumeMotionDown();
2960 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2961 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2962 mWindow->assertNoEvents();
2963}
2964
2965/**
2966 * If a window is processing a motion event, and then a key event comes in, the key event should
2967 * not to to the focused window until the motion is processed.
2968 *
2969 * Warning!!!
2970 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2971 * and the injection timeout that we specify when injecting the key.
2972 * We must have the injection timeout (10ms) be smaller than
2973 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2974 *
2975 * If that value changes, this test should also change.
2976 */
2977TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
2978 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2979 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2980
2981 tapOnWindow();
2982 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2983 ASSERT_TRUE(downSequenceNum);
2984 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2985 ASSERT_TRUE(upSequenceNum);
2986 // Don't finish the events yet, and send a key
2987 // Injection will "succeed" because we will eventually give up and send the key to the focused
2988 // window even if motions are still being processed. But because the injection timeout is short,
2989 // we will receive INJECTION_TIMED_OUT as the result.
2990
2991 int32_t result =
2992 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2993 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2994 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2995 // Key will not be sent to the window, yet, because the window is still processing events
2996 // and the key remains pending, waiting for the touch events to be processed
2997 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2998 ASSERT_FALSE(keySequenceNum);
2999
3000 std::this_thread::sleep_for(500ms);
3001 // if we wait long enough though, dispatcher will give up, and still send the key
3002 // to the focused window, even though we have not yet finished the motion event
3003 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3004 mWindow->finishEvent(*downSequenceNum);
3005 mWindow->finishEvent(*upSequenceNum);
3006}
3007
3008/**
3009 * If a window is processing a motion event, and then a key event comes in, the key event should
3010 * not go to the focused window until the motion is processed.
3011 * If then a new motion comes in, then the pending key event should be going to the currently
3012 * focused window right away.
3013 */
3014TEST_F(InputDispatcherSingleWindowAnr,
3015 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3016 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3018
3019 tapOnWindow();
3020 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3021 ASSERT_TRUE(downSequenceNum);
3022 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3023 ASSERT_TRUE(upSequenceNum);
3024 // Don't finish the events yet, and send a key
3025 // Injection is async, so it will succeed
3026 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3027 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
3028 ADISPLAY_ID_DEFAULT, INPUT_EVENT_INJECTION_SYNC_NONE));
3029 // At this point, key is still pending, and should not be sent to the application yet.
3030 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3031 ASSERT_FALSE(keySequenceNum);
3032
3033 // Now tap down again. It should cause the pending key to go to the focused window right away.
3034 tapOnWindow();
3035 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3036 // the other events yet. We can finish events in any order.
3037 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3038 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3039 mWindow->consumeMotionDown();
3040 mWindow->consumeMotionUp();
3041 mWindow->assertNoEvents();
3042}
3043
3044class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3045 virtual void SetUp() override {
3046 InputDispatcherTest::SetUp();
3047
3048 mApplication = new FakeApplicationHandle();
3049 mApplication->setDispatchingTimeout(10ms);
3050 mUnfocusedWindow =
3051 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3052 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3053 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3054 // window.
3055 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003056 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3057 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3058 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003059
3060 mFocusedWindow =
3061 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003062 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003063 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003064 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3065 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003066
3067 // Set focused application.
3068 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3069 mFocusedWindow->setFocus(true);
3070
3071 // Expect one focus window exist in display.
3072 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3073 mFocusedWindow->consumeFocusEvent(true);
3074 }
3075
3076 virtual void TearDown() override {
3077 InputDispatcherTest::TearDown();
3078
3079 mUnfocusedWindow.clear();
3080 mFocusedWindow.clear();
3081 }
3082
3083protected:
3084 sp<FakeApplicationHandle> mApplication;
3085 sp<FakeWindowHandle> mUnfocusedWindow;
3086 sp<FakeWindowHandle> mFocusedWindow;
3087 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3088 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3089 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3090
3091 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3092
3093 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3094
3095private:
3096 void tap(const PointF& location) {
3097 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3098 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3099 location));
3100 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3101 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3102 location));
3103 }
3104};
3105
3106// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3107// should be ANR'd first.
3108TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
3109 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3111 FOCUSED_WINDOW_LOCATION))
3112 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
3113 mFocusedWindow->consumeMotionDown();
3114 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3115 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3116 // We consumed all events, so no ANR
3117 ASSERT_TRUE(mDispatcher->waitForIdle());
3118 mFakePolicy->assertNotifyAnrWasNotCalled();
3119
3120 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3121 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3122 FOCUSED_WINDOW_LOCATION));
3123 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3124 ASSERT_TRUE(unfocusedSequenceNum);
3125 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
3126 ASSERT_TRUE(focusedSequenceNum);
3127
3128 const std::chrono::duration timeout =
3129 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3130 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3131 mFocusedWindow->getToken());
3132
3133 mFocusedWindow->finishEvent(*focusedSequenceNum);
3134 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
3135 ASSERT_TRUE(mDispatcher->waitForIdle());
3136}
3137
3138// If we have 2 windows with identical timeouts that are both unresponsive,
3139// it doesn't matter which order they should have ANR.
3140// But we should receive ANR for both.
3141TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3142 // Set the timeout for unfocused window to match the focused window
3143 mUnfocusedWindow->setDispatchingTimeout(10ms);
3144 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3145
3146 tapOnFocusedWindow();
3147 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
3148 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData1 =
3149 mFakePolicy->getNotifyAnrData(10ms);
3150 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData2 =
3151 mFakePolicy->getNotifyAnrData(0ms);
3152
3153 // We don't know which window will ANR first. But both of them should happen eventually.
3154 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
3155 mFocusedWindow->getToken() == anrData2.second);
3156 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
3157 mUnfocusedWindow->getToken() == anrData2.second);
3158
3159 ASSERT_TRUE(mDispatcher->waitForIdle());
3160 mFakePolicy->assertNotifyAnrWasNotCalled();
3161}
3162
3163// If a window is already not responding, the second tap on the same window should be ignored.
3164// We should also log an error to account for the dropped event (not tested here).
3165// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3166TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3167 tapOnFocusedWindow();
3168 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3169 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3170 // Receive the events, but don't respond
3171 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3172 ASSERT_TRUE(downEventSequenceNum);
3173 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3174 ASSERT_TRUE(upEventSequenceNum);
3175 const std::chrono::duration timeout =
3176 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3177 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3178 mFocusedWindow->getToken());
3179
3180 // Tap once again
3181 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
3182 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3183 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3184 FOCUSED_WINDOW_LOCATION));
3185 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3186 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3187 FOCUSED_WINDOW_LOCATION));
3188 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3189 // valid touch target
3190 mUnfocusedWindow->assertNoEvents();
3191
3192 // Consume the first tap
3193 mFocusedWindow->finishEvent(*downEventSequenceNum);
3194 mFocusedWindow->finishEvent(*upEventSequenceNum);
3195 ASSERT_TRUE(mDispatcher->waitForIdle());
3196 // The second tap did not go to the focused window
3197 mFocusedWindow->assertNoEvents();
3198 // should not have another ANR after the window just became healthy again
3199 mFakePolicy->assertNotifyAnrWasNotCalled();
3200}
3201
3202// If you tap outside of all windows, there will not be ANR
3203TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
3204 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3205 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3206 LOCATION_OUTSIDE_ALL_WINDOWS));
3207 ASSERT_TRUE(mDispatcher->waitForIdle());
3208 mFakePolicy->assertNotifyAnrWasNotCalled();
3209}
3210
3211// Since the focused window is paused, tapping on it should not produce any events
3212TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3213 mFocusedWindow->setPaused(true);
3214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3215
3216 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3217 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3218 FOCUSED_WINDOW_LOCATION));
3219
3220 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3221 ASSERT_TRUE(mDispatcher->waitForIdle());
3222 // Should not ANR because the window is paused, and touches shouldn't go to it
3223 mFakePolicy->assertNotifyAnrWasNotCalled();
3224
3225 mFocusedWindow->assertNoEvents();
3226 mUnfocusedWindow->assertNoEvents();
3227}
3228
3229/**
3230 * If a window is processing a motion event, and then a key event comes in, the key event should
3231 * not to to the focused window until the motion is processed.
3232 * If a different window becomes focused at this time, the key should go to that window instead.
3233 *
3234 * Warning!!!
3235 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3236 * and the injection timeout that we specify when injecting the key.
3237 * We must have the injection timeout (10ms) be smaller than
3238 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3239 *
3240 * If that value changes, this test should also change.
3241 */
3242TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3243 // Set a long ANR timeout to prevent it from triggering
3244 mFocusedWindow->setDispatchingTimeout(2s);
3245 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3246
3247 tapOnUnfocusedWindow();
3248 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3249 ASSERT_TRUE(downSequenceNum);
3250 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3251 ASSERT_TRUE(upSequenceNum);
3252 // Don't finish the events yet, and send a key
3253 // Injection will succeed because we will eventually give up and send the key to the focused
3254 // window even if motions are still being processed.
3255
3256 int32_t result =
3257 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
3258 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
3259 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
3260 // Key will not be sent to the window, yet, because the window is still processing events
3261 // and the key remains pending, waiting for the touch events to be processed
3262 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3263 ASSERT_FALSE(keySequenceNum);
3264
3265 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
3266 mFocusedWindow->setFocus(false);
3267 mUnfocusedWindow->setFocus(true);
3268 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3269
3270 // Focus events should precede the key events
3271 mUnfocusedWindow->consumeFocusEvent(true);
3272 mFocusedWindow->consumeFocusEvent(false);
3273
3274 // Finish the tap events, which should unblock dispatcher
3275 mUnfocusedWindow->finishEvent(*downSequenceNum);
3276 mUnfocusedWindow->finishEvent(*upSequenceNum);
3277
3278 // Now that all queues are cleared and no backlog in the connections, the key event
3279 // can finally go to the newly focused "mUnfocusedWindow".
3280 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3281 mFocusedWindow->assertNoEvents();
3282 mUnfocusedWindow->assertNoEvents();
3283}
3284
3285// When the touch stream is split across 2 windows, and one of them does not respond,
3286// then ANR should be raised and the touch should be canceled for the unresponsive window.
3287// The other window should not be affected by that.
3288TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3289 // Touch Window 1
3290 NotifyMotionArgs motionArgs =
3291 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3292 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3293 mDispatcher->notifyMotion(&motionArgs);
3294 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3295 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3296
3297 // Touch Window 2
3298 int32_t actionPointerDown =
3299 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3300
3301 motionArgs =
3302 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3303 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3304 mDispatcher->notifyMotion(&motionArgs);
3305
3306 const std::chrono::duration timeout =
3307 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3308 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3309 mFocusedWindow->getToken());
3310
3311 mUnfocusedWindow->consumeMotionDown();
3312 mFocusedWindow->consumeMotionDown();
3313 // Focused window may or may not receive ACTION_MOVE
3314 // But it should definitely receive ACTION_CANCEL due to the ANR
3315 InputEvent* event;
3316 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3317 ASSERT_TRUE(moveOrCancelSequenceNum);
3318 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3319 ASSERT_NE(nullptr, event);
3320 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3321 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3322 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3323 mFocusedWindow->consumeMotionCancel();
3324 } else {
3325 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3326 }
3327
3328 ASSERT_TRUE(mDispatcher->waitForIdle());
3329 mUnfocusedWindow->assertNoEvents();
3330 mFocusedWindow->assertNoEvents();
3331}
3332
Garfield Tane84e6f92019-08-29 17:28:41 -07003333} // namespace android::inputdispatcher