blob: 8d80f2aa4842c6baa2cc1f1ecb6192a7165d22e4 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan1c7bc862020-01-28 13:24:04 -080019#include <android-base/stringprintf.h>
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -070020#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
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 Vishniakouffaa2b12020-05-26 21:43:02 -070027#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080029#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031using android::base::StringPrintf;
32
Garfield Tane84e6f92019-08-29 17:28:41 -070033namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080034
35// An arbitrary time value.
36static const nsecs_t ARBITRARY_TIME = 1234;
37
38// An arbitrary device id.
39static const int32_t DEVICE_ID = 1;
40
Jeff Brownf086ddb2014-02-11 14:28:48 -080041// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080042static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080043
Michael Wrightd02c5b62014-02-10 15:10:22 -080044// An arbitrary injector pid / uid pair that has permission to inject events.
45static const int32_t INJECTOR_PID = 999;
46static const int32_t INJECTOR_UID = 1001;
47
chaviwd1c23182019-12-20 18:44:56 -080048struct PointF {
49 float x;
50 float y;
51};
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
Gang Wang342c9272020-01-13 13:15:04 -050053/**
54 * Return a DOWN key event with KEYCODE_A.
55 */
56static KeyEvent getTestKeyEvent() {
57 KeyEvent event;
58
Garfield Tanfbe732e2020-01-24 11:26:14 -080059 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
60 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
61 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050062 return event;
63}
64
Michael Wrightd02c5b62014-02-10 15:10:22 -080065// --- FakeInputDispatcherPolicy ---
66
67class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
68 InputDispatcherConfiguration mConfig;
69
70protected:
71 virtual ~FakeInputDispatcherPolicy() {
72 }
73
74public:
75 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080076 }
77
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080078 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080079 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
80 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080081 }
82
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080083 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080084 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
85 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080086 }
87
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070088 void assertFilterInputEventWasNotCalled() {
89 std::scoped_lock lock(mLock);
90 ASSERT_EQ(nullptr, mFilteredEvent);
91 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080092
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080093 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070094 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080095 ASSERT_TRUE(mConfigurationChangedTime)
96 << "Timed out waiting for configuration changed call";
97 ASSERT_EQ(*mConfigurationChangedTime, when);
98 mConfigurationChangedTime = std::nullopt;
99 }
100
101 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700102 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800103 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800104 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800105 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
106 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
107 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
108 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
109 mLastNotifySwitch = std::nullopt;
110 }
111
chaviwfd6d3512019-03-25 13:23:49 -0700112 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700113 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800114 ASSERT_EQ(touchedToken, mOnPointerDownToken);
115 mOnPointerDownToken.clear();
116 }
117
118 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700119 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800120 ASSERT_TRUE(mOnPointerDownToken == nullptr)
121 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700122 }
123
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700124 // This function must be called soon after the expected ANR timer starts,
125 // because we are also checking how much time has passed.
126 void assertNotifyAnrWasCalled(std::chrono::nanoseconds timeout,
127 const sp<InputApplicationHandle>& expectedApplication,
128 const sp<IBinder>& expectedToken) {
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700129 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData;
130 ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
131 ASSERT_EQ(expectedApplication, anrData.first);
132 ASSERT_EQ(expectedToken, anrData.second);
133 }
134
135 std::pair<sp<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
136 std::chrono::nanoseconds timeout) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700137 const std::chrono::time_point start = std::chrono::steady_clock::now();
138 std::unique_lock lock(mLock);
139 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
140 android::base::ScopedLockAssertion assumeLocked(mLock);
141
142 // If there is an ANR, Dispatcher won't be idle because there are still events
143 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
144 // before checking if ANR was called.
145 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
146 // it some time to act. 100ms seems reasonable.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700147 mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
148 return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
149 });
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700150 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700151 if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
152 ADD_FAILURE() << "Did not receive ANR callback";
Siarhei Vishniakou4e219792020-09-22 21:43:09 -0500153 return {};
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700154 }
Siarhei Vishniakouffaa2b12020-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 Vishniakoue4623042020-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 Vishniakouffaa2b12020-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 Vishniakoue4623042020-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 Vishniakouffaa2b12020-05-26 21:43:02 -0700191 // ANR handling
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700192 std::queue<sp<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
193 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
Siarhei Vishniakouffaa2b12020-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 Vishniakouffaa2b12020-05-26 21:43:02 -0700202 virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& application,
203 const sp<IBinder>& windowToken, const std::string&) override {
204 std::scoped_lock lock(mLock);
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700205 mAnrApplications.push(application);
206 mAnrWindowTokens.push(windowToken);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700207 mNotifyAnr.notify_all();
208 return mAnrTimeout.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209 }
210
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700211 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800212
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700213 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700214
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700215 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800216 *outConfig = mConfig;
217 }
218
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800219 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700220 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800221 switch (inputEvent->getType()) {
222 case AINPUT_EVENT_TYPE_KEY: {
223 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800224 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800225 break;
226 }
227
228 case AINPUT_EVENT_TYPE_MOTION: {
229 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800230 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800231 break;
232 }
233 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800234 return true;
235 }
236
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700237 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800238
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700239 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700241 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
242 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800243 return 0;
244 }
245
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700246 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
247 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800248 return false;
249 }
250
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800251 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
252 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700253 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800254 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
255 * essentially a passthrough for notifySwitch.
256 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800257 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800258 }
259
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700260 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800261
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700262 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800263 return false;
264 }
Jackal Guof9696682018-10-05 12:23:23 +0800265
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700266 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700267 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700268 mOnPointerDownToken = newToken;
269 }
270
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800271 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
272 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700273 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800274 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
275 ASSERT_EQ(mFilteredEvent->getType(), type);
276
277 if (type == AINPUT_EVENT_TYPE_KEY) {
278 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
279 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
280 EXPECT_EQ(keyEvent.getAction(), action);
281 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
282 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
283 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
284 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
285 EXPECT_EQ(motionEvent.getAction(), action);
286 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
287 } else {
288 FAIL() << "Unknown type: " << type;
289 }
290
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800291 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800292 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800293};
294
Gang Wang342c9272020-01-13 13:15:04 -0500295// --- HmacKeyManagerTest ---
296
297class HmacKeyManagerTest : public testing::Test {
298protected:
299 HmacKeyManager mHmacKeyManager;
300};
301
302/**
303 * Ensure that separate calls to sign the same data are generating the same key.
304 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
305 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
306 * tests.
307 */
308TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
309 KeyEvent event = getTestKeyEvent();
310 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
311
312 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
313 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
314 ASSERT_EQ(hmac1, hmac2);
315}
316
317/**
318 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
319 */
320TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
321 KeyEvent event = getTestKeyEvent();
322 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
323 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
324
325 verifiedEvent.deviceId += 1;
326 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
327
328 verifiedEvent.source += 1;
329 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
330
331 verifiedEvent.eventTimeNanos += 1;
332 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
333
334 verifiedEvent.displayId += 1;
335 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
336
337 verifiedEvent.action += 1;
338 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
339
340 verifiedEvent.downTimeNanos += 1;
341 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
342
343 verifiedEvent.flags += 1;
344 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
345
346 verifiedEvent.keyCode += 1;
347 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
348
349 verifiedEvent.scanCode += 1;
350 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
351
352 verifiedEvent.metaState += 1;
353 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
354
355 verifiedEvent.repeatCount += 1;
356 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
357}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800358
359// --- InputDispatcherTest ---
360
361class InputDispatcherTest : public testing::Test {
362protected:
363 sp<FakeInputDispatcherPolicy> mFakePolicy;
364 sp<InputDispatcher> mDispatcher;
365
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700366 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800367 mFakePolicy = new FakeInputDispatcherPolicy();
368 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800369 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
370 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700371 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800372 }
373
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700374 virtual void TearDown() override {
375 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800376 mFakePolicy.clear();
377 mDispatcher.clear();
378 }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700379
380 /**
381 * Used for debugging when writing the test
382 */
383 void dumpDispatcherState() {
384 std::string dump;
385 mDispatcher->dump(dump);
386 std::stringstream ss(dump);
387 std::string to;
388
389 while (std::getline(ss, to, '\n')) {
390 ALOGE("%s", to.c_str());
391 }
392 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800393};
394
395
396TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
397 KeyEvent event;
398
399 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800400 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
401 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600402 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
403 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700404 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
405 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
406 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800407 << "Should reject key events with undefined action.";
408
409 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800410 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
411 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600412 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700413 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
414 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
415 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800416 << "Should reject key events with ACTION_MULTIPLE.";
417}
418
419TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
420 MotionEvent event;
421 PointerProperties pointerProperties[MAX_POINTERS + 1];
422 PointerCoords pointerCoords[MAX_POINTERS + 1];
423 for (int i = 0; i <= MAX_POINTERS; i++) {
424 pointerProperties[i].clear();
425 pointerProperties[i].id = i;
426 pointerCoords[i].clear();
427 }
428
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800429 // Some constants commonly used below
430 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
431 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
432 constexpr int32_t metaState = AMETA_NONE;
433 constexpr MotionClassification classification = MotionClassification::NONE;
434
Michael Wrightd02c5b62014-02-10 15:10:22 -0800435 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800436 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600437 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
438 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
439 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700440 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700441 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
442 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
443 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800444 << "Should reject motion events with undefined action.";
445
446 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800447 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700448 AMOTION_EVENT_ACTION_POINTER_DOWN |
449 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600450 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
451 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
452 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700453 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700454 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
455 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
456 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800457 << "Should reject motion events with pointer down index too large.";
458
Garfield Tanfbe732e2020-01-24 11:26:14 -0800459 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700460 AMOTION_EVENT_ACTION_POINTER_DOWN |
461 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600462 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
463 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
464 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700465 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700466 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
467 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
468 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800469 << "Should reject motion events with pointer down index too small.";
470
471 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800472 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700473 AMOTION_EVENT_ACTION_POINTER_UP |
474 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600475 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
476 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
477 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700478 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700479 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
480 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
481 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800482 << "Should reject motion events with pointer up index too large.";
483
Garfield Tanfbe732e2020-01-24 11:26:14 -0800484 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700485 AMOTION_EVENT_ACTION_POINTER_UP |
486 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600487 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
488 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
489 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700490 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700491 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
492 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
493 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800494 << "Should reject motion events with pointer up index too small.";
495
496 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800497 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
498 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
499 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
500 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
501 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700502 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700503 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
504 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
505 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800506 << "Should reject motion events with 0 pointers.";
507
Garfield Tanfbe732e2020-01-24 11:26:14 -0800508 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
509 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
510 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
511 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
512 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,
523 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
524 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
525 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700526 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700527 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
528 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
529 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800530 << "Should reject motion events with pointer ids less than 0.";
531
532 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800533 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
534 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
535 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
536 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
537 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700538 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700539 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
540 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
541 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
543
544 // Rejects motion events with duplicate pointer ids.
545 pointerProperties[0].id = 1;
546 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800547 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
548 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
549 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
550 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
551 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700552 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700553 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
554 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
555 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800556 << "Should reject motion events with duplicate pointer ids.";
557}
558
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800559/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
560
561TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
562 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800563 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800564 mDispatcher->notifyConfigurationChanged(&args);
565 ASSERT_TRUE(mDispatcher->waitForIdle());
566
567 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
568}
569
570TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800571 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
572 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800573 mDispatcher->notifySwitch(&args);
574
575 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
576 args.policyFlags |= POLICY_FLAG_TRUSTED;
577 mFakePolicy->assertNotifySwitchWasCalled(args);
578}
579
Arthur Hungb92218b2018-08-14 12:00:21 +0800580// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700581static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700582static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800583
584class FakeApplicationHandle : public InputApplicationHandle {
585public:
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700586 FakeApplicationHandle() {
587 mInfo.name = "Fake Application";
588 mInfo.token = new BBinder();
589 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
590 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800591 virtual ~FakeApplicationHandle() {}
592
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700593 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800594 return true;
595 }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700596
597 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
598 mInfo.dispatchingTimeout = timeout.count();
599 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800600};
601
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800602class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800603public:
chaviwd1c23182019-12-20 18:44:56 -0800604 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
605 : mName(name) {
606 mConsumer = std::make_unique<InputConsumer>(clientChannel);
607 }
608
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800609 InputEvent* consume() {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700610 InputEvent* event;
611 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
612 if (!consumeSeq) {
613 return nullptr;
614 }
615 finishEvent(*consumeSeq);
616 return event;
617 }
618
619 /**
620 * Receive an event without acknowledging it.
621 * Return the sequence number that could later be used to send finished signal.
622 */
623 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800624 uint32_t consumeSeq;
625 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800626
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800627 std::chrono::time_point start = std::chrono::steady_clock::now();
628 status_t status = WOULD_BLOCK;
629 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800630 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800631 &event);
632 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
633 if (elapsed > 100ms) {
634 break;
635 }
636 }
637
638 if (status == WOULD_BLOCK) {
639 // Just means there's no event available.
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700640 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800641 }
642
643 if (status != OK) {
644 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700645 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800646 }
647 if (event == nullptr) {
648 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700649 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800650 }
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700651 if (outEvent != nullptr) {
652 *outEvent = event;
653 }
654 return consumeSeq;
655 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800656
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700657 /**
658 * To be used together with "receiveEvent" to complete the consumption of an event.
659 */
660 void finishEvent(uint32_t consumeSeq) {
661 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
662 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800663 }
664
665 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
666 int32_t expectedFlags) {
667 InputEvent* event = consume();
668
669 ASSERT_NE(nullptr, event) << mName.c_str()
670 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800671 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700672 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800673 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800674
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800675 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800676
Tiger Huang8664f8c2018-10-11 19:14:35 +0800677 switch (expectedEventType) {
678 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800679 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
680 EXPECT_EQ(expectedAction, keyEvent.getAction());
681 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800682 break;
683 }
684 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800685 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
686 EXPECT_EQ(expectedAction, motionEvent.getAction());
687 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800688 break;
689 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100690 case AINPUT_EVENT_TYPE_FOCUS: {
691 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
692 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800693 default: {
694 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
695 }
696 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800697 }
698
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100699 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
700 InputEvent* event = consume();
701 ASSERT_NE(nullptr, event) << mName.c_str()
702 << ": consumer should have returned non-NULL event.";
703 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
704 << "Got " << inputEventTypeToString(event->getType())
705 << " event instead of FOCUS event";
706
707 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
708 << mName.c_str() << ": event displayId should always be NONE.";
709
710 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
711 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
712 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
713 }
714
chaviwd1c23182019-12-20 18:44:56 -0800715 void assertNoEvents() {
716 InputEvent* event = consume();
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700717 if (event == nullptr) {
718 return;
719 }
720 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
721 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
722 ADD_FAILURE() << "Received key event "
723 << KeyEvent::actionToString(keyEvent.getAction());
724 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
725 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
726 ADD_FAILURE() << "Received motion event "
727 << MotionEvent::actionToString(motionEvent.getAction());
728 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
729 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
730 ADD_FAILURE() << "Received focus event, hasFocus = "
731 << (focusEvent.getHasFocus() ? "true" : "false");
732 }
733 FAIL() << mName.c_str()
734 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800735 }
736
737 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
738
739protected:
740 std::unique_ptr<InputConsumer> mConsumer;
741 PreallocatedInputEventFactory mEventFactory;
742
743 std::string mName;
744};
745
746class FakeWindowHandle : public InputWindowHandle {
747public:
748 static const int32_t WIDTH = 600;
749 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800750
751 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
752 const sp<InputDispatcher>& dispatcher, const std::string name,
753 int32_t displayId, sp<IBinder> token = nullptr)
754 : mName(name) {
755 if (token == nullptr) {
756 sp<InputChannel> serverChannel, clientChannel;
757 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
758 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
759 dispatcher->registerInputChannel(serverChannel);
760 token = serverChannel->getConnectionToken();
761 }
762
763 inputApplicationHandle->updateInfo();
764 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
765
766 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700767 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800768 mInfo.name = name;
769 mInfo.layoutParamsFlags = 0;
770 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700771 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
chaviwd1c23182019-12-20 18:44:56 -0800772 mInfo.frameLeft = 0;
773 mInfo.frameTop = 0;
774 mInfo.frameRight = WIDTH;
775 mInfo.frameBottom = HEIGHT;
776 mInfo.globalScaleFactor = 1.0;
777 mInfo.touchableRegion.clear();
778 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
779 mInfo.visible = true;
780 mInfo.canReceiveKeys = true;
781 mInfo.hasFocus = false;
782 mInfo.hasWallpaper = false;
783 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800784 mInfo.ownerPid = INJECTOR_PID;
785 mInfo.ownerUid = INJECTOR_UID;
786 mInfo.inputFeatures = 0;
787 mInfo.displayId = displayId;
788 }
789
790 virtual bool updateInfo() { return true; }
791
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100792 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800793
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700794 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
795 mInfo.dispatchingTimeout = timeout.count();
796 }
797
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700798 void setPaused(bool paused) { mInfo.paused = paused; }
799
chaviwd1c23182019-12-20 18:44:56 -0800800 void setFrame(const Rect& frame) {
801 mInfo.frameLeft = frame.left;
802 mInfo.frameTop = frame.top;
803 mInfo.frameRight = frame.right;
804 mInfo.frameBottom = frame.bottom;
805 mInfo.touchableRegion.clear();
806 mInfo.addTouchableRegion(frame);
807 }
808
809 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
810
chaviwaf87b3e2019-10-01 16:59:28 -0700811 void setWindowScale(float xScale, float yScale) {
812 mInfo.windowXScale = xScale;
813 mInfo.windowYScale = yScale;
814 }
815
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800816 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
817 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
818 expectedFlags);
819 }
820
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700821 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
822 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
823 }
824
Svet Ganov5d3bc372020-01-26 23:11:07 -0800825 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
826 int32_t expectedFlags = 0) {
827 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
828 expectedFlags);
829 }
830
831 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
832 int32_t expectedFlags = 0) {
833 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
834 expectedFlags);
835 }
836
837 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
838 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800839 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
840 expectedFlags);
841 }
842
Svet Ganov5d3bc372020-01-26 23:11:07 -0800843 void consumeMotionPointerDown(int32_t pointerIdx,
844 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
845 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
846 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
847 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
848 }
849
850 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
851 int32_t expectedFlags = 0) {
852 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
853 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
854 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
855 }
856
857 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
858 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000859 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
860 expectedFlags);
861 }
862
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100863 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
864 ASSERT_NE(mInputReceiver, nullptr)
865 << "Cannot consume events from a window with no receiver";
866 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
867 }
868
chaviwd1c23182019-12-20 18:44:56 -0800869 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
870 int32_t expectedFlags) {
871 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
872 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
873 expectedFlags);
874 }
875
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700876 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700877 if (mInputReceiver == nullptr) {
878 ADD_FAILURE() << "Invalid receive event on window with no receiver";
879 return std::nullopt;
880 }
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700881 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700882 }
883
884 void finishEvent(uint32_t sequenceNum) {
885 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
886 mInputReceiver->finishEvent(sequenceNum);
887 }
888
chaviwaf87b3e2019-10-01 16:59:28 -0700889 InputEvent* consume() {
890 if (mInputReceiver == nullptr) {
891 return nullptr;
892 }
893 return mInputReceiver->consume();
894 }
895
Arthur Hungb92218b2018-08-14 12:00:21 +0800896 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800897 ASSERT_NE(mInputReceiver, nullptr)
898 << "Call 'assertNoEvents' on a window with an InputReceiver";
899 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800900 }
901
chaviwaf87b3e2019-10-01 16:59:28 -0700902 sp<IBinder> getToken() { return mInfo.token; }
903
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100904 const std::string& getName() { return mName; }
905
chaviwd1c23182019-12-20 18:44:56 -0800906private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100907 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800908 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700909 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800910};
911
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700912std::atomic<int32_t> FakeWindowHandle::sId{1};
913
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700914static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700915 int32_t displayId = ADISPLAY_ID_NONE,
916 int32_t syncMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
917 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800918 KeyEvent event;
919 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
920
921 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800922 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700923 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
924 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800925
926 // Inject event until dispatch out.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700927 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
928 injectionTimeout,
929 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800930}
931
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700932static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
933 int32_t displayId = ADISPLAY_ID_NONE) {
934 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
935}
936
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700937static int32_t injectKeyUp(const sp<InputDispatcher>& dispatcher,
938 int32_t displayId = ADISPLAY_ID_NONE) {
939 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
940}
941
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700942static int32_t injectMotionEvent(
943 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
944 const PointF& position,
945 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700946 AMOTION_EVENT_INVALID_CURSOR_POSITION},
947 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
948 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
949 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800950 MotionEvent event;
951 PointerProperties pointerProperties[1];
952 PointerCoords pointerCoords[1];
953
954 pointerProperties[0].clear();
955 pointerProperties[0].id = 0;
956 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
957
958 pointerCoords[0].clear();
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700959 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
960 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800961
Arthur Hungb92218b2018-08-14 12:00:21 +0800962 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800963 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
964 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600965 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700966 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600967 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700968 /* xPrecision */ 0, /* yPrecision */ 0, cursorPosition.x, cursorPosition.y,
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700969 eventTime, eventTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700970 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800971
972 // Inject event until dispatch out.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -0700973 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
974 injectionTimeout,
975 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800976}
977
Garfield Tan00f511d2019-06-12 16:55:40 -0700978static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700979 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700980 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700981}
982
Michael Wright3a240c42019-12-10 20:53:41 +0000983static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700984 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -0700985 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000986}
987
Jackal Guof9696682018-10-05 12:23:23 +0800988static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
989 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
990 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800991 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
992 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
993 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800994
995 return args;
996}
997
chaviwd1c23182019-12-20 18:44:56 -0800998static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
999 const std::vector<PointF>& points) {
1000 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001001 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1002 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1003 }
1004
chaviwd1c23182019-12-20 18:44:56 -08001005 PointerProperties pointerProperties[pointerCount];
1006 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001007
chaviwd1c23182019-12-20 18:44:56 -08001008 for (size_t i = 0; i < pointerCount; i++) {
1009 pointerProperties[i].clear();
1010 pointerProperties[i].id = i;
1011 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001012
chaviwd1c23182019-12-20 18:44:56 -08001013 pointerCoords[i].clear();
1014 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1015 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1016 }
Jackal Guof9696682018-10-05 12:23:23 +08001017
1018 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1019 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001020 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001021 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1022 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001023 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1024 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001025 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1026 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001027
1028 return args;
1029}
1030
chaviwd1c23182019-12-20 18:44:56 -08001031static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1032 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1033}
1034
Arthur Hungb92218b2018-08-14 12:00:21 +08001035TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
1036 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001037 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1038 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001039
Arthur Hung72d8dc32020-03-28 00:48:39 +00001040 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001041 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1042 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001043 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1044
1045 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001046 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001047}
1048
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001049/**
1050 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1051 * To ensure that window receives only events that were directly inside of it, add
1052 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1053 * when finding touched windows.
1054 * This test serves as a sanity check for the next test, where setInputWindows is
1055 * called twice.
1056 */
1057TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
1058 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1059 sp<FakeWindowHandle> window =
1060 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1061 window->setFrame(Rect(0, 0, 100, 100));
1062 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1063
1064 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1065 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1066 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1067 {50, 50}))
1068 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1069
1070 // Window should receive motion event.
1071 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1072}
1073
1074/**
1075 * Calling setInputWindows twice, with the same info, should not cause any issues.
1076 * To ensure that window receives only events that were directly inside of it, add
1077 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1078 * when finding touched windows.
1079 */
1080TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
1081 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1082 sp<FakeWindowHandle> window =
1083 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1084 window->setFrame(Rect(0, 0, 100, 100));
1085 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1086
1087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1089 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1090 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1091 {50, 50}))
1092 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1093
1094 // Window should receive motion event.
1095 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1096}
1097
Arthur Hungb92218b2018-08-14 12:00:21 +08001098// The foreground window should receive the first touch down event.
1099TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
1100 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001101 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1102 ADISPLAY_ID_DEFAULT);
1103 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1104 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001105
Arthur Hung72d8dc32020-03-28 00:48:39 +00001106 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001107 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1108 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001109 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1110
1111 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001112 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001113 windowSecond->assertNoEvents();
1114}
1115
1116TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
1117 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001118 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1119 ADISPLAY_ID_DEFAULT);
1120 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1121 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001122
Arthur Hung7ab76b12019-01-09 19:17:20 +08001123 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001124 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001125
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001126 // Display should have only one focused window
1127 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001128 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001129
1130 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001131 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1132 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1133
1134 // Focused window should receive event.
1135 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001136 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001137}
1138
Arthur Hung7ab76b12019-01-09 19:17:20 +08001139TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
1140 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1141 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1142 ADISPLAY_ID_DEFAULT);
1143 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1144 ADISPLAY_ID_DEFAULT);
1145
1146 // Set focused application.
1147 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1148
1149 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001150 windowTop->setFocus(true);
1151 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001152
Arthur Hung72d8dc32020-03-28 00:48:39 +00001153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001154 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001155 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1156 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1157
1158 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001159 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001160 windowSecond->assertNoEvents();
1161}
1162
Arthur Hung3b413f22018-10-26 18:05:34 +08001163TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1164 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1165
1166 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1167 ADISPLAY_ID_DEFAULT);
1168 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1169 ADISPLAY_ID_DEFAULT);
1170
Arthur Hung832bc4a2019-01-28 11:43:17 +08001171 // Set focused application.
1172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001173
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001174 windowTop->setFocus(true);
1175 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001176 // Release channel for window is no longer valid.
1177 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001178 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001179 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001180
Arthur Hung832bc4a2019-01-28 11:43:17 +08001181 // Test inject a key down, should dispatch to a valid window.
1182 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1183 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001184
1185 // Top window is invalid, so it should not receive any input event.
1186 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001187 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001188}
1189
Garfield Tan00f511d2019-06-12 16:55:40 -07001190TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1191 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1192
1193 sp<FakeWindowHandle> windowLeft =
1194 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1195 windowLeft->setFrame(Rect(0, 0, 600, 800));
1196 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1197 sp<FakeWindowHandle> windowRight =
1198 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1199 windowRight->setFrame(Rect(600, 0, 1200, 800));
1200 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1201
1202 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1203
Arthur Hung72d8dc32020-03-28 00:48:39 +00001204 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001205
1206 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1207 // left window. This event should be dispatched to the left window.
1208 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1209 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07001210 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001211 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001212 windowRight->assertNoEvents();
1213}
1214
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001215TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1216 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1217 sp<FakeWindowHandle> window =
1218 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001219 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001220
Arthur Hung72d8dc32020-03-28 00:48:39 +00001221 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001222 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001223
1224 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1225 mDispatcher->notifyKey(&keyArgs);
1226
1227 // Window should receive key down event.
1228 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1229
1230 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1231 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001232 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001233 mDispatcher->notifyDeviceReset(&args);
1234 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1235 AKEY_EVENT_FLAG_CANCELED);
1236}
1237
1238TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1239 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1240 sp<FakeWindowHandle> window =
1241 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1242
Arthur Hung72d8dc32020-03-28 00:48:39 +00001243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001244
1245 NotifyMotionArgs motionArgs =
1246 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1247 ADISPLAY_ID_DEFAULT);
1248 mDispatcher->notifyMotion(&motionArgs);
1249
1250 // Window should receive motion down event.
1251 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1252
1253 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1254 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001255 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001256 mDispatcher->notifyDeviceReset(&args);
1257 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1258 0 /*expectedFlags*/);
1259}
1260
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1262 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1263
1264 // Create a couple of windows
1265 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1266 "First Window", ADISPLAY_ID_DEFAULT);
1267 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1268 "Second Window", ADISPLAY_ID_DEFAULT);
1269
1270 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001271 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001272
1273 // Send down to the first window
1274 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1275 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1276 mDispatcher->notifyMotion(&downMotionArgs);
1277 // Only the first window should get the down event
1278 firstWindow->consumeMotionDown();
1279 secondWindow->assertNoEvents();
1280
1281 // Transfer touch focus to the second window
1282 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1283 // The first window gets cancel and the second gets down
1284 firstWindow->consumeMotionCancel();
1285 secondWindow->consumeMotionDown();
1286
1287 // Send up event to the second window
1288 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1289 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1290 mDispatcher->notifyMotion(&upMotionArgs);
1291 // The first window gets no events and the second gets up
1292 firstWindow->assertNoEvents();
1293 secondWindow->consumeMotionUp();
1294}
1295
1296TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1297 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1298
1299 PointF touchPoint = {10, 10};
1300
1301 // Create a couple of windows
1302 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1303 "First Window", ADISPLAY_ID_DEFAULT);
1304 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1305 "Second Window", ADISPLAY_ID_DEFAULT);
1306
1307 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309
1310 // Send down to the first window
1311 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1312 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1313 mDispatcher->notifyMotion(&downMotionArgs);
1314 // Only the first window should get the down event
1315 firstWindow->consumeMotionDown();
1316 secondWindow->assertNoEvents();
1317
1318 // Send pointer down to the first window
1319 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1320 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1321 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1322 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1323 // Only the first window should get the pointer down event
1324 firstWindow->consumeMotionPointerDown(1);
1325 secondWindow->assertNoEvents();
1326
1327 // Transfer touch focus to the second window
1328 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1329 // The first window gets cancel and the second gets down and pointer down
1330 firstWindow->consumeMotionCancel();
1331 secondWindow->consumeMotionDown();
1332 secondWindow->consumeMotionPointerDown(1);
1333
1334 // Send pointer up to the second window
1335 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1336 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1337 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1338 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1339 // The first window gets nothing and the second gets pointer up
1340 firstWindow->assertNoEvents();
1341 secondWindow->consumeMotionPointerUp(1);
1342
1343 // Send up event to the second window
1344 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1345 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1346 mDispatcher->notifyMotion(&upMotionArgs);
1347 // The first window gets nothing and the second gets up
1348 firstWindow->assertNoEvents();
1349 secondWindow->consumeMotionUp();
1350}
1351
1352TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1353 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1354
1355 // Create a non touch modal window that supports split touch
1356 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1357 "First Window", ADISPLAY_ID_DEFAULT);
1358 firstWindow->setFrame(Rect(0, 0, 600, 400));
1359 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1360 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1361
1362 // Create a non touch modal window that supports split touch
1363 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1364 "Second Window", ADISPLAY_ID_DEFAULT);
1365 secondWindow->setFrame(Rect(0, 400, 600, 800));
1366 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1367 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1368
1369 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001370 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001371
1372 PointF pointInFirst = {300, 200};
1373 PointF pointInSecond = {300, 600};
1374
1375 // Send down to the first window
1376 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1377 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1378 mDispatcher->notifyMotion(&firstDownMotionArgs);
1379 // Only the first window should get the down event
1380 firstWindow->consumeMotionDown();
1381 secondWindow->assertNoEvents();
1382
1383 // Send down to the second window
1384 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1385 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1386 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1387 mDispatcher->notifyMotion(&secondDownMotionArgs);
1388 // The first window gets a move and the second a down
1389 firstWindow->consumeMotionMove();
1390 secondWindow->consumeMotionDown();
1391
1392 // Transfer touch focus to the second window
1393 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1394 // The first window gets cancel and the new gets pointer down (it already saw down)
1395 firstWindow->consumeMotionCancel();
1396 secondWindow->consumeMotionPointerDown(1);
1397
1398 // Send pointer up to the second window
1399 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1400 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1401 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1402 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1403 // The first window gets nothing and the second gets pointer up
1404 firstWindow->assertNoEvents();
1405 secondWindow->consumeMotionPointerUp(1);
1406
1407 // Send up event to the second window
1408 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1409 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1410 mDispatcher->notifyMotion(&upMotionArgs);
1411 // The first window gets nothing and the second gets up
1412 firstWindow->assertNoEvents();
1413 secondWindow->consumeMotionUp();
1414}
1415
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001416TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1417 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1418 sp<FakeWindowHandle> window =
1419 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1420
1421 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001423
1424 window->consumeFocusEvent(true);
1425
1426 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1427 mDispatcher->notifyKey(&keyArgs);
1428
1429 // Window should receive key down event.
1430 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1431}
1432
1433TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1434 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1435 sp<FakeWindowHandle> window =
1436 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1437
Arthur Hung72d8dc32020-03-28 00:48:39 +00001438 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001439
1440 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1441 mDispatcher->notifyKey(&keyArgs);
1442 mDispatcher->waitForIdle();
1443
1444 window->assertNoEvents();
1445}
1446
1447// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1448TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1449 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1450 sp<FakeWindowHandle> window =
1451 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1452
Arthur Hung72d8dc32020-03-28 00:48:39 +00001453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001454
1455 // Send key
1456 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1457 mDispatcher->notifyKey(&keyArgs);
1458 // Send motion
1459 NotifyMotionArgs motionArgs =
1460 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1461 ADISPLAY_ID_DEFAULT);
1462 mDispatcher->notifyMotion(&motionArgs);
1463
1464 // Window should receive only the motion event
1465 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1466 window->assertNoEvents(); // Key event or focus event will not be received
1467}
1468
chaviwd1c23182019-12-20 18:44:56 -08001469class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001470public:
1471 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001472 int32_t displayId, bool isGestureMonitor = false) {
1473 sp<InputChannel> serverChannel, clientChannel;
1474 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1475 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1476 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001477 }
1478
chaviwd1c23182019-12-20 18:44:56 -08001479 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1480
1481 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1482 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1483 expectedDisplayId, expectedFlags);
1484 }
1485
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07001486 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1487
1488 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1489
chaviwd1c23182019-12-20 18:44:56 -08001490 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1491 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1492 expectedDisplayId, expectedFlags);
1493 }
1494
1495 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1496 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1497 expectedDisplayId, expectedFlags);
1498 }
1499
1500 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1501
1502private:
1503 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001504};
1505
1506// Tests for gesture monitors
1507TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1508 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1509 sp<FakeWindowHandle> window =
1510 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001512
chaviwd1c23182019-12-20 18:44:56 -08001513 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1514 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001515
1516 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1517 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1518 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1519 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001520 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001521}
1522
1523TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1524 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1525 sp<FakeWindowHandle> window =
1526 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1527
1528 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001529 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001530
Arthur Hung72d8dc32020-03-28 00:48:39 +00001531 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001532 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001533
chaviwd1c23182019-12-20 18:44:56 -08001534 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1535 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001536
1537 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1538 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1539 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001540 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001541}
1542
1543TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1544 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1545 sp<FakeWindowHandle> window =
1546 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001547 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001548
chaviwd1c23182019-12-20 18:44:56 -08001549 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1550 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001551
1552 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1553 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1554 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1555 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001556 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001557
1558 window->releaseChannel();
1559
chaviwd1c23182019-12-20 18:44:56 -08001560 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001561
1562 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1563 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1564 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001565 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001566}
1567
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07001568TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1569 FakeMonitorReceiver monitor =
1570 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1571 true /*isGestureMonitor*/);
1572
1573 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1574 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1575 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1576 ASSERT_TRUE(consumeSeq);
1577
1578 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1579 monitor.finishEvent(*consumeSeq);
1580 ASSERT_TRUE(mDispatcher->waitForIdle());
1581}
1582
chaviw81e2bb92019-12-18 15:03:51 -08001583TEST_F(InputDispatcherTest, TestMoveEvent) {
1584 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1585 sp<FakeWindowHandle> window =
1586 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1587
Arthur Hung72d8dc32020-03-28 00:48:39 +00001588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001589
1590 NotifyMotionArgs motionArgs =
1591 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1592 ADISPLAY_ID_DEFAULT);
1593
1594 mDispatcher->notifyMotion(&motionArgs);
1595 // Window should receive motion down event.
1596 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1597
1598 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001599 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001600 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1601 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1602 motionArgs.pointerCoords[0].getX() - 10);
1603
1604 mDispatcher->notifyMotion(&motionArgs);
1605 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1606 0 /*expectedFlags*/);
1607}
1608
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001609/**
1610 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1611 * the device default right away. In the test scenario, we check both the default value,
1612 * and the action of enabling / disabling.
1613 */
1614TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1615 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1616 sp<FakeWindowHandle> window =
1617 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1618
1619 // Set focused application.
1620 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1621 window->setFocus(true);
1622
1623 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001625 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1626
1627 SCOPED_TRACE("Remove the window to trigger focus loss");
1628 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001629 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001630 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1631
1632 SCOPED_TRACE("Disable touch mode");
1633 mDispatcher->setInTouchMode(false);
1634 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001635 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001636 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1637
1638 SCOPED_TRACE("Remove the window to trigger focus loss");
1639 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001641 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1642
1643 SCOPED_TRACE("Enable touch mode again");
1644 mDispatcher->setInTouchMode(true);
1645 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001646 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001647 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1648
1649 window->assertNoEvents();
1650}
1651
Gang Wange9087892020-01-07 12:17:14 -05001652TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1653 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1654 sp<FakeWindowHandle> window =
1655 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1656
1657 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1658 window->setFocus(true);
1659
Arthur Hung72d8dc32020-03-28 00:48:39 +00001660 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001661 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1662
1663 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1664 mDispatcher->notifyKey(&keyArgs);
1665
1666 InputEvent* event = window->consume();
1667 ASSERT_NE(event, nullptr);
1668
1669 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1670 ASSERT_NE(verified, nullptr);
1671 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1672
1673 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1674 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1675 ASSERT_EQ(keyArgs.source, verified->source);
1676 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1677
1678 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1679
1680 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1681 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001682 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1683 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1684 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1685 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1686 ASSERT_EQ(0, verifiedKey.repeatCount);
1687}
1688
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001689TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1690 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1691 sp<FakeWindowHandle> window =
1692 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1693
1694 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1695
Arthur Hung72d8dc32020-03-28 00:48:39 +00001696 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001697
1698 NotifyMotionArgs motionArgs =
1699 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1700 ADISPLAY_ID_DEFAULT);
1701 mDispatcher->notifyMotion(&motionArgs);
1702
1703 InputEvent* event = window->consume();
1704 ASSERT_NE(event, nullptr);
1705
1706 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1707 ASSERT_NE(verified, nullptr);
1708 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1709
1710 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1711 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1712 EXPECT_EQ(motionArgs.source, verified->source);
1713 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1714
1715 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1716
1717 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1718 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1719 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1720 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1721 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1722 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1723 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1724}
1725
Garfield Tan1c7bc862020-01-28 13:24:04 -08001726class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
1727protected:
1728 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
1729 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
1730
1731 sp<FakeApplicationHandle> mApp;
1732 sp<FakeWindowHandle> mWindow;
1733
1734 virtual void SetUp() override {
1735 mFakePolicy = new FakeInputDispatcherPolicy();
1736 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
1737 mDispatcher = new InputDispatcher(mFakePolicy);
1738 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
1739 ASSERT_EQ(OK, mDispatcher->start());
1740
1741 setUpWindow();
1742 }
1743
1744 void setUpWindow() {
1745 mApp = new FakeApplicationHandle();
1746 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1747
1748 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08001750
1751 mWindow->consumeFocusEvent(true);
1752 }
1753
1754 void sendAndConsumeKeyDown() {
1755 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1756 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
1757 mDispatcher->notifyKey(&keyArgs);
1758
1759 // Window should receive key down event.
1760 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1761 }
1762
1763 void expectKeyRepeatOnce(int32_t repeatCount) {
1764 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
1765 InputEvent* repeatEvent = mWindow->consume();
1766 ASSERT_NE(nullptr, repeatEvent);
1767
1768 uint32_t eventType = repeatEvent->getType();
1769 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
1770
1771 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
1772 uint32_t eventAction = repeatKeyEvent->getAction();
1773 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
1774 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
1775 }
1776
1777 void sendAndConsumeKeyUp() {
1778 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
1779 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
1780 mDispatcher->notifyKey(&keyArgs);
1781
1782 // Window should receive key down event.
1783 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1784 0 /*expectedFlags*/);
1785 }
1786};
1787
1788TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
1789 sendAndConsumeKeyDown();
1790 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1791 expectKeyRepeatOnce(repeatCount);
1792 }
1793}
1794
1795TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
1796 sendAndConsumeKeyDown();
1797 expectKeyRepeatOnce(1 /*repeatCount*/);
1798 sendAndConsumeKeyUp();
1799 mWindow->assertNoEvents();
1800}
1801
liushenxiangfea99012021-05-21 20:24:09 +08001802TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
1803 sendAndConsumeKeyDown();
1804 expectKeyRepeatOnce(1 /*repeatCount*/);
1805 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
1806 mDispatcher->notifyDeviceReset(&args);
1807 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
1808 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
1809 mWindow->assertNoEvents();
1810}
1811
Garfield Tan1c7bc862020-01-28 13:24:04 -08001812TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
1813 sendAndConsumeKeyDown();
1814 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1815 InputEvent* repeatEvent = mWindow->consume();
1816 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1817 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
1818 IdGenerator::getSource(repeatEvent->getId()));
1819 }
1820}
1821
1822TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
1823 sendAndConsumeKeyDown();
1824
1825 std::unordered_set<int32_t> idSet;
1826 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1827 InputEvent* repeatEvent = mWindow->consume();
1828 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1829 int32_t id = repeatEvent->getId();
1830 EXPECT_EQ(idSet.end(), idSet.find(id));
1831 idSet.insert(id);
1832 }
1833}
1834
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001835/* Test InputDispatcher for MultiDisplay */
1836class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1837public:
1838 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001839 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001840 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001841
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001842 application1 = new FakeApplicationHandle();
1843 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1844 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001845
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001846 // Set focus window for primary display, but focused display would be second one.
1847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001848 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001849 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001850 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001851
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001852 application2 = new FakeApplicationHandle();
1853 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1854 SECOND_DISPLAY_ID);
1855 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001856 // Set focus display to second one.
1857 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1858 // Set focus window for second display.
1859 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001860 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001861 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001862 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001863 }
1864
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001865 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001866 InputDispatcherTest::TearDown();
1867
1868 application1.clear();
1869 windowInPrimary.clear();
1870 application2.clear();
1871 windowInSecondary.clear();
1872 }
1873
1874protected:
1875 sp<FakeApplicationHandle> application1;
1876 sp<FakeWindowHandle> windowInPrimary;
1877 sp<FakeApplicationHandle> application2;
1878 sp<FakeWindowHandle> windowInSecondary;
1879};
1880
1881TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1882 // Test touch down on primary display.
1883 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1884 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001885 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001886 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001887 windowInSecondary->assertNoEvents();
1888
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001889 // Test touch down on second display.
1890 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1891 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001892 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1893 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001894 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001895}
1896
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001897TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001898 // Test inject a key down with display id specified.
1899 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1900 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001901 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001902 windowInSecondary->assertNoEvents();
1903
1904 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001905 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1906 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1907 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001908 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001909
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001910 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001911 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08001912
1913 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001914 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1915 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001916
1917 // Test inject a key down, should timeout because of no target window.
1918 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1919 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1920 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001921 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001922 windowInSecondary->assertNoEvents();
1923}
1924
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001925// Test per-display input monitors for motion event.
1926TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001927 FakeMonitorReceiver monitorInPrimary =
1928 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1929 FakeMonitorReceiver monitorInSecondary =
1930 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001931
1932 // Test touch down on primary display.
1933 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1934 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1935 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001936 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001937 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001938 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001939 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001940
1941 // Test touch down on second display.
1942 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1943 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1944 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1945 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001946 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001947 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001948 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001949
1950 // Test inject a non-pointer motion event.
1951 // If specific a display, it will dispatch to the focused window of particular display,
1952 // or it will dispatch to the focused window of focused display.
1953 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1954 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1955 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1956 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001957 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001958 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001959 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001960}
1961
1962// Test per-display input monitors for key event.
1963TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1964 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001965 FakeMonitorReceiver monitorInPrimary =
1966 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1967 FakeMonitorReceiver monitorInSecondary =
1968 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001969
1970 // Test inject a key down.
1971 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1972 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1973 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001974 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001975 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001976 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001977}
1978
Jackal Guof9696682018-10-05 12:23:23 +08001979class InputFilterTest : public InputDispatcherTest {
1980protected:
1981 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1982
1983 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1984 NotifyMotionArgs motionArgs;
1985
1986 motionArgs = generateMotionArgs(
1987 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1988 mDispatcher->notifyMotion(&motionArgs);
1989 motionArgs = generateMotionArgs(
1990 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1991 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001992 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001993 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001994 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001995 } else {
1996 mFakePolicy->assertFilterInputEventWasNotCalled();
1997 }
1998 }
1999
2000 void testNotifyKey(bool expectToBeFiltered) {
2001 NotifyKeyArgs keyArgs;
2002
2003 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2004 mDispatcher->notifyKey(&keyArgs);
2005 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2006 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002007 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002008
2009 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002010 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002011 } else {
2012 mFakePolicy->assertFilterInputEventWasNotCalled();
2013 }
2014 }
2015};
2016
2017// Test InputFilter for MotionEvent
2018TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2019 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2020 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2021 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2022
2023 // Enable InputFilter
2024 mDispatcher->setInputFilterEnabled(true);
2025 // Test touch on both primary and second display, and check if both events are filtered.
2026 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2027 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2028
2029 // Disable InputFilter
2030 mDispatcher->setInputFilterEnabled(false);
2031 // Test touch on both primary and second display, and check if both events aren't filtered.
2032 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2033 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2034}
2035
2036// Test InputFilter for KeyEvent
2037TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2038 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2039 testNotifyKey(/*expectToBeFiltered*/ false);
2040
2041 // Enable InputFilter
2042 mDispatcher->setInputFilterEnabled(true);
2043 // Send a key event, and check if it is filtered.
2044 testNotifyKey(/*expectToBeFiltered*/ true);
2045
2046 // Disable InputFilter
2047 mDispatcher->setInputFilterEnabled(false);
2048 // Send a key event, and check if it isn't filtered.
2049 testNotifyKey(/*expectToBeFiltered*/ false);
2050}
2051
chaviwfd6d3512019-03-25 13:23:49 -07002052class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002053 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002054 InputDispatcherTest::SetUp();
2055
2056 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2057 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2058 ADISPLAY_ID_DEFAULT);
2059 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2060 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2061 // window.
2062 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2063
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002064 mFocusedWindow =
2065 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2066 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
2067 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002068
2069 // Set focused application.
2070 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002071 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07002072
2073 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002075 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002076 }
2077
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002078 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002079 InputDispatcherTest::TearDown();
2080
2081 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002082 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002083 }
2084
2085protected:
2086 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002087 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002088 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002089};
2090
2091// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2092// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2093// the onPointerDownOutsideFocus callback.
2094TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002095 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2096 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2097 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002098 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002099 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002100
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002101 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002102 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2103}
2104
2105// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2106// DOWN on the window that doesn't have focus. Ensure no window received the
2107// onPointerDownOutsideFocus callback.
2108TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002109 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002111 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002112 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002113
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002114 ASSERT_TRUE(mDispatcher->waitForIdle());
2115 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002116}
2117
2118// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2119// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2120TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2121 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2122 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002123 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002124
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002125 ASSERT_TRUE(mDispatcher->waitForIdle());
2126 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002127}
2128
2129// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2130// DOWN on the window that already has focus. Ensure no window received the
2131// onPointerDownOutsideFocus callback.
2132TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2133 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002134 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2135 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002136 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002137 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002138 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002139
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002140 ASSERT_TRUE(mDispatcher->waitForIdle());
2141 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002142}
2143
chaviwaf87b3e2019-10-01 16:59:28 -07002144// These tests ensures we can send touch events to a single client when there are multiple input
2145// windows that point to the same client token.
2146class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2147 virtual void SetUp() override {
2148 InputDispatcherTest::SetUp();
2149
2150 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2151 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2152 ADISPLAY_ID_DEFAULT);
2153 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2154 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
2155 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2156 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002157 mWindow1->setFrame(Rect(0, 0, 100, 100));
2158
2159 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2160 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
2161 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2162 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002163 mWindow2->setFrame(Rect(100, 100, 200, 200));
2164
Arthur Hung72d8dc32020-03-28 00:48:39 +00002165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002166 }
2167
2168protected:
2169 sp<FakeWindowHandle> mWindow1;
2170 sp<FakeWindowHandle> mWindow2;
2171
2172 // Helper function to convert the point from screen coordinates into the window's space
2173 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
2174 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
2175 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
2176 return {x, y};
2177 }
2178
2179 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2180 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002181 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002182 InputEvent* event = window->consume();
2183
2184 ASSERT_NE(nullptr, event) << name.c_str()
2185 << ": consumer should have returned non-NULL event.";
2186
2187 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2188 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2189 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2190
2191 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2192 EXPECT_EQ(expectedAction, motionEvent.getAction());
2193
2194 for (size_t i = 0; i < points.size(); i++) {
2195 float expectedX = points[i].x;
2196 float expectedY = points[i].y;
2197
2198 EXPECT_EQ(expectedX, motionEvent.getX(i))
2199 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2200 << ", got " << motionEvent.getX(i);
2201 EXPECT_EQ(expectedY, motionEvent.getY(i))
2202 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2203 << ", got " << motionEvent.getY(i);
2204 }
2205 }
2206};
2207
2208TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2209 // Touch Window 1
2210 PointF touchedPoint = {10, 10};
2211 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2212
2213 NotifyMotionArgs motionArgs =
2214 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2215 ADISPLAY_ID_DEFAULT, {touchedPoint});
2216 mDispatcher->notifyMotion(&motionArgs);
2217 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2218
2219 // Release touch on Window 1
2220 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2221 ADISPLAY_ID_DEFAULT, {touchedPoint});
2222 mDispatcher->notifyMotion(&motionArgs);
2223 // consume the UP event
2224 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2225
2226 // Touch Window 2
2227 touchedPoint = {150, 150};
2228 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2229
2230 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2231 ADISPLAY_ID_DEFAULT, {touchedPoint});
2232 mDispatcher->notifyMotion(&motionArgs);
2233
2234 // Consuming from window1 since it's the window that has the InputReceiver
2235 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2236}
2237
2238TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2239 mWindow2->setWindowScale(0.5f, 0.5f);
2240
2241 // Touch Window 1
2242 PointF touchedPoint = {10, 10};
2243 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2244
2245 NotifyMotionArgs motionArgs =
2246 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2247 ADISPLAY_ID_DEFAULT, {touchedPoint});
2248 mDispatcher->notifyMotion(&motionArgs);
2249 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2250
2251 // Release touch on Window 1
2252 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2253 ADISPLAY_ID_DEFAULT, {touchedPoint});
2254 mDispatcher->notifyMotion(&motionArgs);
2255 // consume the UP event
2256 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2257
2258 // Touch Window 2
2259 touchedPoint = {150, 150};
2260 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2261
2262 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2263 ADISPLAY_ID_DEFAULT, {touchedPoint});
2264 mDispatcher->notifyMotion(&motionArgs);
2265
2266 // Consuming from window1 since it's the window that has the InputReceiver
2267 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2268}
2269
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002270TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2271 mWindow2->setWindowScale(0.5f, 0.5f);
2272
2273 // Touch Window 1
2274 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2275 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2276
2277 NotifyMotionArgs motionArgs =
2278 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2279 ADISPLAY_ID_DEFAULT, touchedPoints);
2280 mDispatcher->notifyMotion(&motionArgs);
2281 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2282
2283 // Touch Window 2
2284 int32_t actionPointerDown =
2285 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2286 touchedPoints.emplace_back(PointF{150, 150});
2287 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2288
2289 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2290 ADISPLAY_ID_DEFAULT, touchedPoints);
2291 mDispatcher->notifyMotion(&motionArgs);
2292
2293 // Consuming from window1 since it's the window that has the InputReceiver
2294 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2295}
2296
2297TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2298 mWindow2->setWindowScale(0.5f, 0.5f);
2299
2300 // Touch Window 1
2301 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2302 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2303
2304 NotifyMotionArgs motionArgs =
2305 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2306 ADISPLAY_ID_DEFAULT, touchedPoints);
2307 mDispatcher->notifyMotion(&motionArgs);
2308 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2309
2310 // Touch Window 2
2311 int32_t actionPointerDown =
2312 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2313 touchedPoints.emplace_back(PointF{150, 150});
2314 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2315
2316 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2317 ADISPLAY_ID_DEFAULT, touchedPoints);
2318 mDispatcher->notifyMotion(&motionArgs);
2319
2320 // Consuming from window1 since it's the window that has the InputReceiver
2321 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2322
2323 // Move both windows
2324 touchedPoints = {{20, 20}, {175, 175}};
2325 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2326 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2327
2328 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2329 ADISPLAY_ID_DEFAULT, touchedPoints);
2330 mDispatcher->notifyMotion(&motionArgs);
2331
2332 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2333}
2334
2335TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2336 mWindow1->setWindowScale(0.5f, 0.5f);
2337
2338 // Touch Window 1
2339 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2340 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2341
2342 NotifyMotionArgs motionArgs =
2343 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2344 ADISPLAY_ID_DEFAULT, touchedPoints);
2345 mDispatcher->notifyMotion(&motionArgs);
2346 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2347
2348 // Touch Window 2
2349 int32_t actionPointerDown =
2350 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2351 touchedPoints.emplace_back(PointF{150, 150});
2352 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2353
2354 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2355 ADISPLAY_ID_DEFAULT, touchedPoints);
2356 mDispatcher->notifyMotion(&motionArgs);
2357
2358 // Consuming from window1 since it's the window that has the InputReceiver
2359 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2360
2361 // Move both windows
2362 touchedPoints = {{20, 20}, {175, 175}};
2363 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2364 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2365
2366 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2367 ADISPLAY_ID_DEFAULT, touchedPoints);
2368 mDispatcher->notifyMotion(&motionArgs);
2369
2370 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2371}
2372
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002373class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2374 virtual void SetUp() override {
2375 InputDispatcherTest::SetUp();
2376
2377 mApplication = new FakeApplicationHandle();
2378 mApplication->setDispatchingTimeout(20ms);
2379 mWindow =
2380 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2381 mWindow->setFrame(Rect(0, 0, 30, 30));
2382 mWindow->setDispatchingTimeout(10ms);
2383 mWindow->setFocus(true);
2384 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2385 // window.
2386 mWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2387
2388 // Set focused application.
2389 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2390
2391 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2392 mWindow->consumeFocusEvent(true);
2393 }
2394
2395 virtual void TearDown() override {
2396 InputDispatcherTest::TearDown();
2397 mWindow.clear();
2398 }
2399
2400protected:
2401 sp<FakeApplicationHandle> mApplication;
2402 sp<FakeWindowHandle> mWindow;
2403 static constexpr PointF WINDOW_LOCATION = {20, 20};
2404
2405 void tapOnWindow() {
2406 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2407 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2408 WINDOW_LOCATION));
2409 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2410 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2411 WINDOW_LOCATION));
2412 }
2413};
2414
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002415// Send a tap and respond, which should not cause an ANR.
2416TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2417 tapOnWindow();
2418 mWindow->consumeMotionDown();
2419 mWindow->consumeMotionUp();
2420 ASSERT_TRUE(mDispatcher->waitForIdle());
2421 mFakePolicy->assertNotifyAnrWasNotCalled();
2422}
2423
2424// Send a regular key and respond, which should not cause an ANR.
2425TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
2426 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2427 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2428 ASSERT_TRUE(mDispatcher->waitForIdle());
2429 mFakePolicy->assertNotifyAnrWasNotCalled();
2430}
2431
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002432// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002433// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2434// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002435TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2436 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2437 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2438 WINDOW_LOCATION));
2439
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002440 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2441 ASSERT_TRUE(sequenceNum);
2442 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2443 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002444
2445 // The remaining lines are not really needed for the test, but kept as a sanity check
2446 mWindow->finishEvent(*sequenceNum);
2447 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2448 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002449 ASSERT_TRUE(mDispatcher->waitForIdle());
2450}
2451
2452// Send a key to the app and have the app not respond right away.
2453TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2454 // Inject a key, and don't respond - expect that ANR is called.
2455 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2456 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2457 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002458 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002459 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakouffaa2b12020-05-26 21:43:02 -07002460 ASSERT_TRUE(mDispatcher->waitForIdle());
2461}
2462
Siarhei Vishniakoue4623042020-03-25 16:16:40 -07002463// We have a focused application, but no focused window
2464TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
2465 mWindow->setFocus(false);
2466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2467 mWindow->consumeFocusEvent(false);
2468
2469 // taps on the window work as normal
2470 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2471 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2472 WINDOW_LOCATION));
2473 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2474 mDispatcher->waitForIdle();
2475 mFakePolicy->assertNotifyAnrWasNotCalled();
2476
2477 // Once a focused event arrives, we get an ANR for this application
2478 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2479 // injection times out (instead of failing).
2480 const int32_t result =
2481 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2482 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2483 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2484 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2485 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2486 ASSERT_TRUE(mDispatcher->waitForIdle());
2487}
2488
2489// We have a focused application, but no focused window
2490// If the policy wants to keep waiting on the focused window to be added, make sure
2491// that this timeout extension is honored and ANR is raised again.
2492TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
2493 mWindow->setFocus(false);
2494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2495 mWindow->consumeFocusEvent(false);
2496 const std::chrono::duration timeout = 5ms;
2497 mFakePolicy->setAnrTimeout(timeout);
2498
2499 // Once a focused event arrives, we get an ANR for this application
2500 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2501 // injection times out (instead of failing).
2502 const int32_t result =
2503 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2504 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2505 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2506 const std::chrono::duration appTimeout =
2507 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2508 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2509
2510 // After the extended time has passed, ANR should be raised again
2511 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2512
2513 // If we stop extending the timeout, dispatcher should go to idle.
2514 // Another ANR may be raised during this time
2515 mFakePolicy->setAnrTimeout(0ms);
2516 ASSERT_TRUE(mDispatcher->waitForIdle());
2517}
2518
2519// We have a focused application, but no focused window
2520TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
2521 mWindow->setFocus(false);
2522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2523 mWindow->consumeFocusEvent(false);
2524
2525 // Once a focused event arrives, we get an ANR for this application
2526 const int32_t result =
2527 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2528 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2529 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2530
2531 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2532 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2533
2534 // Future focused events get dropped right away
2535 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, injectKeyDown(mDispatcher));
2536 ASSERT_TRUE(mDispatcher->waitForIdle());
2537 mWindow->assertNoEvents();
2538}
2539
2540/**
2541 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2542 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2543 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2544 * the ANR mechanism should still work.
2545 *
2546 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2547 * DOWN event, while not responding on the second one.
2548 */
2549TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2550 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2551 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2552 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2553 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2554 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2555 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2556
2557 // Now send ACTION_UP, with identical timestamp
2558 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2559 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2560 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2561 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2562 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2563
2564 // We have now sent down and up. Let's consume first event and then ANR on the second.
2565 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2566 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2567 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2568}
2569
2570// If an app is not responding to a key event, gesture monitors should continue to receive
2571// new motion events
2572TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
2573 FakeMonitorReceiver monitor =
2574 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2575 true /*isGestureMonitor*/);
2576
2577 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
2578 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2579 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
2580
2581 // Stuck on the ACTION_UP
2582 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2583 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2584
2585 // New tap will go to the gesture monitor, but not to the window
2586 tapOnWindow();
2587 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2588 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2589
2590 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2591 mDispatcher->waitForIdle();
2592 mWindow->assertNoEvents();
2593 monitor.assertNoEvents();
2594}
2595
2596// If an app is not responding to a motion event, gesture monitors should continue to receive
2597// new motion events
2598TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
2599 FakeMonitorReceiver monitor =
2600 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2601 true /*isGestureMonitor*/);
2602
2603 tapOnWindow();
2604 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2605 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2606
2607 mWindow->consumeMotionDown();
2608 // Stuck on the ACTION_UP
2609 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2610 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2611
2612 // New tap will go to the gesture monitor, but not to the window
2613 tapOnWindow();
2614 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2615 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2616
2617 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2618 mDispatcher->waitForIdle();
2619 mWindow->assertNoEvents();
2620 monitor.assertNoEvents();
2621}
2622
2623// If a window is unresponsive, then you get anr. if the window later catches up and starts to
2624// process events, you don't get an anr. When the window later becomes unresponsive again, you
2625// get an ANR again.
2626// 1. tap -> block on ACTION_UP -> receive ANR
2627// 2. consume all pending events (= queue becomes healthy again)
2628// 3. tap again -> block on ACTION_UP again -> receive ANR second time
2629TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
2630 tapOnWindow();
2631
2632 mWindow->consumeMotionDown();
2633 // Block on ACTION_UP
2634 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2635 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2636 mWindow->consumeMotionUp(); // Now the connection should be healthy again
2637 mDispatcher->waitForIdle();
2638 mWindow->assertNoEvents();
2639
2640 tapOnWindow();
2641 mWindow->consumeMotionDown();
2642 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2643 mWindow->consumeMotionUp();
2644
2645 mDispatcher->waitForIdle();
2646 mWindow->assertNoEvents();
2647}
2648
2649// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
2650// is honored
2651TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
2652 const std::chrono::duration timeout = 5ms;
2653 mFakePolicy->setAnrTimeout(timeout);
2654
2655 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2656 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2657 WINDOW_LOCATION));
2658
2659 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2660 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
2661 mWindow->getToken());
2662
2663 // Since the policy wanted to extend ANR, make sure it is called again after the extension
2664 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2665 mFakePolicy->setAnrTimeout(0ms);
2666 std::this_thread::sleep_for(windowTimeout);
2667 // We are not checking if ANR has been called, because it may have been called again by the
2668 // time we set the timeout to 0
2669
2670 // When the policy finally says stop, we should get ACTION_CANCEL
2671 mWindow->consumeMotionDown();
2672 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2673 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2674 mWindow->assertNoEvents();
2675}
2676
2677/**
2678 * If a window is processing a motion event, and then a key event comes in, the key event should
2679 * not to to the focused window until the motion is processed.
2680 *
2681 * Warning!!!
2682 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2683 * and the injection timeout that we specify when injecting the key.
2684 * We must have the injection timeout (10ms) be smaller than
2685 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2686 *
2687 * If that value changes, this test should also change.
2688 */
2689TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
2690 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2692
2693 tapOnWindow();
2694 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2695 ASSERT_TRUE(downSequenceNum);
2696 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2697 ASSERT_TRUE(upSequenceNum);
2698 // Don't finish the events yet, and send a key
2699 // Injection will "succeed" because we will eventually give up and send the key to the focused
2700 // window even if motions are still being processed. But because the injection timeout is short,
2701 // we will receive INJECTION_TIMED_OUT as the result.
2702
2703 int32_t result =
2704 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2705 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2706 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2707 // Key will not be sent to the window, yet, because the window is still processing events
2708 // and the key remains pending, waiting for the touch events to be processed
2709 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2710 ASSERT_FALSE(keySequenceNum);
2711
2712 std::this_thread::sleep_for(500ms);
2713 // if we wait long enough though, dispatcher will give up, and still send the key
2714 // to the focused window, even though we have not yet finished the motion event
2715 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2716 mWindow->finishEvent(*downSequenceNum);
2717 mWindow->finishEvent(*upSequenceNum);
2718}
2719
2720/**
2721 * If a window is processing a motion event, and then a key event comes in, the key event should
2722 * not go to the focused window until the motion is processed.
2723 * If then a new motion comes in, then the pending key event should be going to the currently
2724 * focused window right away.
2725 */
2726TEST_F(InputDispatcherSingleWindowAnr,
2727 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
2728 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2729 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2730
2731 tapOnWindow();
2732 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2733 ASSERT_TRUE(downSequenceNum);
2734 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2735 ASSERT_TRUE(upSequenceNum);
2736 // Don't finish the events yet, and send a key
2737 // Injection is async, so it will succeed
2738 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2739 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
2740 ADISPLAY_ID_DEFAULT, INPUT_EVENT_INJECTION_SYNC_NONE));
2741 // At this point, key is still pending, and should not be sent to the application yet.
2742 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2743 ASSERT_FALSE(keySequenceNum);
2744
2745 // Now tap down again. It should cause the pending key to go to the focused window right away.
2746 tapOnWindow();
2747 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
2748 // the other events yet. We can finish events in any order.
2749 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
2750 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
2751 mWindow->consumeMotionDown();
2752 mWindow->consumeMotionUp();
2753 mWindow->assertNoEvents();
2754}
2755
2756class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
2757 virtual void SetUp() override {
2758 InputDispatcherTest::SetUp();
2759
2760 mApplication = new FakeApplicationHandle();
2761 mApplication->setDispatchingTimeout(10ms);
2762 mUnfocusedWindow =
2763 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
2764 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2765 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2766 // window.
2767 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
2768 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2769 InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH |
2770 InputWindowInfo::FLAG_SPLIT_TOUCH);
2771
2772 mFocusedWindow =
2773 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
2774 mFocusedWindow->setDispatchingTimeout(10ms);
2775 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
2776 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2777 InputWindowInfo::FLAG_SPLIT_TOUCH);
2778
2779 // Set focused application.
2780 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2781 mFocusedWindow->setFocus(true);
2782
2783 // Expect one focus window exist in display.
2784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2785 mFocusedWindow->consumeFocusEvent(true);
2786 }
2787
2788 virtual void TearDown() override {
2789 InputDispatcherTest::TearDown();
2790
2791 mUnfocusedWindow.clear();
2792 mFocusedWindow.clear();
2793 }
2794
2795protected:
2796 sp<FakeApplicationHandle> mApplication;
2797 sp<FakeWindowHandle> mUnfocusedWindow;
2798 sp<FakeWindowHandle> mFocusedWindow;
2799 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
2800 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
2801 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
2802
2803 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
2804
2805 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
2806
2807private:
2808 void tap(const PointF& location) {
2809 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2810 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2811 location));
2812 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2813 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2814 location));
2815 }
2816};
2817
2818// If we have 2 windows that are both unresponsive, the one with the shortest timeout
2819// should be ANR'd first.
2820TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
2821 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2822 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2823 FOCUSED_WINDOW_LOCATION))
2824 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2825 mFocusedWindow->consumeMotionDown();
2826 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2827 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2828 // We consumed all events, so no ANR
2829 ASSERT_TRUE(mDispatcher->waitForIdle());
2830 mFakePolicy->assertNotifyAnrWasNotCalled();
2831
2832 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2833 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2834 FOCUSED_WINDOW_LOCATION));
2835 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
2836 ASSERT_TRUE(unfocusedSequenceNum);
2837 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
2838 ASSERT_TRUE(focusedSequenceNum);
2839
2840 const std::chrono::duration timeout =
2841 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2842 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
2843 mFocusedWindow->getToken());
2844
2845 mFocusedWindow->finishEvent(*focusedSequenceNum);
2846 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
2847 ASSERT_TRUE(mDispatcher->waitForIdle());
2848}
2849
2850// If we have 2 windows with identical timeouts that are both unresponsive,
2851// it doesn't matter which order they should have ANR.
2852// But we should receive ANR for both.
2853TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
2854 // Set the timeout for unfocused window to match the focused window
2855 mUnfocusedWindow->setDispatchingTimeout(10ms);
2856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2857
2858 tapOnFocusedWindow();
2859 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
2860 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData1 =
2861 mFakePolicy->getNotifyAnrData(10ms);
2862 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData2 =
2863 mFakePolicy->getNotifyAnrData(0ms);
2864
2865 // We don't know which window will ANR first. But both of them should happen eventually.
2866 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
2867 mFocusedWindow->getToken() == anrData2.second);
2868 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
2869 mUnfocusedWindow->getToken() == anrData2.second);
2870
2871 ASSERT_TRUE(mDispatcher->waitForIdle());
2872 mFakePolicy->assertNotifyAnrWasNotCalled();
2873}
2874
2875// If a window is already not responding, the second tap on the same window should be ignored.
2876// We should also log an error to account for the dropped event (not tested here).
2877// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
2878TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
2879 tapOnFocusedWindow();
2880 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2881 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2882 // Receive the events, but don't respond
2883 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
2884 ASSERT_TRUE(downEventSequenceNum);
2885 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
2886 ASSERT_TRUE(upEventSequenceNum);
2887 const std::chrono::duration timeout =
2888 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2889 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
2890 mFocusedWindow->getToken());
2891
2892 // Tap once again
2893 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
2894 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2895 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2896 FOCUSED_WINDOW_LOCATION));
2897 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2898 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2899 FOCUSED_WINDOW_LOCATION));
2900 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
2901 // valid touch target
2902 mUnfocusedWindow->assertNoEvents();
2903
2904 // Consume the first tap
2905 mFocusedWindow->finishEvent(*downEventSequenceNum);
2906 mFocusedWindow->finishEvent(*upEventSequenceNum);
2907 ASSERT_TRUE(mDispatcher->waitForIdle());
2908 // The second tap did not go to the focused window
2909 mFocusedWindow->assertNoEvents();
2910 // should not have another ANR after the window just became healthy again
2911 mFakePolicy->assertNotifyAnrWasNotCalled();
2912}
2913
2914// If you tap outside of all windows, there will not be ANR
2915TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
2916 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2917 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2918 LOCATION_OUTSIDE_ALL_WINDOWS));
2919 ASSERT_TRUE(mDispatcher->waitForIdle());
2920 mFakePolicy->assertNotifyAnrWasNotCalled();
2921}
2922
2923// Since the focused window is paused, tapping on it should not produce any events
2924TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
2925 mFocusedWindow->setPaused(true);
2926 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2927
2928 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2929 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2930 FOCUSED_WINDOW_LOCATION));
2931
2932 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
2933 ASSERT_TRUE(mDispatcher->waitForIdle());
2934 // Should not ANR because the window is paused, and touches shouldn't go to it
2935 mFakePolicy->assertNotifyAnrWasNotCalled();
2936
2937 mFocusedWindow->assertNoEvents();
2938 mUnfocusedWindow->assertNoEvents();
2939}
2940
2941/**
2942 * If a window is processing a motion event, and then a key event comes in, the key event should
2943 * not to to the focused window until the motion is processed.
2944 * If a different window becomes focused at this time, the key should go to that window instead.
2945 *
2946 * Warning!!!
2947 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2948 * and the injection timeout that we specify when injecting the key.
2949 * We must have the injection timeout (10ms) be smaller than
2950 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2951 *
2952 * If that value changes, this test should also change.
2953 */
2954TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
2955 // Set a long ANR timeout to prevent it from triggering
2956 mFocusedWindow->setDispatchingTimeout(2s);
2957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
2958
2959 tapOnUnfocusedWindow();
2960 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
2961 ASSERT_TRUE(downSequenceNum);
2962 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
2963 ASSERT_TRUE(upSequenceNum);
2964 // Don't finish the events yet, and send a key
2965 // Injection will succeed because we will eventually give up and send the key to the focused
2966 // window even if motions are still being processed.
2967
2968 int32_t result =
2969 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
2970 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
2971 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
2972 // Key will not be sent to the window, yet, because the window is still processing events
2973 // and the key remains pending, waiting for the touch events to be processed
2974 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
2975 ASSERT_FALSE(keySequenceNum);
2976
2977 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
2978 mFocusedWindow->setFocus(false);
2979 mUnfocusedWindow->setFocus(true);
2980 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
2981
2982 // Focus events should precede the key events
2983 mUnfocusedWindow->consumeFocusEvent(true);
2984 mFocusedWindow->consumeFocusEvent(false);
2985
2986 // Finish the tap events, which should unblock dispatcher
2987 mUnfocusedWindow->finishEvent(*downSequenceNum);
2988 mUnfocusedWindow->finishEvent(*upSequenceNum);
2989
2990 // Now that all queues are cleared and no backlog in the connections, the key event
2991 // can finally go to the newly focused "mUnfocusedWindow".
2992 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2993 mFocusedWindow->assertNoEvents();
2994 mUnfocusedWindow->assertNoEvents();
2995}
2996
2997// When the touch stream is split across 2 windows, and one of them does not respond,
2998// then ANR should be raised and the touch should be canceled for the unresponsive window.
2999// The other window should not be affected by that.
3000TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3001 // Touch Window 1
3002 NotifyMotionArgs motionArgs =
3003 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3004 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3005 mDispatcher->notifyMotion(&motionArgs);
3006 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3007 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3008
3009 // Touch Window 2
3010 int32_t actionPointerDown =
3011 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3012
3013 motionArgs =
3014 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3015 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3016 mDispatcher->notifyMotion(&motionArgs);
3017
3018 const std::chrono::duration timeout =
3019 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3020 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3021 mFocusedWindow->getToken());
3022
3023 mUnfocusedWindow->consumeMotionDown();
3024 mFocusedWindow->consumeMotionDown();
3025 // Focused window may or may not receive ACTION_MOVE
3026 // But it should definitely receive ACTION_CANCEL due to the ANR
3027 InputEvent* event;
3028 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3029 ASSERT_TRUE(moveOrCancelSequenceNum);
3030 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3031 ASSERT_NE(nullptr, event);
3032 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3033 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3034 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3035 mFocusedWindow->consumeMotionCancel();
3036 } else {
3037 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3038 }
3039
3040 ASSERT_TRUE(mDispatcher->waitForIdle());
3041 mUnfocusedWindow->assertNoEvents();
3042 mFocusedWindow->assertNoEvents();
3043}
3044
Siarhei Vishniakou265ab012020-09-08 19:43:33 -05003045/**
3046 * If we have no focused window, and a key comes in, we start the ANR timer.
3047 * The focused application should add a focused window before the timer runs out to prevent ANR.
3048 *
3049 * If the user touches another application during this time, the key should be dropped.
3050 * Next, if a new focused window comes in, without toggling the focused application,
3051 * then no ANR should occur.
3052 *
3053 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3054 * but in some cases the policy may not update the focused application.
3055 */
3056TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3057 sp<FakeApplicationHandle> focusedApplication = new FakeApplicationHandle();
3058 focusedApplication->setDispatchingTimeout(60ms);
3059 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3060 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3061 mFocusedWindow->setFocus(false);
3062
3063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3064 mFocusedWindow->consumeFocusEvent(false);
3065
3066 // Send a key. The ANR timer should start because there is no focused window.
3067 // 'focusedApplication' will get blamed if this timer completes.
3068 // Key will not be sent anywhere because we have no focused window. It will remain pending.
3069 int32_t result =
3070 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
3071 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
3072 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
3073
3074 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3075 // then the injected touches won't cause the focused event to get dropped.
3076 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3077 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3078 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3079 // For this test, it means that the key would get delivered to the window once it becomes
3080 // focused.
3081 std::this_thread::sleep_for(10ms);
3082
3083 // Touch unfocused window. This should force the pending key to get dropped.
3084 NotifyMotionArgs motionArgs =
3085 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3086 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3087 mDispatcher->notifyMotion(&motionArgs);
3088
3089 // We do not consume the motion right away, because that would require dispatcher to first
3090 // process (== drop) the key event, and by that time, ANR will be raised.
3091 // Set the focused window first.
3092 mFocusedWindow->setFocus(true);
3093 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3094 mFocusedWindow->consumeFocusEvent(true);
3095 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3096 // to another application. This could be a bug / behaviour in the policy.
3097
3098 mUnfocusedWindow->consumeMotionDown();
3099
3100 ASSERT_TRUE(mDispatcher->waitForIdle());
3101 // Should not ANR because we actually have a focused window. It was just added too slowly.
3102 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3103}
3104
Garfield Tane84e6f92019-08-29 17:28:41 -07003105} // namespace android::inputdispatcher