blob: 86d62d74cacf0c27483da91705080f4477ea714f [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
chaviw9eaa22c2020-07-01 16:21:27 -0700436 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800437 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800438 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700439 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
440 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600441 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700442 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700443 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
444 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
445 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800446 << "Should reject motion events with undefined action.";
447
448 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800449 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700450 AMOTION_EVENT_ACTION_POINTER_DOWN |
451 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700452 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
453 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
454 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
455 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700456 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
457 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
458 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800459 << "Should reject motion events with pointer down index too large.";
460
Garfield Tanfbe732e2020-01-24 11:26:14 -0800461 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700462 AMOTION_EVENT_ACTION_POINTER_DOWN |
463 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700464 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
465 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
466 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
467 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700468 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
469 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
470 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800471 << "Should reject motion events with pointer down index too small.";
472
473 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800474 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700475 AMOTION_EVENT_ACTION_POINTER_UP |
476 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700477 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
478 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
479 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
480 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700481 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
482 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
483 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800484 << "Should reject motion events with pointer up index too large.";
485
Garfield Tanfbe732e2020-01-24 11:26:14 -0800486 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700487 AMOTION_EVENT_ACTION_POINTER_UP |
488 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700489 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
490 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
491 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
492 pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700493 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
494 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
495 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800496 << "Should reject motion events with pointer up index too small.";
497
498 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800499 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
500 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700501 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
502 AMOTION_EVENT_INVALID_CURSOR_POSITION, 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,
chaviw9eaa22c2020-07-01 16:21:27 -0700511 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
512 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700513 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700514 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
515 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
516 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800517 << "Should reject motion events with more than MAX_POINTERS pointers.";
518
519 // Rejects motion events with invalid pointer ids.
520 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800521 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
522 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700523 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
524 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700525 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700526 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
527 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
528 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529 << "Should reject motion events with pointer ids less than 0.";
530
531 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800532 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
533 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700534 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
535 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700536 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700537 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
538 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
539 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800540 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
541
542 // Rejects motion events with duplicate pointer ids.
543 pointerProperties[0].id = 1;
544 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800545 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
546 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700547 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
548 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700549 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700550 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
551 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
552 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553 << "Should reject motion events with duplicate pointer ids.";
554}
555
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800556/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
557
558TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
559 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800560 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800561 mDispatcher->notifyConfigurationChanged(&args);
562 ASSERT_TRUE(mDispatcher->waitForIdle());
563
564 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
565}
566
567TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800568 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
569 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800570 mDispatcher->notifySwitch(&args);
571
572 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
573 args.policyFlags |= POLICY_FLAG_TRUSTED;
574 mFakePolicy->assertNotifySwitchWasCalled(args);
575}
576
Arthur Hungb92218b2018-08-14 12:00:21 +0800577// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700578static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700579static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800580
581class FakeApplicationHandle : public InputApplicationHandle {
582public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700583 FakeApplicationHandle() {
584 mInfo.name = "Fake Application";
585 mInfo.token = new BBinder();
Chris Ye6c4243b2020-07-22 12:07:12 -0700586 mInfo.dispatchingTimeoutNanos = DISPATCHING_TIMEOUT.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700587 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800588 virtual ~FakeApplicationHandle() {}
589
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700590 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800591 return true;
592 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700593
594 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Chris Ye6c4243b2020-07-22 12:07:12 -0700595 mInfo.dispatchingTimeoutNanos = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700596 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800597};
598
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800599class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800600public:
Siarhei Vishniakouce5ab082020-07-09 17:03:21 -0500601 explicit FakeInputReceiver(const std::shared_ptr<InputChannel>& clientChannel,
602 const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800603 : mName(name) {
604 mConsumer = std::make_unique<InputConsumer>(clientChannel);
605 }
606
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800607 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700608 InputEvent* event;
609 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
610 if (!consumeSeq) {
611 return nullptr;
612 }
613 finishEvent(*consumeSeq);
614 return event;
615 }
616
617 /**
618 * Receive an event without acknowledging it.
619 * Return the sequence number that could later be used to send finished signal.
620 */
621 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800622 uint32_t consumeSeq;
623 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800624
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800625 std::chrono::time_point start = std::chrono::steady_clock::now();
626 status_t status = WOULD_BLOCK;
627 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800628 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800629 &event);
630 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
631 if (elapsed > 100ms) {
632 break;
633 }
634 }
635
636 if (status == WOULD_BLOCK) {
637 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700638 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800639 }
640
641 if (status != OK) {
642 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700643 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800644 }
645 if (event == nullptr) {
646 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700647 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800648 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700649 if (outEvent != nullptr) {
650 *outEvent = event;
651 }
652 return consumeSeq;
653 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800654
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700655 /**
656 * To be used together with "receiveEvent" to complete the consumption of an event.
657 */
658 void finishEvent(uint32_t consumeSeq) {
659 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
660 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800661 }
662
663 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
664 int32_t expectedFlags) {
665 InputEvent* event = consume();
666
667 ASSERT_NE(nullptr, event) << mName.c_str()
668 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800669 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700670 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800671 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800672
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800673 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800674
Tiger Huang8664f8c2018-10-11 19:14:35 +0800675 switch (expectedEventType) {
676 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800677 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
678 EXPECT_EQ(expectedAction, keyEvent.getAction());
679 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800680 break;
681 }
682 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800683 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
684 EXPECT_EQ(expectedAction, motionEvent.getAction());
685 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800686 break;
687 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100688 case AINPUT_EVENT_TYPE_FOCUS: {
689 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
690 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800691 default: {
692 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
693 }
694 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800695 }
696
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100697 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
698 InputEvent* event = consume();
699 ASSERT_NE(nullptr, event) << mName.c_str()
700 << ": consumer should have returned non-NULL event.";
701 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
702 << "Got " << inputEventTypeToString(event->getType())
703 << " event instead of FOCUS event";
704
705 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
706 << mName.c_str() << ": event displayId should always be NONE.";
707
708 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
709 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
710 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
711 }
712
chaviwd1c23182019-12-20 18:44:56 -0800713 void assertNoEvents() {
714 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700715 if (event == nullptr) {
716 return;
717 }
718 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
719 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
720 ADD_FAILURE() << "Received key event "
721 << KeyEvent::actionToString(keyEvent.getAction());
722 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
723 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
724 ADD_FAILURE() << "Received motion event "
725 << MotionEvent::actionToString(motionEvent.getAction());
726 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
727 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
728 ADD_FAILURE() << "Received focus event, hasFocus = "
729 << (focusEvent.getHasFocus() ? "true" : "false");
730 }
731 FAIL() << mName.c_str()
732 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800733 }
734
735 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
736
737protected:
738 std::unique_ptr<InputConsumer> mConsumer;
739 PreallocatedInputEventFactory mEventFactory;
740
741 std::string mName;
742};
743
744class FakeWindowHandle : public InputWindowHandle {
745public:
746 static const int32_t WIDTH = 600;
747 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800748
749 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
750 const sp<InputDispatcher>& dispatcher, const std::string name,
751 int32_t displayId, sp<IBinder> token = nullptr)
752 : mName(name) {
753 if (token == nullptr) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500754 std::unique_ptr<InputChannel> serverChannel, clientChannel;
chaviwd1c23182019-12-20 18:44:56 -0800755 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500756 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
chaviwd1c23182019-12-20 18:44:56 -0800757 token = serverChannel->getConnectionToken();
Siarhei Vishniakoud2588272020-07-10 11:15:40 -0500758 dispatcher->registerInputChannel(std::move(serverChannel));
chaviwd1c23182019-12-20 18:44:56 -0800759 }
760
761 inputApplicationHandle->updateInfo();
762 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
763
764 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700765 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800766 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100767 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500768 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800769 mInfo.frameLeft = 0;
770 mInfo.frameTop = 0;
771 mInfo.frameRight = WIDTH;
772 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700773 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800774 mInfo.globalScaleFactor = 1.0;
775 mInfo.touchableRegion.clear();
776 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
777 mInfo.visible = true;
778 mInfo.canReceiveKeys = true;
779 mInfo.hasFocus = false;
780 mInfo.hasWallpaper = false;
781 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800782 mInfo.ownerPid = INJECTOR_PID;
783 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800784 mInfo.displayId = displayId;
785 }
786
787 virtual bool updateInfo() { return true; }
788
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100789 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800790
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700791 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500792 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700793 }
794
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700795 void setPaused(bool paused) { mInfo.paused = paused; }
796
chaviwd1c23182019-12-20 18:44:56 -0800797 void setFrame(const Rect& frame) {
798 mInfo.frameLeft = frame.left;
799 mInfo.frameTop = frame.top;
800 mInfo.frameRight = frame.right;
801 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700802 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800803 mInfo.touchableRegion.clear();
804 mInfo.addTouchableRegion(frame);
805 }
806
Michael Wright44753b12020-07-08 13:48:11 +0100807 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800808
chaviw9eaa22c2020-07-01 16:21:27 -0700809 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
810 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
811 }
812
813 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700814
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800815 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
816 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
817 expectedFlags);
818 }
819
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700820 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
821 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
822 }
823
Svet Ganov5d3bc372020-01-26 23:11:07 -0800824 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
825 int32_t expectedFlags = 0) {
826 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
827 expectedFlags);
828 }
829
830 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
831 int32_t expectedFlags = 0) {
832 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
833 expectedFlags);
834 }
835
836 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
837 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800838 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
839 expectedFlags);
840 }
841
Svet Ganov5d3bc372020-01-26 23:11:07 -0800842 void consumeMotionPointerDown(int32_t pointerIdx,
843 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
844 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
845 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
846 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
847 }
848
849 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
850 int32_t expectedFlags = 0) {
851 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
852 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
853 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
854 }
855
856 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
857 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000858 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
859 expectedFlags);
860 }
861
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100862 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
863 ASSERT_NE(mInputReceiver, nullptr)
864 << "Cannot consume events from a window with no receiver";
865 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
866 }
867
chaviwd1c23182019-12-20 18:44:56 -0800868 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
869 int32_t expectedFlags) {
870 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
871 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
872 expectedFlags);
873 }
874
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700875 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700876 if (mInputReceiver == nullptr) {
877 ADD_FAILURE() << "Invalid receive event on window with no receiver";
878 return std::nullopt;
879 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700880 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 }
882
883 void finishEvent(uint32_t sequenceNum) {
884 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
885 mInputReceiver->finishEvent(sequenceNum);
886 }
887
chaviwaf87b3e2019-10-01 16:59:28 -0700888 InputEvent* consume() {
889 if (mInputReceiver == nullptr) {
890 return nullptr;
891 }
892 return mInputReceiver->consume();
893 }
894
Arthur Hungb92218b2018-08-14 12:00:21 +0800895 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800896 ASSERT_NE(mInputReceiver, nullptr)
897 << "Call 'assertNoEvents' on a window with an InputReceiver";
898 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800899 }
900
chaviwaf87b3e2019-10-01 16:59:28 -0700901 sp<IBinder> getToken() { return mInfo.token; }
902
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100903 const std::string& getName() { return mName; }
904
chaviwd1c23182019-12-20 18:44:56 -0800905private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100906 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800907 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700908 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800909};
910
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700911std::atomic<int32_t> FakeWindowHandle::sId{1};
912
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700914 int32_t displayId = ADISPLAY_ID_NONE,
915 int32_t syncMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
916 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 KeyEvent event;
918 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
919
920 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800921 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700922 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
923 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800924
925 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700926 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
927 injectionTimeout,
928 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800929}
930
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
932 int32_t displayId = ADISPLAY_ID_NONE) {
933 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
934}
935
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700936static int32_t injectKeyUp(const sp<InputDispatcher>& dispatcher,
937 int32_t displayId = ADISPLAY_ID_NONE) {
938 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
939}
940
Garfield Tandf26e862020-07-01 20:18:19 -0700941class PointerBuilder {
942public:
943 PointerBuilder(int32_t id, int32_t toolType) {
944 mProperties.clear();
945 mProperties.id = id;
946 mProperties.toolType = toolType;
947 mCoords.clear();
948 }
949
950 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
951
952 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
953
954 PointerBuilder& axis(int32_t axis, float value) {
955 mCoords.setAxisValue(axis, value);
956 return *this;
957 }
958
959 PointerProperties buildProperties() const { return mProperties; }
960
961 PointerCoords buildCoords() const { return mCoords; }
962
963private:
964 PointerProperties mProperties;
965 PointerCoords mCoords;
966};
967
968class MotionEventBuilder {
969public:
970 MotionEventBuilder(int32_t action, int32_t source) {
971 mAction = action;
972 mSource = source;
973 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
974 }
975
976 MotionEventBuilder& eventTime(nsecs_t eventTime) {
977 mEventTime = eventTime;
978 return *this;
979 }
980
981 MotionEventBuilder& displayId(int32_t displayId) {
982 mDisplayId = displayId;
983 return *this;
984 }
985
986 MotionEventBuilder& actionButton(int32_t actionButton) {
987 mActionButton = actionButton;
988 return *this;
989 }
990
991 MotionEventBuilder& buttonState(int32_t actionButton) {
992 mActionButton = actionButton;
993 return *this;
994 }
995
996 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
997 mRawXCursorPosition = rawXCursorPosition;
998 return *this;
999 }
1000
1001 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1002 mRawYCursorPosition = rawYCursorPosition;
1003 return *this;
1004 }
1005
1006 MotionEventBuilder& pointer(PointerBuilder pointer) {
1007 mPointers.push_back(pointer);
1008 return *this;
1009 }
1010
1011 MotionEvent build() {
1012 std::vector<PointerProperties> pointerProperties;
1013 std::vector<PointerCoords> pointerCoords;
1014 for (const PointerBuilder& pointer : mPointers) {
1015 pointerProperties.push_back(pointer.buildProperties());
1016 pointerCoords.push_back(pointer.buildCoords());
1017 }
1018
1019 // Set mouse cursor position for the most common cases to avoid boilerplate.
1020 if (mSource == AINPUT_SOURCE_MOUSE &&
1021 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1022 mPointers.size() == 1) {
1023 mRawXCursorPosition = pointerCoords[0].getX();
1024 mRawYCursorPosition = pointerCoords[0].getY();
1025 }
1026
1027 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001028 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001029 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1030 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001031 mButtonState, MotionClassification::NONE, identityTransform,
1032 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1033 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1034 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001035
1036 return event;
1037 }
1038
1039private:
1040 int32_t mAction;
1041 int32_t mSource;
1042 nsecs_t mEventTime;
1043 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1044 int32_t mActionButton{0};
1045 int32_t mButtonState{0};
1046 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1047 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1048
1049 std::vector<PointerBuilder> mPointers;
1050};
1051
1052static int32_t injectMotionEvent(
1053 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1054 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1055 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT) {
1056 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1057 injectionTimeout,
1058 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1059}
1060
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001061static int32_t injectMotionEvent(
1062 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1063 const PointF& position,
1064 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001065 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1066 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1067 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
1068 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001069 MotionEvent event = MotionEventBuilder(action, source)
1070 .displayId(displayId)
1071 .eventTime(eventTime)
1072 .rawXCursorPosition(cursorPosition.x)
1073 .rawYCursorPosition(cursorPosition.y)
1074 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1075 .x(position.x)
1076 .y(position.y))
1077 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001078
1079 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001080 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001081}
1082
Garfield Tan00f511d2019-06-12 16:55:40 -07001083static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001084 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001085 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001086}
1087
Michael Wright3a240c42019-12-10 20:53:41 +00001088static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001089 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001090 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001091}
1092
Jackal Guof9696682018-10-05 12:23:23 +08001093static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1094 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1095 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001096 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1097 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1098 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001099
1100 return args;
1101}
1102
chaviwd1c23182019-12-20 18:44:56 -08001103static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1104 const std::vector<PointF>& points) {
1105 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001106 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1107 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1108 }
1109
chaviwd1c23182019-12-20 18:44:56 -08001110 PointerProperties pointerProperties[pointerCount];
1111 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001112
chaviwd1c23182019-12-20 18:44:56 -08001113 for (size_t i = 0; i < pointerCount; i++) {
1114 pointerProperties[i].clear();
1115 pointerProperties[i].id = i;
1116 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001117
chaviwd1c23182019-12-20 18:44:56 -08001118 pointerCoords[i].clear();
1119 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1120 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1121 }
Jackal Guof9696682018-10-05 12:23:23 +08001122
1123 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1124 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001125 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001126 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1127 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001128 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1129 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001130 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1131 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001132
1133 return args;
1134}
1135
chaviwd1c23182019-12-20 18:44:56 -08001136static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1137 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1138}
1139
Arthur Hungb92218b2018-08-14 12:00:21 +08001140TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
1141 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001142 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1143 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001144
Arthur Hung72d8dc32020-03-28 00:48:39 +00001145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001146 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1147 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001148 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1149
1150 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001151 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001152}
1153
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001154/**
1155 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1156 * To ensure that window receives only events that were directly inside of it, add
1157 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1158 * when finding touched windows.
1159 * This test serves as a sanity check for the next test, where setInputWindows is
1160 * called twice.
1161 */
1162TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
1163 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1164 sp<FakeWindowHandle> window =
1165 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1166 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001167 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001168
1169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1170 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1171 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1172 {50, 50}))
1173 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1174
1175 // Window should receive motion event.
1176 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1177}
1178
1179/**
1180 * Calling setInputWindows twice, with the same info, should not cause any issues.
1181 * To ensure that window receives only events that were directly inside of it, add
1182 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1183 * when finding touched windows.
1184 */
1185TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
1186 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1187 sp<FakeWindowHandle> window =
1188 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1189 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001190 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001191
1192 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1194 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1195 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1196 {50, 50}))
1197 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1198
1199 // Window should receive motion event.
1200 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1201}
1202
Arthur Hungb92218b2018-08-14 12:00:21 +08001203// The foreground window should receive the first touch down event.
1204TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
1205 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001206 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1207 ADISPLAY_ID_DEFAULT);
1208 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1209 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001210
Arthur Hung72d8dc32020-03-28 00:48:39 +00001211 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001212 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1213 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001214 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1215
1216 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001217 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001218 windowSecond->assertNoEvents();
1219}
1220
1221TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
1222 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001223 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1224 ADISPLAY_ID_DEFAULT);
1225 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1226 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001227
Arthur Hung7ab76b12019-01-09 19:17:20 +08001228 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001229 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001230
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001231 // Display should have only one focused window
1232 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001234
1235 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001236 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1237 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1238
1239 // Focused window should receive event.
1240 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001241 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001242}
1243
Arthur Hung7ab76b12019-01-09 19:17:20 +08001244TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
1245 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1246 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1247 ADISPLAY_ID_DEFAULT);
1248 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1249 ADISPLAY_ID_DEFAULT);
1250
1251 // Set focused application.
1252 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1253
1254 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001255 windowTop->setFocus(true);
1256 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001257
Arthur Hung72d8dc32020-03-28 00:48:39 +00001258 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001259 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001260 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1261 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1262
1263 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001264 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001265 windowSecond->assertNoEvents();
1266}
1267
Arthur Hung3b413f22018-10-26 18:05:34 +08001268TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1269 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1270
1271 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1272 ADISPLAY_ID_DEFAULT);
1273 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1274 ADISPLAY_ID_DEFAULT);
1275
Arthur Hung832bc4a2019-01-28 11:43:17 +08001276 // Set focused application.
1277 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001278
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001279 windowTop->setFocus(true);
1280 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001281 // Release channel for window is no longer valid.
1282 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001284 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001285
Arthur Hung832bc4a2019-01-28 11:43:17 +08001286 // Test inject a key down, should dispatch to a valid window.
1287 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1288 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001289
1290 // Top window is invalid, so it should not receive any input event.
1291 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001292 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001293}
1294
Garfield Tandf26e862020-07-01 20:18:19 -07001295TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
1296 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1297 sp<FakeWindowHandle> windowLeft =
1298 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1299 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001300 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001301 sp<FakeWindowHandle> windowRight =
1302 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1303 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001304 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001305
1306 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1307
1308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1309
1310 // Start cursor position in right window so that we can move the cursor to left window.
1311 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1312 injectMotionEvent(mDispatcher,
1313 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1314 AINPUT_SOURCE_MOUSE)
1315 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1316 .x(900)
1317 .y(400))
1318 .build()));
1319 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1320 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1321 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1322 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1323
1324 // Move cursor into left window
1325 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1326 injectMotionEvent(mDispatcher,
1327 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1328 AINPUT_SOURCE_MOUSE)
1329 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1330 .x(300)
1331 .y(400))
1332 .build()));
1333 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1334 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1335 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1336 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1337 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1338 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1339
1340 // Inject a series of mouse events for a mouse click
1341 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1342 injectMotionEvent(mDispatcher,
1343 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1344 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1345 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1346 .x(300)
1347 .y(400))
1348 .build()));
1349 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1350
1351 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1352 injectMotionEvent(mDispatcher,
1353 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1354 AINPUT_SOURCE_MOUSE)
1355 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1356 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1357 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1358 .x(300)
1359 .y(400))
1360 .build()));
1361 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1362 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1363
1364 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1365 injectMotionEvent(mDispatcher,
1366 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1367 AINPUT_SOURCE_MOUSE)
1368 .buttonState(0)
1369 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1370 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1371 .x(300)
1372 .y(400))
1373 .build()));
1374 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1375 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1376
1377 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1378 injectMotionEvent(mDispatcher,
1379 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1380 .buttonState(0)
1381 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1382 .x(300)
1383 .y(400))
1384 .build()));
1385 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1386
1387 // Move mouse cursor back to right window
1388 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1389 injectMotionEvent(mDispatcher,
1390 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1391 AINPUT_SOURCE_MOUSE)
1392 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1393 .x(900)
1394 .y(400))
1395 .build()));
1396 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1397 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1398 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1399 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1400 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1401 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1402}
1403
1404// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1405// directly in this test.
1406TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
1407 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1408 sp<FakeWindowHandle> window =
1409 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1410 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001411 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001412
1413 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1414
1415 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1416
1417 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1418 injectMotionEvent(mDispatcher,
1419 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1420 AINPUT_SOURCE_MOUSE)
1421 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1422 .x(300)
1423 .y(400))
1424 .build()));
1425 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1426 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1427
1428 // Inject a series of mouse events for a mouse click
1429 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1430 injectMotionEvent(mDispatcher,
1431 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1432 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1433 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1434 .x(300)
1435 .y(400))
1436 .build()));
1437 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1438
1439 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1440 injectMotionEvent(mDispatcher,
1441 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1442 AINPUT_SOURCE_MOUSE)
1443 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1444 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1445 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1446 .x(300)
1447 .y(400))
1448 .build()));
1449 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1450 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1451
1452 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1453 injectMotionEvent(mDispatcher,
1454 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1455 AINPUT_SOURCE_MOUSE)
1456 .buttonState(0)
1457 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1458 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1459 .x(300)
1460 .y(400))
1461 .build()));
1462 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1463 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1464
1465 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1466 injectMotionEvent(mDispatcher,
1467 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1468 .buttonState(0)
1469 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1470 .x(300)
1471 .y(400))
1472 .build()));
1473 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1474
1475 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1476 injectMotionEvent(mDispatcher,
1477 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1478 AINPUT_SOURCE_MOUSE)
1479 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1480 .x(300)
1481 .y(400))
1482 .build()));
1483 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1484 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1485}
1486
Garfield Tan00f511d2019-06-12 16:55:40 -07001487TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1488 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1489
1490 sp<FakeWindowHandle> windowLeft =
1491 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1492 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001493 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001494 sp<FakeWindowHandle> windowRight =
1495 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1496 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001497 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001498
1499 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1500
Arthur Hung72d8dc32020-03-28 00:48:39 +00001501 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001502
1503 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1504 // left window. This event should be dispatched to the left window.
1505 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1506 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001507 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001508 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001509 windowRight->assertNoEvents();
1510}
1511
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001512TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1513 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1514 sp<FakeWindowHandle> window =
1515 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001516 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001517
Arthur Hung72d8dc32020-03-28 00:48:39 +00001518 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001519 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001520
1521 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1522 mDispatcher->notifyKey(&keyArgs);
1523
1524 // Window should receive key down event.
1525 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1526
1527 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1528 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001529 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001530 mDispatcher->notifyDeviceReset(&args);
1531 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1532 AKEY_EVENT_FLAG_CANCELED);
1533}
1534
1535TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1536 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1537 sp<FakeWindowHandle> window =
1538 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1539
Arthur Hung72d8dc32020-03-28 00:48:39 +00001540 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001541
1542 NotifyMotionArgs motionArgs =
1543 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1544 ADISPLAY_ID_DEFAULT);
1545 mDispatcher->notifyMotion(&motionArgs);
1546
1547 // Window should receive motion down event.
1548 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1549
1550 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1551 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001552 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001553 mDispatcher->notifyDeviceReset(&args);
1554 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1555 0 /*expectedFlags*/);
1556}
1557
Svet Ganov5d3bc372020-01-26 23:11:07 -08001558TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1559 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1560
1561 // Create a couple of windows
1562 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1563 "First Window", ADISPLAY_ID_DEFAULT);
1564 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1565 "Second Window", ADISPLAY_ID_DEFAULT);
1566
1567 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001568 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001569
1570 // Send down to the first window
1571 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1572 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1573 mDispatcher->notifyMotion(&downMotionArgs);
1574 // Only the first window should get the down event
1575 firstWindow->consumeMotionDown();
1576 secondWindow->assertNoEvents();
1577
1578 // Transfer touch focus to the second window
1579 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1580 // The first window gets cancel and the second gets down
1581 firstWindow->consumeMotionCancel();
1582 secondWindow->consumeMotionDown();
1583
1584 // Send up event to the second window
1585 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1586 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1587 mDispatcher->notifyMotion(&upMotionArgs);
1588 // The first window gets no events and the second gets up
1589 firstWindow->assertNoEvents();
1590 secondWindow->consumeMotionUp();
1591}
1592
1593TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1594 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1595
1596 PointF touchPoint = {10, 10};
1597
1598 // Create a couple of windows
1599 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1600 "First Window", ADISPLAY_ID_DEFAULT);
1601 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1602 "Second Window", ADISPLAY_ID_DEFAULT);
1603
1604 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001606
1607 // Send down to the first window
1608 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1609 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1610 mDispatcher->notifyMotion(&downMotionArgs);
1611 // Only the first window should get the down event
1612 firstWindow->consumeMotionDown();
1613 secondWindow->assertNoEvents();
1614
1615 // Send pointer down to the first window
1616 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1617 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1618 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1619 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1620 // Only the first window should get the pointer down event
1621 firstWindow->consumeMotionPointerDown(1);
1622 secondWindow->assertNoEvents();
1623
1624 // Transfer touch focus to the second window
1625 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1626 // The first window gets cancel and the second gets down and pointer down
1627 firstWindow->consumeMotionCancel();
1628 secondWindow->consumeMotionDown();
1629 secondWindow->consumeMotionPointerDown(1);
1630
1631 // Send pointer up to the second window
1632 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1633 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1634 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1635 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1636 // The first window gets nothing and the second gets pointer up
1637 firstWindow->assertNoEvents();
1638 secondWindow->consumeMotionPointerUp(1);
1639
1640 // Send up event to the second window
1641 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1642 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1643 mDispatcher->notifyMotion(&upMotionArgs);
1644 // The first window gets nothing and the second gets up
1645 firstWindow->assertNoEvents();
1646 secondWindow->consumeMotionUp();
1647}
1648
1649TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1650 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1651
1652 // Create a non touch modal window that supports split touch
1653 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1654 "First Window", ADISPLAY_ID_DEFAULT);
1655 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001656 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1657 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001658
1659 // Create a non touch modal window that supports split touch
1660 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1661 "Second Window", ADISPLAY_ID_DEFAULT);
1662 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001663 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1664 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001665
1666 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001668
1669 PointF pointInFirst = {300, 200};
1670 PointF pointInSecond = {300, 600};
1671
1672 // Send down to the first window
1673 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1674 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1675 mDispatcher->notifyMotion(&firstDownMotionArgs);
1676 // Only the first window should get the down event
1677 firstWindow->consumeMotionDown();
1678 secondWindow->assertNoEvents();
1679
1680 // Send down to the second window
1681 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1682 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1683 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1684 mDispatcher->notifyMotion(&secondDownMotionArgs);
1685 // The first window gets a move and the second a down
1686 firstWindow->consumeMotionMove();
1687 secondWindow->consumeMotionDown();
1688
1689 // Transfer touch focus to the second window
1690 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1691 // The first window gets cancel and the new gets pointer down (it already saw down)
1692 firstWindow->consumeMotionCancel();
1693 secondWindow->consumeMotionPointerDown(1);
1694
1695 // Send pointer up to the second window
1696 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1697 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1698 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1699 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1700 // The first window gets nothing and the second gets pointer up
1701 firstWindow->assertNoEvents();
1702 secondWindow->consumeMotionPointerUp(1);
1703
1704 // Send up event to the second window
1705 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1706 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1707 mDispatcher->notifyMotion(&upMotionArgs);
1708 // The first window gets nothing and the second gets up
1709 firstWindow->assertNoEvents();
1710 secondWindow->consumeMotionUp();
1711}
1712
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001713TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1714 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1715 sp<FakeWindowHandle> window =
1716 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1717
1718 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001719 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001720
1721 window->consumeFocusEvent(true);
1722
1723 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1724 mDispatcher->notifyKey(&keyArgs);
1725
1726 // Window should receive key down event.
1727 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1728}
1729
1730TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1731 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1732 sp<FakeWindowHandle> window =
1733 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1734
Arthur Hung72d8dc32020-03-28 00:48:39 +00001735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001736
1737 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1738 mDispatcher->notifyKey(&keyArgs);
1739 mDispatcher->waitForIdle();
1740
1741 window->assertNoEvents();
1742}
1743
1744// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1745TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1746 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1747 sp<FakeWindowHandle> window =
1748 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1749
Arthur Hung72d8dc32020-03-28 00:48:39 +00001750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001751
1752 // Send key
1753 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1754 mDispatcher->notifyKey(&keyArgs);
1755 // Send motion
1756 NotifyMotionArgs motionArgs =
1757 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1758 ADISPLAY_ID_DEFAULT);
1759 mDispatcher->notifyMotion(&motionArgs);
1760
1761 // Window should receive only the motion event
1762 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1763 window->assertNoEvents(); // Key event or focus event will not be received
1764}
1765
chaviwd1c23182019-12-20 18:44:56 -08001766class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001767public:
1768 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001769 int32_t displayId, bool isGestureMonitor = false) {
Siarhei Vishniakoud2588272020-07-10 11:15:40 -05001770 std::unique_ptr<InputChannel> serverChannel, clientChannel;
chaviwd1c23182019-12-20 18:44:56 -08001771 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
Siarhei Vishniakoud2588272020-07-10 11:15:40 -05001772 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
1773 dispatcher->registerInputMonitor(std::move(serverChannel), displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001774 }
1775
chaviwd1c23182019-12-20 18:44:56 -08001776 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1777
1778 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1779 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1780 expectedDisplayId, expectedFlags);
1781 }
1782
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001783 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1784
1785 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1786
chaviwd1c23182019-12-20 18:44:56 -08001787 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1788 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1789 expectedDisplayId, expectedFlags);
1790 }
1791
1792 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1793 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1794 expectedDisplayId, expectedFlags);
1795 }
1796
1797 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1798
1799private:
1800 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001801};
1802
1803// Tests for gesture monitors
1804TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1805 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1806 sp<FakeWindowHandle> window =
1807 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001809
chaviwd1c23182019-12-20 18:44:56 -08001810 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1811 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001812
1813 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1814 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1815 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1816 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001817 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001818}
1819
1820TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1821 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1822 sp<FakeWindowHandle> window =
1823 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1824
1825 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001826 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001827
Arthur Hung72d8dc32020-03-28 00:48:39 +00001828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001829 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001830
chaviwd1c23182019-12-20 18:44:56 -08001831 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1832 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001833
1834 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1835 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1836 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001837 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001838}
1839
1840TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1841 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1842 sp<FakeWindowHandle> window =
1843 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001844 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001845
chaviwd1c23182019-12-20 18:44:56 -08001846 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1847 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001848
1849 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1850 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1851 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1852 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001853 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001854
1855 window->releaseChannel();
1856
chaviwd1c23182019-12-20 18:44:56 -08001857 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001858
1859 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1860 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1861 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001862 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001863}
1864
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001865TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1866 FakeMonitorReceiver monitor =
1867 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1868 true /*isGestureMonitor*/);
1869
1870 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1871 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1872 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1873 ASSERT_TRUE(consumeSeq);
1874
1875 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1876 monitor.finishEvent(*consumeSeq);
1877 ASSERT_TRUE(mDispatcher->waitForIdle());
1878}
1879
chaviw81e2bb92019-12-18 15:03:51 -08001880TEST_F(InputDispatcherTest, TestMoveEvent) {
1881 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1882 sp<FakeWindowHandle> window =
1883 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1884
Arthur Hung72d8dc32020-03-28 00:48:39 +00001885 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001886
1887 NotifyMotionArgs motionArgs =
1888 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1889 ADISPLAY_ID_DEFAULT);
1890
1891 mDispatcher->notifyMotion(&motionArgs);
1892 // Window should receive motion down event.
1893 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1894
1895 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001896 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001897 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1898 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1899 motionArgs.pointerCoords[0].getX() - 10);
1900
1901 mDispatcher->notifyMotion(&motionArgs);
1902 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1903 0 /*expectedFlags*/);
1904}
1905
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001906/**
1907 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1908 * the device default right away. In the test scenario, we check both the default value,
1909 * and the action of enabling / disabling.
1910 */
1911TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1912 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1913 sp<FakeWindowHandle> window =
1914 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1915
1916 // Set focused application.
1917 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1918 window->setFocus(true);
1919
1920 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001922 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1923
1924 SCOPED_TRACE("Remove the window to trigger focus loss");
1925 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001926 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001927 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1928
1929 SCOPED_TRACE("Disable touch mode");
1930 mDispatcher->setInTouchMode(false);
1931 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001933 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1934
1935 SCOPED_TRACE("Remove the window to trigger focus loss");
1936 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001938 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1939
1940 SCOPED_TRACE("Enable touch mode again");
1941 mDispatcher->setInTouchMode(true);
1942 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001943 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001944 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1945
1946 window->assertNoEvents();
1947}
1948
Gang Wange9087892020-01-07 12:17:14 -05001949TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1950 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1951 sp<FakeWindowHandle> window =
1952 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1953
1954 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1955 window->setFocus(true);
1956
Arthur Hung72d8dc32020-03-28 00:48:39 +00001957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001958 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1959
1960 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1961 mDispatcher->notifyKey(&keyArgs);
1962
1963 InputEvent* event = window->consume();
1964 ASSERT_NE(event, nullptr);
1965
1966 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1967 ASSERT_NE(verified, nullptr);
1968 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1969
1970 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1971 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1972 ASSERT_EQ(keyArgs.source, verified->source);
1973 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1974
1975 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1976
1977 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1978 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001979 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1980 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1981 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1982 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1983 ASSERT_EQ(0, verifiedKey.repeatCount);
1984}
1985
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001986TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1987 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1988 sp<FakeWindowHandle> window =
1989 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1990
1991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1992
Arthur Hung72d8dc32020-03-28 00:48:39 +00001993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001994
1995 NotifyMotionArgs motionArgs =
1996 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1997 ADISPLAY_ID_DEFAULT);
1998 mDispatcher->notifyMotion(&motionArgs);
1999
2000 InputEvent* event = window->consume();
2001 ASSERT_NE(event, nullptr);
2002
2003 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2004 ASSERT_NE(verified, nullptr);
2005 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2006
2007 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2008 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2009 EXPECT_EQ(motionArgs.source, verified->source);
2010 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2011
2012 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2013
2014 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2015 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2016 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2017 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2018 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2019 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2020 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2021}
2022
Garfield Tan1c7bc862020-01-28 13:24:04 -08002023class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2024protected:
2025 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2026 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2027
2028 sp<FakeApplicationHandle> mApp;
2029 sp<FakeWindowHandle> mWindow;
2030
2031 virtual void SetUp() override {
2032 mFakePolicy = new FakeInputDispatcherPolicy();
2033 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2034 mDispatcher = new InputDispatcher(mFakePolicy);
2035 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2036 ASSERT_EQ(OK, mDispatcher->start());
2037
2038 setUpWindow();
2039 }
2040
2041 void setUpWindow() {
2042 mApp = new FakeApplicationHandle();
2043 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2044
2045 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08002047
2048 mWindow->consumeFocusEvent(true);
2049 }
2050
2051 void sendAndConsumeKeyDown() {
2052 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2053 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2054 mDispatcher->notifyKey(&keyArgs);
2055
2056 // Window should receive key down event.
2057 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2058 }
2059
2060 void expectKeyRepeatOnce(int32_t repeatCount) {
2061 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2062 InputEvent* repeatEvent = mWindow->consume();
2063 ASSERT_NE(nullptr, repeatEvent);
2064
2065 uint32_t eventType = repeatEvent->getType();
2066 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2067
2068 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2069 uint32_t eventAction = repeatKeyEvent->getAction();
2070 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2071 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2072 }
2073
2074 void sendAndConsumeKeyUp() {
2075 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2076 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2077 mDispatcher->notifyKey(&keyArgs);
2078
2079 // Window should receive key down event.
2080 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2081 0 /*expectedFlags*/);
2082 }
2083};
2084
2085TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
2086 sendAndConsumeKeyDown();
2087 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2088 expectKeyRepeatOnce(repeatCount);
2089 }
2090}
2091
2092TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
2093 sendAndConsumeKeyDown();
2094 expectKeyRepeatOnce(1 /*repeatCount*/);
2095 sendAndConsumeKeyUp();
2096 mWindow->assertNoEvents();
2097}
2098
2099TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
2100 sendAndConsumeKeyDown();
2101 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2102 InputEvent* repeatEvent = mWindow->consume();
2103 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2104 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2105 IdGenerator::getSource(repeatEvent->getId()));
2106 }
2107}
2108
2109TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
2110 sendAndConsumeKeyDown();
2111
2112 std::unordered_set<int32_t> idSet;
2113 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2114 InputEvent* repeatEvent = mWindow->consume();
2115 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2116 int32_t id = repeatEvent->getId();
2117 EXPECT_EQ(idSet.end(), idSet.find(id));
2118 idSet.insert(id);
2119 }
2120}
2121
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002122/* Test InputDispatcher for MultiDisplay */
2123class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2124public:
2125 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002126 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002127 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002128
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002129 application1 = new FakeApplicationHandle();
2130 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
2131 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002132
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002133 // Set focus window for primary display, but focused display would be second one.
2134 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002135 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002137 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002138
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002139 application2 = new FakeApplicationHandle();
2140 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
2141 SECOND_DISPLAY_ID);
2142 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002143 // Set focus display to second one.
2144 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2145 // Set focus window for second display.
2146 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002147 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002148 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002149 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002150 }
2151
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002152 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002153 InputDispatcherTest::TearDown();
2154
2155 application1.clear();
2156 windowInPrimary.clear();
2157 application2.clear();
2158 windowInSecondary.clear();
2159 }
2160
2161protected:
2162 sp<FakeApplicationHandle> application1;
2163 sp<FakeWindowHandle> windowInPrimary;
2164 sp<FakeApplicationHandle> application2;
2165 sp<FakeWindowHandle> windowInSecondary;
2166};
2167
2168TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2169 // Test touch down on primary display.
2170 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2171 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08002172 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002173 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002174 windowInSecondary->assertNoEvents();
2175
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002176 // Test touch down on second display.
2177 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2178 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08002179 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2180 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002181 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002182}
2183
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002184TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002185 // Test inject a key down with display id specified.
2186 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2187 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002188 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002189 windowInSecondary->assertNoEvents();
2190
2191 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08002192 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2193 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2194 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002195 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002196
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002197 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002198 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002199
2200 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002201 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2202 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002203
2204 // Test inject a key down, should timeout because of no target window.
2205 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
2206 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
2207 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002208 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002209 windowInSecondary->assertNoEvents();
2210}
2211
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002212// Test per-display input monitors for motion event.
2213TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002214 FakeMonitorReceiver monitorInPrimary =
2215 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2216 FakeMonitorReceiver monitorInSecondary =
2217 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002218
2219 // Test touch down on primary display.
2220 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2221 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2222 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002223 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002224 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002225 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002226 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002227
2228 // Test touch down on second display.
2229 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2230 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2231 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2232 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002233 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002234 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002235 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002236
2237 // Test inject a non-pointer motion event.
2238 // If specific a display, it will dispatch to the focused window of particular display,
2239 // or it will dispatch to the focused window of focused display.
2240 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
2241 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2242 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2243 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002244 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002245 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002246 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002247}
2248
2249// Test per-display input monitors for key event.
2250TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
2251 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002252 FakeMonitorReceiver monitorInPrimary =
2253 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2254 FakeMonitorReceiver monitorInSecondary =
2255 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002256
2257 // Test inject a key down.
2258 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
2259 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2260 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002261 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002262 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002263 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002264}
2265
Jackal Guof9696682018-10-05 12:23:23 +08002266class InputFilterTest : public InputDispatcherTest {
2267protected:
2268 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2269
2270 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2271 NotifyMotionArgs motionArgs;
2272
2273 motionArgs = generateMotionArgs(
2274 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2275 mDispatcher->notifyMotion(&motionArgs);
2276 motionArgs = generateMotionArgs(
2277 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2278 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002279 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002280 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002281 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002282 } else {
2283 mFakePolicy->assertFilterInputEventWasNotCalled();
2284 }
2285 }
2286
2287 void testNotifyKey(bool expectToBeFiltered) {
2288 NotifyKeyArgs keyArgs;
2289
2290 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2291 mDispatcher->notifyKey(&keyArgs);
2292 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2293 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002294 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002295
2296 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002297 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002298 } else {
2299 mFakePolicy->assertFilterInputEventWasNotCalled();
2300 }
2301 }
2302};
2303
2304// Test InputFilter for MotionEvent
2305TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2306 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2307 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2308 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2309
2310 // Enable InputFilter
2311 mDispatcher->setInputFilterEnabled(true);
2312 // Test touch on both primary and second display, and check if both events are filtered.
2313 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2314 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2315
2316 // Disable InputFilter
2317 mDispatcher->setInputFilterEnabled(false);
2318 // Test touch on both primary and second display, and check if both events aren't filtered.
2319 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2320 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2321}
2322
2323// Test InputFilter for KeyEvent
2324TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2325 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2326 testNotifyKey(/*expectToBeFiltered*/ false);
2327
2328 // Enable InputFilter
2329 mDispatcher->setInputFilterEnabled(true);
2330 // Send a key event, and check if it is filtered.
2331 testNotifyKey(/*expectToBeFiltered*/ true);
2332
2333 // Disable InputFilter
2334 mDispatcher->setInputFilterEnabled(false);
2335 // Send a key event, and check if it isn't filtered.
2336 testNotifyKey(/*expectToBeFiltered*/ false);
2337}
2338
chaviwfd6d3512019-03-25 13:23:49 -07002339class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002340 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002341 InputDispatcherTest::SetUp();
2342
2343 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2344 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2345 ADISPLAY_ID_DEFAULT);
2346 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2347 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2348 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002349 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002350
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002351 mFocusedWindow =
2352 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2353 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002354 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002355
2356 // Set focused application.
2357 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002358 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07002359
2360 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002361 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002362 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002363 }
2364
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002365 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002366 InputDispatcherTest::TearDown();
2367
2368 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002369 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002370 }
2371
2372protected:
2373 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002374 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002375 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002376};
2377
2378// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2379// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2380// the onPointerDownOutsideFocus callback.
2381TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002382 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2383 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2384 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002385 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002386 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002387
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002388 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002389 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2390}
2391
2392// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2393// DOWN on the window that doesn't have focus. Ensure no window received the
2394// onPointerDownOutsideFocus callback.
2395TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002396 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2397 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002398 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002399 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002400
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002401 ASSERT_TRUE(mDispatcher->waitForIdle());
2402 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002403}
2404
2405// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2406// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2407TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2408 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2409 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002410 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002411
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002412 ASSERT_TRUE(mDispatcher->waitForIdle());
2413 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002414}
2415
2416// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2417// DOWN on the window that already has focus. Ensure no window received the
2418// onPointerDownOutsideFocus callback.
2419TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2420 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002421 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2422 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002423 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002424 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002425 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002426
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002427 ASSERT_TRUE(mDispatcher->waitForIdle());
2428 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002429}
2430
chaviwaf87b3e2019-10-01 16:59:28 -07002431// These tests ensures we can send touch events to a single client when there are multiple input
2432// windows that point to the same client token.
2433class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2434 virtual void SetUp() override {
2435 InputDispatcherTest::SetUp();
2436
2437 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2438 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2439 ADISPLAY_ID_DEFAULT);
2440 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2441 // 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 +01002442 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2443 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002444 mWindow1->setFrame(Rect(0, 0, 100, 100));
2445
2446 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2447 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002448 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2449 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002450 mWindow2->setFrame(Rect(100, 100, 200, 200));
2451
Arthur Hung72d8dc32020-03-28 00:48:39 +00002452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002453 }
2454
2455protected:
2456 sp<FakeWindowHandle> mWindow1;
2457 sp<FakeWindowHandle> mWindow2;
2458
2459 // Helper function to convert the point from screen coordinates into the window's space
2460 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002461 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2462 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002463 }
2464
2465 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2466 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002467 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002468 InputEvent* event = window->consume();
2469
2470 ASSERT_NE(nullptr, event) << name.c_str()
2471 << ": consumer should have returned non-NULL event.";
2472
2473 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2474 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2475 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2476
2477 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2478 EXPECT_EQ(expectedAction, motionEvent.getAction());
2479
2480 for (size_t i = 0; i < points.size(); i++) {
2481 float expectedX = points[i].x;
2482 float expectedY = points[i].y;
2483
2484 EXPECT_EQ(expectedX, motionEvent.getX(i))
2485 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2486 << ", got " << motionEvent.getX(i);
2487 EXPECT_EQ(expectedY, motionEvent.getY(i))
2488 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2489 << ", got " << motionEvent.getY(i);
2490 }
2491 }
chaviw9eaa22c2020-07-01 16:21:27 -07002492
2493 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
2494 std::vector<PointF> expectedPoints) {
2495 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
2496 ADISPLAY_ID_DEFAULT, touchedPoints);
2497 mDispatcher->notifyMotion(&motionArgs);
2498
2499 // Always consume from window1 since it's the window that has the InputReceiver
2500 consumeMotionEvent(mWindow1, action, expectedPoints);
2501 }
chaviwaf87b3e2019-10-01 16:59:28 -07002502};
2503
2504TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2505 // Touch Window 1
2506 PointF touchedPoint = {10, 10};
2507 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002508 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002509
2510 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002511 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002512
2513 // Touch Window 2
2514 touchedPoint = {150, 150};
2515 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002516 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002517}
2518
chaviw9eaa22c2020-07-01 16:21:27 -07002519TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
2520 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07002521 mWindow2->setWindowScale(0.5f, 0.5f);
2522
2523 // Touch Window 1
2524 PointF touchedPoint = {10, 10};
2525 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002526 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002527 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002528 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002529
2530 // Touch Window 2
2531 touchedPoint = {150, 150};
2532 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002533 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
2534 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002535
chaviw9eaa22c2020-07-01 16:21:27 -07002536 // Update the transform so rotation is set
2537 mWindow2->setWindowTransform(0, -1, 1, 0);
2538 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2539 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002540}
2541
chaviw9eaa22c2020-07-01 16:21:27 -07002542TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002543 mWindow2->setWindowScale(0.5f, 0.5f);
2544
2545 // Touch Window 1
2546 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2547 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002548 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002549
2550 // Touch Window 2
2551 int32_t actionPointerDown =
2552 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002553 touchedPoints.push_back(PointF{150, 150});
2554 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2555 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002556
chaviw9eaa22c2020-07-01 16:21:27 -07002557 // Release Window 2
2558 int32_t actionPointerUp =
2559 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2560 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2561 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002562
chaviw9eaa22c2020-07-01 16:21:27 -07002563 // Update the transform so rotation is set for Window 2
2564 mWindow2->setWindowTransform(0, -1, 1, 0);
2565 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2566 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002567}
2568
chaviw9eaa22c2020-07-01 16:21:27 -07002569TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002570 mWindow2->setWindowScale(0.5f, 0.5f);
2571
2572 // Touch Window 1
2573 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2574 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002575 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002576
2577 // Touch Window 2
2578 int32_t actionPointerDown =
2579 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002580 touchedPoints.push_back(PointF{150, 150});
2581 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002582
chaviw9eaa22c2020-07-01 16:21:27 -07002583 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002584
2585 // Move both windows
2586 touchedPoints = {{20, 20}, {175, 175}};
2587 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2588 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2589
chaviw9eaa22c2020-07-01 16:21:27 -07002590 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002591
chaviw9eaa22c2020-07-01 16:21:27 -07002592 // Release Window 2
2593 int32_t actionPointerUp =
2594 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2595 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2596 expectedPoints.pop_back();
2597
2598 // Touch Window 2
2599 mWindow2->setWindowTransform(0, -1, 1, 0);
2600 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2601 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
2602
2603 // Move both windows
2604 touchedPoints = {{20, 20}, {175, 175}};
2605 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2606 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2607
2608 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002609}
2610
2611TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2612 mWindow1->setWindowScale(0.5f, 0.5f);
2613
2614 // Touch Window 1
2615 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2616 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002617 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002618
2619 // Touch Window 2
2620 int32_t actionPointerDown =
2621 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002622 touchedPoints.push_back(PointF{150, 150});
2623 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002624
chaviw9eaa22c2020-07-01 16:21:27 -07002625 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002626
2627 // Move both windows
2628 touchedPoints = {{20, 20}, {175, 175}};
2629 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2630 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2631
chaviw9eaa22c2020-07-01 16:21:27 -07002632 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002633}
2634
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002635class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2636 virtual void SetUp() override {
2637 InputDispatcherTest::SetUp();
2638
2639 mApplication = new FakeApplicationHandle();
2640 mApplication->setDispatchingTimeout(20ms);
2641 mWindow =
2642 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2643 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002644 mWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002645 mWindow->setFocus(true);
2646 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2647 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002648 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002649
2650 // Set focused application.
2651 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2652
2653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2654 mWindow->consumeFocusEvent(true);
2655 }
2656
2657 virtual void TearDown() override {
2658 InputDispatcherTest::TearDown();
2659 mWindow.clear();
2660 }
2661
2662protected:
2663 sp<FakeApplicationHandle> mApplication;
2664 sp<FakeWindowHandle> mWindow;
2665 static constexpr PointF WINDOW_LOCATION = {20, 20};
2666
2667 void tapOnWindow() {
2668 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2669 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2670 WINDOW_LOCATION));
2671 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2672 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2673 WINDOW_LOCATION));
2674 }
2675};
2676
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002677// Send a tap and respond, which should not cause an ANR.
2678TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2679 tapOnWindow();
2680 mWindow->consumeMotionDown();
2681 mWindow->consumeMotionUp();
2682 ASSERT_TRUE(mDispatcher->waitForIdle());
2683 mFakePolicy->assertNotifyAnrWasNotCalled();
2684}
2685
2686// Send a regular key and respond, which should not cause an ANR.
2687TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
2688 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2689 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2690 ASSERT_TRUE(mDispatcher->waitForIdle());
2691 mFakePolicy->assertNotifyAnrWasNotCalled();
2692}
2693
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002694// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002695// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2696// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002697TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2698 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2699 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2700 WINDOW_LOCATION));
2701
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002702 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2703 ASSERT_TRUE(sequenceNum);
2704 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2705 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002706
2707 // The remaining lines are not really needed for the test, but kept as a sanity check
2708 mWindow->finishEvent(*sequenceNum);
2709 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2710 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002711 ASSERT_TRUE(mDispatcher->waitForIdle());
2712}
2713
2714// Send a key to the app and have the app not respond right away.
2715TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2716 // Inject a key, and don't respond - expect that ANR is called.
2717 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2718 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2719 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002720 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002721 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002722 ASSERT_TRUE(mDispatcher->waitForIdle());
2723}
2724
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002725// We have a focused application, but no focused window
2726TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
2727 mWindow->setFocus(false);
2728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2729 mWindow->consumeFocusEvent(false);
2730
2731 // taps on the window work as normal
2732 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2733 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2734 WINDOW_LOCATION));
2735 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2736 mDispatcher->waitForIdle();
2737 mFakePolicy->assertNotifyAnrWasNotCalled();
2738
2739 // Once a focused event arrives, we get an ANR for this application
2740 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2741 // injection times out (instead of failing).
2742 const int32_t result =
2743 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2744 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2745 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2746 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2747 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2748 ASSERT_TRUE(mDispatcher->waitForIdle());
2749}
2750
2751// We have a focused application, but no focused window
2752// If the policy wants to keep waiting on the focused window to be added, make sure
2753// that this timeout extension is honored and ANR is raised again.
2754TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
2755 mWindow->setFocus(false);
2756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2757 mWindow->consumeFocusEvent(false);
2758 const std::chrono::duration timeout = 5ms;
2759 mFakePolicy->setAnrTimeout(timeout);
2760
2761 // Once a focused event arrives, we get an ANR for this application
2762 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2763 // injection times out (instead of failing).
2764 const int32_t result =
2765 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2766 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2767 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2768 const std::chrono::duration appTimeout =
2769 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2770 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2771
2772 // After the extended time has passed, ANR should be raised again
2773 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2774
2775 // If we stop extending the timeout, dispatcher should go to idle.
2776 // Another ANR may be raised during this time
2777 mFakePolicy->setAnrTimeout(0ms);
2778 ASSERT_TRUE(mDispatcher->waitForIdle());
2779}
2780
2781// We have a focused application, but no focused window
2782TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
2783 mWindow->setFocus(false);
2784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2785 mWindow->consumeFocusEvent(false);
2786
2787 // Once a focused event arrives, we get an ANR for this application
2788 const int32_t result =
2789 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2790 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2791 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2792
2793 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2794 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2795
2796 // Future focused events get dropped right away
2797 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, injectKeyDown(mDispatcher));
2798 ASSERT_TRUE(mDispatcher->waitForIdle());
2799 mWindow->assertNoEvents();
2800}
2801
2802/**
2803 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2804 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2805 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2806 * the ANR mechanism should still work.
2807 *
2808 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2809 * DOWN event, while not responding on the second one.
2810 */
2811TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2812 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2813 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2814 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2815 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2816 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2817 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2818
2819 // Now send ACTION_UP, with identical timestamp
2820 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2821 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2822 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2823 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2824 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2825
2826 // We have now sent down and up. Let's consume first event and then ANR on the second.
2827 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2828 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2829 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2830}
2831
2832// If an app is not responding to a key event, gesture monitors should continue to receive
2833// new motion events
2834TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
2835 FakeMonitorReceiver monitor =
2836 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2837 true /*isGestureMonitor*/);
2838
2839 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
2840 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2841 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
2842
2843 // Stuck on the ACTION_UP
2844 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2845 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2846
2847 // New tap will go to the gesture monitor, but not to the window
2848 tapOnWindow();
2849 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2850 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2851
2852 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2853 mDispatcher->waitForIdle();
2854 mWindow->assertNoEvents();
2855 monitor.assertNoEvents();
2856}
2857
2858// If an app is not responding to a motion event, gesture monitors should continue to receive
2859// new motion events
2860TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
2861 FakeMonitorReceiver monitor =
2862 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2863 true /*isGestureMonitor*/);
2864
2865 tapOnWindow();
2866 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2867 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2868
2869 mWindow->consumeMotionDown();
2870 // Stuck on the ACTION_UP
2871 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2872 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2873
2874 // New tap will go to the gesture monitor, but not to the window
2875 tapOnWindow();
2876 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2877 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2878
2879 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2880 mDispatcher->waitForIdle();
2881 mWindow->assertNoEvents();
2882 monitor.assertNoEvents();
2883}
2884
2885// If a window is unresponsive, then you get anr. if the window later catches up and starts to
2886// process events, you don't get an anr. When the window later becomes unresponsive again, you
2887// get an ANR again.
2888// 1. tap -> block on ACTION_UP -> receive ANR
2889// 2. consume all pending events (= queue becomes healthy again)
2890// 3. tap again -> block on ACTION_UP again -> receive ANR second time
2891TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
2892 tapOnWindow();
2893
2894 mWindow->consumeMotionDown();
2895 // Block on ACTION_UP
2896 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2897 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2898 mWindow->consumeMotionUp(); // Now the connection should be healthy again
2899 mDispatcher->waitForIdle();
2900 mWindow->assertNoEvents();
2901
2902 tapOnWindow();
2903 mWindow->consumeMotionDown();
2904 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2905 mWindow->consumeMotionUp();
2906
2907 mDispatcher->waitForIdle();
2908 mWindow->assertNoEvents();
2909}
2910
2911// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
2912// is honored
2913TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
2914 const std::chrono::duration timeout = 5ms;
2915 mFakePolicy->setAnrTimeout(timeout);
2916
2917 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2918 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2919 WINDOW_LOCATION));
2920
2921 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2922 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
2923 mWindow->getToken());
2924
2925 // Since the policy wanted to extend ANR, make sure it is called again after the extension
2926 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2927 mFakePolicy->setAnrTimeout(0ms);
2928 std::this_thread::sleep_for(windowTimeout);
2929 // We are not checking if ANR has been called, because it may have been called again by the
2930 // time we set the timeout to 0
2931
2932 // When the policy finally says stop, we should get ACTION_CANCEL
2933 mWindow->consumeMotionDown();
2934 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2935 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2936 mWindow->assertNoEvents();
2937}
2938
2939/**
2940 * If a window is processing a motion event, and then a key event comes in, the key event should
2941 * not to to the focused window until the motion is processed.
2942 *
2943 * Warning!!!
2944 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2945 * and the injection timeout that we specify when injecting the key.
2946 * We must have the injection timeout (10ms) be smaller than
2947 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2948 *
2949 * If that value changes, this test should also change.
2950 */
2951TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
2952 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2953 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2954
2955 tapOnWindow();
2956 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2957 ASSERT_TRUE(downSequenceNum);
2958 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2959 ASSERT_TRUE(upSequenceNum);
2960 // Don't finish the events yet, and send a key
2961 // Injection will "succeed" because we will eventually give up and send the key to the focused
2962 // window even if motions are still being processed. But because the injection timeout is short,
2963 // we will receive INJECTION_TIMED_OUT as the result.
2964
2965 int32_t result =
2966 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2967 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2968 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2969 // Key will not be sent to the window, yet, because the window is still processing events
2970 // and the key remains pending, waiting for the touch events to be processed
2971 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2972 ASSERT_FALSE(keySequenceNum);
2973
2974 std::this_thread::sleep_for(500ms);
2975 // if we wait long enough though, dispatcher will give up, and still send the key
2976 // to the focused window, even though we have not yet finished the motion event
2977 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2978 mWindow->finishEvent(*downSequenceNum);
2979 mWindow->finishEvent(*upSequenceNum);
2980}
2981
2982/**
2983 * If a window is processing a motion event, and then a key event comes in, the key event should
2984 * not go to the focused window until the motion is processed.
2985 * If then a new motion comes in, then the pending key event should be going to the currently
2986 * focused window right away.
2987 */
2988TEST_F(InputDispatcherSingleWindowAnr,
2989 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
2990 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2992
2993 tapOnWindow();
2994 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2995 ASSERT_TRUE(downSequenceNum);
2996 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2997 ASSERT_TRUE(upSequenceNum);
2998 // Don't finish the events yet, and send a key
2999 // Injection is async, so it will succeed
3000 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3001 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
3002 ADISPLAY_ID_DEFAULT, INPUT_EVENT_INJECTION_SYNC_NONE));
3003 // At this point, key is still pending, and should not be sent to the application yet.
3004 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3005 ASSERT_FALSE(keySequenceNum);
3006
3007 // Now tap down again. It should cause the pending key to go to the focused window right away.
3008 tapOnWindow();
3009 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3010 // the other events yet. We can finish events in any order.
3011 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3012 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3013 mWindow->consumeMotionDown();
3014 mWindow->consumeMotionUp();
3015 mWindow->assertNoEvents();
3016}
3017
3018class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3019 virtual void SetUp() override {
3020 InputDispatcherTest::SetUp();
3021
3022 mApplication = new FakeApplicationHandle();
3023 mApplication->setDispatchingTimeout(10ms);
3024 mUnfocusedWindow =
3025 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3026 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3027 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3028 // window.
3029 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003030 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3031 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3032 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003033
3034 mFocusedWindow =
3035 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003036 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003037 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003038 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3039 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003040
3041 // Set focused application.
3042 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3043 mFocusedWindow->setFocus(true);
3044
3045 // Expect one focus window exist in display.
3046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3047 mFocusedWindow->consumeFocusEvent(true);
3048 }
3049
3050 virtual void TearDown() override {
3051 InputDispatcherTest::TearDown();
3052
3053 mUnfocusedWindow.clear();
3054 mFocusedWindow.clear();
3055 }
3056
3057protected:
3058 sp<FakeApplicationHandle> mApplication;
3059 sp<FakeWindowHandle> mUnfocusedWindow;
3060 sp<FakeWindowHandle> mFocusedWindow;
3061 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3062 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3063 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3064
3065 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3066
3067 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3068
3069private:
3070 void tap(const PointF& location) {
3071 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3072 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3073 location));
3074 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3075 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3076 location));
3077 }
3078};
3079
3080// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3081// should be ANR'd first.
3082TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
3083 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3084 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3085 FOCUSED_WINDOW_LOCATION))
3086 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
3087 mFocusedWindow->consumeMotionDown();
3088 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3089 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3090 // We consumed all events, so no ANR
3091 ASSERT_TRUE(mDispatcher->waitForIdle());
3092 mFakePolicy->assertNotifyAnrWasNotCalled();
3093
3094 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
3095 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3096 FOCUSED_WINDOW_LOCATION));
3097 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3098 ASSERT_TRUE(unfocusedSequenceNum);
3099 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
3100 ASSERT_TRUE(focusedSequenceNum);
3101
3102 const std::chrono::duration timeout =
3103 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3104 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3105 mFocusedWindow->getToken());
3106
3107 mFocusedWindow->finishEvent(*focusedSequenceNum);
3108 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
3109 ASSERT_TRUE(mDispatcher->waitForIdle());
3110}
3111
3112// If we have 2 windows with identical timeouts that are both unresponsive,
3113// it doesn't matter which order they should have ANR.
3114// But we should receive ANR for both.
3115TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3116 // Set the timeout for unfocused window to match the focused window
3117 mUnfocusedWindow->setDispatchingTimeout(10ms);
3118 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3119
3120 tapOnFocusedWindow();
3121 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
3122 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData1 =
3123 mFakePolicy->getNotifyAnrData(10ms);
3124 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData2 =
3125 mFakePolicy->getNotifyAnrData(0ms);
3126
3127 // We don't know which window will ANR first. But both of them should happen eventually.
3128 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
3129 mFocusedWindow->getToken() == anrData2.second);
3130 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
3131 mUnfocusedWindow->getToken() == anrData2.second);
3132
3133 ASSERT_TRUE(mDispatcher->waitForIdle());
3134 mFakePolicy->assertNotifyAnrWasNotCalled();
3135}
3136
3137// If a window is already not responding, the second tap on the same window should be ignored.
3138// We should also log an error to account for the dropped event (not tested here).
3139// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3140TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3141 tapOnFocusedWindow();
3142 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3143 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3144 // Receive the events, but don't respond
3145 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3146 ASSERT_TRUE(downEventSequenceNum);
3147 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3148 ASSERT_TRUE(upEventSequenceNum);
3149 const std::chrono::duration timeout =
3150 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3151 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3152 mFocusedWindow->getToken());
3153
3154 // Tap once again
3155 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
3156 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3157 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3158 FOCUSED_WINDOW_LOCATION));
3159 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3160 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3161 FOCUSED_WINDOW_LOCATION));
3162 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3163 // valid touch target
3164 mUnfocusedWindow->assertNoEvents();
3165
3166 // Consume the first tap
3167 mFocusedWindow->finishEvent(*downEventSequenceNum);
3168 mFocusedWindow->finishEvent(*upEventSequenceNum);
3169 ASSERT_TRUE(mDispatcher->waitForIdle());
3170 // The second tap did not go to the focused window
3171 mFocusedWindow->assertNoEvents();
3172 // should not have another ANR after the window just became healthy again
3173 mFakePolicy->assertNotifyAnrWasNotCalled();
3174}
3175
3176// If you tap outside of all windows, there will not be ANR
3177TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
3178 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3179 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3180 LOCATION_OUTSIDE_ALL_WINDOWS));
3181 ASSERT_TRUE(mDispatcher->waitForIdle());
3182 mFakePolicy->assertNotifyAnrWasNotCalled();
3183}
3184
3185// Since the focused window is paused, tapping on it should not produce any events
3186TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3187 mFocusedWindow->setPaused(true);
3188 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3189
3190 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
3191 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3192 FOCUSED_WINDOW_LOCATION));
3193
3194 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3195 ASSERT_TRUE(mDispatcher->waitForIdle());
3196 // Should not ANR because the window is paused, and touches shouldn't go to it
3197 mFakePolicy->assertNotifyAnrWasNotCalled();
3198
3199 mFocusedWindow->assertNoEvents();
3200 mUnfocusedWindow->assertNoEvents();
3201}
3202
3203/**
3204 * If a window is processing a motion event, and then a key event comes in, the key event should
3205 * not to to the focused window until the motion is processed.
3206 * If a different window becomes focused at this time, the key should go to that window instead.
3207 *
3208 * Warning!!!
3209 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3210 * and the injection timeout that we specify when injecting the key.
3211 * We must have the injection timeout (10ms) be smaller than
3212 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3213 *
3214 * If that value changes, this test should also change.
3215 */
3216TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3217 // Set a long ANR timeout to prevent it from triggering
3218 mFocusedWindow->setDispatchingTimeout(2s);
3219 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3220
3221 tapOnUnfocusedWindow();
3222 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3223 ASSERT_TRUE(downSequenceNum);
3224 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3225 ASSERT_TRUE(upSequenceNum);
3226 // Don't finish the events yet, and send a key
3227 // Injection will succeed because we will eventually give up and send the key to the focused
3228 // window even if motions are still being processed.
3229
3230 int32_t result =
3231 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
3232 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
3233 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
3234 // Key will not be sent to the window, yet, because the window is still processing events
3235 // and the key remains pending, waiting for the touch events to be processed
3236 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3237 ASSERT_FALSE(keySequenceNum);
3238
3239 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
3240 mFocusedWindow->setFocus(false);
3241 mUnfocusedWindow->setFocus(true);
3242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3243
3244 // Focus events should precede the key events
3245 mUnfocusedWindow->consumeFocusEvent(true);
3246 mFocusedWindow->consumeFocusEvent(false);
3247
3248 // Finish the tap events, which should unblock dispatcher
3249 mUnfocusedWindow->finishEvent(*downSequenceNum);
3250 mUnfocusedWindow->finishEvent(*upSequenceNum);
3251
3252 // Now that all queues are cleared and no backlog in the connections, the key event
3253 // can finally go to the newly focused "mUnfocusedWindow".
3254 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3255 mFocusedWindow->assertNoEvents();
3256 mUnfocusedWindow->assertNoEvents();
3257}
3258
3259// When the touch stream is split across 2 windows, and one of them does not respond,
3260// then ANR should be raised and the touch should be canceled for the unresponsive window.
3261// The other window should not be affected by that.
3262TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3263 // Touch Window 1
3264 NotifyMotionArgs motionArgs =
3265 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3266 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3267 mDispatcher->notifyMotion(&motionArgs);
3268 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3269 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3270
3271 // Touch Window 2
3272 int32_t actionPointerDown =
3273 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3274
3275 motionArgs =
3276 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3277 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3278 mDispatcher->notifyMotion(&motionArgs);
3279
3280 const std::chrono::duration timeout =
3281 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3282 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3283 mFocusedWindow->getToken());
3284
3285 mUnfocusedWindow->consumeMotionDown();
3286 mFocusedWindow->consumeMotionDown();
3287 // Focused window may or may not receive ACTION_MOVE
3288 // But it should definitely receive ACTION_CANCEL due to the ANR
3289 InputEvent* event;
3290 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3291 ASSERT_TRUE(moveOrCancelSequenceNum);
3292 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3293 ASSERT_NE(nullptr, event);
3294 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3295 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3296 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3297 mFocusedWindow->consumeMotionCancel();
3298 } else {
3299 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3300 }
3301
3302 ASSERT_TRUE(mDispatcher->waitForIdle());
3303 mUnfocusedWindow->assertNoEvents();
3304 mFocusedWindow->assertNoEvents();
3305}
3306
Garfield Tane84e6f92019-08-29 17:28:41 -07003307} // namespace android::inputdispatcher